//////////
//
//  QuickTime for Java SDK Sample Code
//
//  Usage subject to restrictions in SDK License Agreement
//  Copyright: © 1996-1999 Apple Computer, Inc.
//
//	Contains:	Code to display a QuickTime movie in a window. When the
//              user presses the right arrow the movie is stepped forward.
//              When the user pressed the left arrow key the movie is stepped
//              backward. The movie stepping is accomplished through the use
//              of the code in the FrameStepper class (see the source file
//              FrameStepper.java).
//
//////////

import java.awt.*;
import java.awt.event.*;
import java.io.*;

import quicktime.std.StdQTConstants;
import quicktime.*;
import quicktime.qd.*;
import quicktime.io.*;
import quicktime.std.image.*;
import quicktime.std.movies.*;

import quicktime.app.players.*;
import quicktime.app.QTFactory;
import quicktime.app.time.*;
import quicktime.app.image.*;
import quicktime.app.display.*;
import quicktime.app.anim.*;
import quicktime.app.spaces.*;
import quicktime.app.actions.*;

//////////
//
// KeyBoardController
//
// Contains code which lets us display our QuickTime content within a java.awt
// display space using a QTCanvas. We first call QTSession.open to setup our drawing
// environment. This is required before any QuickTime Java classes can be used.
// Next, we'll use a Compositor to compose our image from two sources. We'll
// add to our Compositor as members an ImagePresenter to display our background
// image, and a MoviePresenter to display our movie. The QuickTime graphics importers
// are used to retrieve the actual movie which will be displayed. Lastly, the services
// of the KBDController are used to perform the stepping of the movie.
//
//////////

public class KeyBoardController extends Frame implements StdQTConstants, QDConstants {

	Label label1;

	public static void main(String args[]) {
		try { 
		    
		    // let's first initialize quicktime - this is required
		    // before we can call any of the QuickTime for Java methods
			QTSession.open();
			
			KeyBoardController kbdController = new KeyBoardController("Movie Frame Stepper");
			
			// lay out and resize the Frame to the size of the Movie
			kbdController.pack();
			kbdController.show();
			kbdController.toFront();	
			
		} catch (Exception e) {
			e.printStackTrace();
			QTSession.close();
		}
	
	}
	
	KeyBoardController(String title) throws Exception {
	    
		super (title);

        // let's create a QTCanvas object to enable us to display
        // QuickTime content within Java. The QTCanvas is a subclass
        // of the java.awt.Canvas and represents primarily a way to
        // gain access to the underlying native graphics structure of
        // the platform
		QTCanvas myQTCanvas = new QTCanvas(QTCanvas.kInitialSize, 0.5f, 0.5f);
		add("Center", myQTCanvas);

		addWindowListener(new WindowAdapter() {
			public void windowClosing (WindowEvent e) {
			    // terminate QuickTime - we must call this for
			    // each call to QTSession.open
				QTSession.close();
				dispose();
			}
			
			public void windowClosed (WindowEvent e) { 
				System.exit(0);
			}
		});

		QDRect qdr = new QDRect(300,300);
		// The QDGraphics object is the destination where we will draw
		QDGraphics gw = new QDGraphics (qdr);
		// We'll use a Compositor to compose our image from two sources. We'll
		// add to it as members our ImagePresenter to display our background
		// image, and a MoviePresenter to display our movie.
		Compositor comp = new Compositor (gw, QDColor.gray, 20, 1);
		
		// Use the QuickTime graphics importers to import our
		// jpeg window background image
		GraphicsImporterDrawer if1 = new GraphicsImporterDrawer (new QTFile (QTFactory.findAbsolutePath ("pics/house.jpg")));
		if1.setDisplayBounds (qdr);
		// The ImagePresenter is used to perform rendering of our image data
		ImagePresenter id = ImagePresenter.fromGraphicsImporterDrawer (if1);
		id.setGraphicsMode (new GraphicsMode (blend, QDColor.gray));
		// Our compositor will make use of our ImagePresenter to perform
		// the actual rendering
		comp.addMember (id, 1);

        // get the QuickTime movie which we'll use to perform
        // our frame stepping operations
		QTFile qtf = new QTFile (QTFactory.findAbsolutePath ("jumps.mov"));		
		OpenMovieFile movieFile = OpenMovieFile.asRead(qtf);
		Movie mv = Movie.fromFile (movieFile);
		// Use a MoviePresentor to render our movie into
		// an offscreen QDGraphics object
		MoviePresenter mvp = new MoviePresenter(mv);		
		mvp.setLocation (80, 80);
		// Tell the Compositor one of our image sources will come from
		// our MoviePresentor
		comp.addMember (mvp, 2);

        // Use a KBDController to handle the user key presses
		KBDController keyController = new KBDController(mvp);				
		comp.addController(keyController);

        // Let's associate our Drawable object with our QTCanvas
		myQTCanvas.setClient (comp, true);
		// we want our movie to play forward with a normal rate of 1
		comp.getTimer().setRate(1);
	}	
}

//////////
//
// KBDController
//
// This class contains code to handle user key presses. Key
// presses of the left/right arrow keys will result in calls to the
// FrameStepper class to step through our QuickTime movie. Key
// presses of the space bar will give the use the opportunity to
// export the current frame as an image file. The QuickTime graphics
// exporters are used to perform the export operation.
//
//////////

class KBDController implements ListenerController, KeyListener {

    private FrameStepper        frameStep;
    private MoviePresenter      moviePresenter;
    private Movie               theMovie;
    private GraphicsExporter    graphExp;
    private QDGraphics          offscreen;

	KBDController (MoviePresenter mp) {
	    
        this.frameStep      = new FrameStepper();
        this.moviePresenter = mp;
        this.theMovie       = mp.getMovie();
	    this.offscreen      = mp.getOffscreenBuffer();
        try {
            // We'll use the jpeg graphics exporter to allow the user to export
            // our movie samples into other formats
            this.graphExp = new GraphicsExporter(StdQTConstants.kQTFileTypeJPEG);
        }
        catch (Exception ex) {
            ex.printStackTrace();
            QTSession.close();
		}

	}
		
	public void addedToSpace (Space s) {}

	public void removedFromSpace () {}
		
	public void addedTo (Object interest){
		if (interest instanceof Component)
			((Component)interest).addKeyListener (this);	
	}	
	public void removedFrom (Object interest){
		if (interest instanceof Component)
			((Component)interest).removeKeyListener (this);	
	}
	public void keyPressed (KeyEvent e) {
			switch (e.getKeyCode()) {

				case KeyEvent.VK_SPACE:
				
				    // export the current movie sample as a jpeg file
				    
                    try {
                        // set the input (source) gworld for our export operation - in
                        // this case, it's the current movie sample
                        graphExp.setInputGWorld(offscreen);
                        // now ask the user to specify the location of the export image
                        FileDialog ofd = new FileDialog (new Frame(), "Export Movie sample to...", FileDialog.SAVE);
                        ofd.setFile("VideoSample.jpg");
                        ofd.show();
                        if (ofd.getFile() == null)
	                        break;
	                    // create the new export image file in the desired location
                        QTFile outFile = new QTFile (ofd.getDirectory() + ofd.getFile());
                        // tell the graphics exporter which file to use as the destination
                        // of the export operation
                        graphExp.setOutputFile(outFile);
                        // do the export operation
                        graphExp.doExport();
                    }
                    catch (Exception exc) {
			            exc.printStackTrace();
			            QTSession.close();
                    }
					break;

				case KeyEvent.VK_UP:
					break;

				case KeyEvent.VK_DOWN:
					break;

				case KeyEvent.VK_LEFT:
				
				    // draw the previous movie sample
                    frameStep.DrawVideoSamplePrev(theMovie);
                    
					break;

				case KeyEvent.VK_RIGHT:
				
				    // draw the next movie sample
                    frameStep.DrawVideoSampleNext(theMovie);
                    
					break;					
			}
	}
	public void keyReleased (KeyEvent e) {}
	public void keyTyped (KeyEvent e) {}
}	
	
