001         package com.croftsoft.apps.midi;
002         
003         import java.applet.*;
004         import java.awt.*;
005         import java.awt.event.*;
006         import java.awt.geom.*;
007         import java.io.*;
008         import java.net.URL;
009         import java.util.*;
010         import javax.sound.midi.*;
011         import javax.swing.*;
012         import javax.swing.event.*;
013    
014         import com.croftsoft.core.animation.*;
015         import com.croftsoft.core.animation.animator.*;
016         import com.croftsoft.core.animation.painter.*;
017         import com.croftsoft.core.io.SerializableLib;
018         import com.croftsoft.core.jnlp.JnlpLib;
019         import com.croftsoft.core.lang.lifecycle.*;
020    
021         /*********************************************************************
022         * MIDI demo.
023         *
024         * @version
025         *   2003-04-12
026         * @since
027         *   2003-04-12
028         * @author
029         *   <a href="https://www.croftsoft.com/">David Wallace Croft</a>
030         *********************************************************************/
031    
032         public final class  Main
033           extends AnimatedApplet
034         //////////////////////////////////////////////////////////////////////
035         //////////////////////////////////////////////////////////////////////
036         {
037    
038         private static final String  VERSION
039           = "2003-04-12";
040    
041         private static final String  TITLE
042           = "CroftSoft MIDI";
043    
044         private static final String  APPLET_INFO
045           = "\n" + TITLE + "\n"
046           + "Copyright 2003 CroftSoft Inc\n"
047           + "https://www.croftsoft.com/\n"
048           + "Version " + VERSION + "\n"
049           + "Licensed under the Academic Free License version 1.2\n";
050    
051         //////////////////////////////////////////////////////////////////////
052         // frame constants
053         //////////////////////////////////////////////////////////////////////
054    
055         private static final String  FRAME_TITLE
056           = TITLE;
057    
058         private static final String  FRAME_ICON_FILENAME
059           = "/images/croftsoft.png";
060           
061         private static final Dimension  FRAME_SIZE
062           = null;
063    
064         private static final String  SHUTDOWN_CONFIRMATION_PROMPT
065           = "Close " + TITLE + "?";
066    
067         //////////////////////////////////////////////////////////////////////
068         // animation constants
069         //////////////////////////////////////////////////////////////////////
070    
071         /** frames per second */
072         private static final double  FRAME_RATE = 30.0;
073    
074         private static final Color   BACKGROUND_COLOR
075           = Color.BLACK;
076    
077         private static final Color   FOREGROUND_COLOR
078           = Color.BLUE;
079    
080         private static final Font    FONT
081           = new Font ( "Arioso", Font.BOLD, 20 );
082    
083         private static final Cursor  CURSOR
084           = new Cursor ( Cursor.CROSSHAIR_CURSOR );
085    
086         private static final long  DELAY = 2000;
087    
088         private static int  DELTA_X = 1;
089    
090         private static int  DELTA_Y = 1;
091    
092         private static String  SOUNDBANK_URL_NAME
093           = "http://java.sun.com/products/java-media/sound/soundbanks.html";
094    
095         //////////////////////////////////////////////////////////////////////
096         // persistence constants
097         //////////////////////////////////////////////////////////////////////
098    
099    
100         //////////////////////////////////////////////////////////////////////
101         // instance variables
102         //////////////////////////////////////////////////////////////////////
103    
104         private Sequencer        sequencer;
105    
106         private Synthesizer      synthesizer;
107    
108         private Instrument  [ ]  instruments;
109    
110         private MidiChannel [ ]  midiChannels;
111    
112         private int              noteNumber;
113    
114         private long             previousTime;
115    
116         private boolean          noteOn;
117    
118         private TextAnimator     textAnimator;
119    
120         private Random           random;
121    
122         private boolean          started;
123    
124         //////////////////////////////////////////////////////////////////////
125         //////////////////////////////////////////////////////////////////////
126    
127         public static void  main ( String [ ]  args )
128         //////////////////////////////////////////////////////////////////////
129         {
130           if ( args.length < 1 )
131           {
132             launch ( new Main ( ) );
133    
134             return;
135           }
136    
137           // Test of playing a MIDI file using AudioClip
138    
139           AudioClip  audioClip = Applet.newAudioClip (
140             Main.class.getClassLoader ( ).getResource ( args [ 0 ] ) );
141    
142           audioClip.loop ( );
143         }
144    
145         private static AnimationInit  createAnimationInit ( )
146         //////////////////////////////////////////////////////////////////////
147         {
148           AnimationInit  animationInit = new AnimationInit ( );
149    
150           animationInit.setAppletInfo ( APPLET_INFO );
151    
152           animationInit.setForegroundColor ( BACKGROUND_COLOR );
153    
154           animationInit.setCursor ( CURSOR );
155    
156           animationInit.setFont ( FONT );
157    
158           animationInit.setForegroundColor ( FOREGROUND_COLOR );
159    
160           animationInit.setFrameIconFilename ( FRAME_ICON_FILENAME );
161    
162           animationInit.setFrameSize ( FRAME_SIZE );
163    
164           animationInit.setFrameTitle ( FRAME_TITLE );
165    
166           animationInit.setShutdownConfirmationPrompt (
167             SHUTDOWN_CONFIRMATION_PROMPT );
168    
169           return animationInit;
170         }
171    
172         //////////////////////////////////////////////////////////////////////
173         //////////////////////////////////////////////////////////////////////
174    
175         public  Main ( )
176         //////////////////////////////////////////////////////////////////////
177         {
178           super ( createAnimationInit ( ) );
179         }
180    
181         //////////////////////////////////////////////////////////////////////
182         // interface Lifecycle methods
183         //////////////////////////////////////////////////////////////////////
184    
185         public void  init ( )
186         //////////////////////////////////////////////////////////////////////
187         {
188           super.init ( );
189    
190           // persistent data
191    
192    /*
193           try
194           {
195             userData = ( UserData ) SerializableLib.load (
196               LATEST_FILENAME,
197               BACKUP_FILENAME,
198               FILE_CONTENTS_SPEC,
199               ( Applet ) this,
200               PERSISTENCE_KEY,
201               getClass ( ).getClassLoader ( ),
202               RESOURCE_PATH_FILENAME );
203           }
204           catch ( Exception  ex )
205           {
206             ex.printStackTrace ( );
207           }
208    
209           if ( userData == null )
210           {
211             userData = new UserData ( );
212           }
213    */
214           addComponentPainter ( new ColorPainter ( BACKGROUND_COLOR ) );
215    
216           textAnimator = new TextAnimator ( );
217    
218           textAnimator.setText ( TITLE );
219    
220           textAnimator.setDeltaX ( DELTA_X );
221    
222           textAnimator.setDeltaY ( DELTA_Y );
223    
224           addComponentAnimator ( textAnimator );
225    
226           random = new Random ( );
227    
228           try
229           {
230             sequencer = MidiSystem.getSequencer ( );
231    
232             synthesizer = MidiSystem.getSynthesizer ( );
233    
234             synthesizer.open ( );
235    
236             Soundbank  soundbank = synthesizer.getDefaultSoundbank ( );
237    
238             if ( soundbank != null )
239             {
240               System.out.println ( "Using soundbank instruments..." );
241    
242               instruments = soundbank.getInstruments ( );
243             }
244             else
245             {
246               System.out.println ( "Using synthesizer instruments..." );
247    
248               instruments = synthesizer.getAvailableInstruments ( );
249             }
250    
251             midiChannels = synthesizer.getChannels ( );
252    
253             if ( instruments.length < 1 )
254             {
255               textAnimator.setText ( SOUNDBANK_URL_NAME );
256    
257               URL  soundbankURL = new URL ( SOUNDBANK_URL_NAME );
258    
259               try
260               {
261                 getAppletContext ( ).showDocument ( soundbankURL, "_blank" );
262               }
263               catch ( Exception  ex )
264               {
265                 try
266                 {
267                   JnlpLib.showDocument ( soundbankURL );
268                 }
269                 catch ( Exception  ex2 )
270                 {
271                 }
272               }
273             }
274           }
275           catch ( Exception  ex )
276           {
277             ex.printStackTrace ( );
278    
279             throw new InitializationException ( ex );
280           }
281         }
282    
283         public void  update ( JComponent  component )
284         //////////////////////////////////////////////////////////////////////
285         {
286           super.update ( component );
287    
288           if ( !started
289            || instruments.length < 1 )
290           {
291             return;
292           }
293    
294           if ( noteOn )
295           {
296             long  currentTime = System.currentTimeMillis ( );
297    
298             if ( previousTime + DELAY >= currentTime )
299             {
300               return;
301             }
302    
303             previousTime = currentTime;
304    
305             midiChannels [ 0 ].noteOff ( noteNumber );
306    
307             noteOn = false;
308           }
309           else
310           {
311             noteNumber = random.nextInt ( 128 );
312    
313             int  instrumentIndex = random.nextInt ( instruments.length );
314    
315             Instrument  instrument = instruments [ instrumentIndex ];
316    
317             textAnimator.setText (
318               instrument.getName ( ) + " " + noteNumber );
319    
320             synthesizer.loadInstrument ( instrument );
321    
322             midiChannels [ 0 ].programChange ( instrumentIndex );
323    
324             int  velocity = 64;
325    
326             midiChannels [ 0 ].noteOn ( noteNumber, velocity );
327    
328             noteOn = true;
329           }
330         }
331    
332         public void  start ( )
333         //////////////////////////////////////////////////////////////////////
334         {
335           started = true;
336    
337           super.start ( );
338         }
339    
340         public void  stop ( )
341         //////////////////////////////////////////////////////////////////////
342         {
343           started = false;
344    
345           if ( noteOn )
346           {
347             midiChannels [ 0 ].noteOff ( noteNumber );
348    
349             noteOn = false;
350           }
351    
352           super.stop ( );
353         }
354    
355         public void  destroy ( )
356         //////////////////////////////////////////////////////////////////////
357         {
358           synthesizer.close ( );
359    
360           sequencer.close ( );
361    
362    /*
363           try
364           {
365             SerializableLib.save (
366               userData,
367               LATEST_FILENAME,
368               BACKUP_FILENAME,
369               FILE_CONTENTS_SPEC,
370               ( Applet ) this,
371               PERSISTENCE_KEY );
372           }
373           catch ( Exception  ex )
374           {
375             ex.printStackTrace ( );
376           }
377    */
378    
379           super.destroy ( );
380         }
381    
382         //////////////////////////////////////////////////////////////////////
383         //////////////////////////////////////////////////////////////////////
384         }