/*
 * @(#)JpegImagesToMovie.java	1.3 01/03/13
 *
 * Copyright (c) 1999-2001 Sun Microsystems, Inc. All Rights Reserved.
 *
 * Sun grants you ("Licensee") a non-exclusive, royalty free, license to use,
 * modify and redistribute this software in source and binary code form,
 * provided that i) this copyright notice and license appear on all copies of
 * the software; and ii) Licensee does not utilize the software in a manner
 * which is disparaging to Sun.
 *
 * This software is provided "AS IS," without a warranty of any kind. ALL
 * EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND WARRANTIES, INCLUDING ANY
 * IMPLIED WARRANTY OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE OR
 * NON-INFRINGEMENT, ARE HEREBY EXCLUDED. SUN AND ITS LICENSORS SHALL NOT BE
 * LIABLE FOR ANY DAMAGES SUFFERED BY LICENSEE AS A RESULT OF USING, MODIFYING
 * OR DISTRIBUTING THE SOFTWARE OR ITS DERIVATIVES. IN NO EVENT WILL SUN OR ITS
 * LICENSORS BE LIABLE FOR ANY LOST REVENUE, PROFIT OR DATA, OR FOR DIRECT,
 * INDIRECT, SPECIAL, CONSEQUENTIAL, INCIDENTAL OR PUNITIVE DAMAGES, HOWEVER
 * CAUSED AND REGARDLESS OF THE THEORY OF LIABILITY, ARISING OUT OF THE USE OF
 * OR INABILITY TO USE SOFTWARE, EVEN IF SUN HAS BEEN ADVISED OF THE
 * POSSIBILITY OF SUCH DAMAGES.
 *
 * This software is not designed or intended for use in on-line control of
 * aircraft, air traffic, aircraft navigation or aircraft communications; or in
 * the design, construction, operation or maintenance of any nuclear
 * facility. Licensee represents and warrants that it will not use or
 * redistribute the Software for such purposes.
 */

import javax.media.*;
import javax.media.control.*;
import javax.media.protocol.*;
import javax.media.datasink.*;
import javax.media.format.VideoFormat;

/**
 * Takes a list of JPEG image files and converts them into a
 * QuickTime movie.
 */
public class JPGAnimator implements ControllerListener, DataSinkListener {
	
	private Processor processor;
	private DataSink dsink;
	private MediaLocator outML;
	private IActions actions;
	
	public JPGAnimator(String outputFile, String imagesDirectory)
	{
		actions = new Actions();
		
		try
		{
			actions.loadImagesFromDirectory(imagesDirectory);
			outML = actions.createMediaLocator(outputFile);
		}
		catch(Exception e)
		{
			e.printStackTrace();
			System.exit(0);
		}
	}
	
	public void start(int width, int height, int frameRate)
	{
		try
		{
			VideoFormat vFormat = actions.createVideoFormatJPEGEncoding(
					width, height, Format.NOT_SPECIFIED,
					Format.byteArray, frameRate);
			
			ImageDataSource ids = new ImageDataSource(vFormat, actions);
			processor = actions.createProcessor(ids);
		}
		catch (Exception e)
		{
			e.printStackTrace();
			System.exit(0);
		}
		processor.addControllerListener(this);
		processor.configure();
	}

	/**
	 * Controller Listener.
	 */
	public void controllerUpdate(ControllerEvent evt)
	{
		if (evt instanceof ConfigureCompleteEvent)
		{
			System.out.println("SYSTEM configured.");
			
			processor.setContentDescriptor(new ContentDescriptor(FileTypeDescriptor.QUICKTIME));
			// Query for the processor for supported formats.
			// Then set it on the processor.
			TrackControl tcs[] = processor.getTrackControls();
			Format f[] = tcs[0].getSupportedFormats();
			if (f == null || f.length <= 0)
			{
				System.out.println("- The mux does not support the input format: "+ tcs[0].getFormat());
				System.exit(0);
			}
			tcs[0].setFormat(f[0]);
			System.out.println("+ Setting the track format to: " + f[0]);

			processor.realize();		
		}
		else if(evt instanceof RealizeCompleteEvent)
		{
			System.out.println("SYSTEM realized: creating DataSink.");	
			try
			{
				dsink = actions.createDataSink(processor, outML);
				dsink.open();
				dsink.addDataSinkListener(this);
				processor.start();
				dsink.start();
			}
			catch (Exception e)
			{
				e.printStackTrace();
				System.exit(0);
			}
			processor.prefetch();
		}
		else if (evt instanceof ResourceUnavailableEvent)
		{
			System.out.println("SYSTEM resourceUnavailable.");
			System.exit(0);
		}
		else if (evt instanceof EndOfMediaEvent)
		{
			evt.getSourceController().stop();
			evt.getSourceController().close();
		}
	}

	/**
	 * Event handler for the file writer.
	 */
	public void dataSinkUpdate(DataSinkEvent evt)
	{
		if (evt instanceof EndOfStreamEvent)
		{
			try
			{
				dsink.close();
			}
			catch (Exception e)
			{
				e.printStackTrace();
				System.exit(0);
			}
			processor.removeControllerListener(this);
			System.out.println();	
			System.out.println();	
			System.out.println("END!!!!!");	
		}
		else if (evt instanceof DataSinkErrorEvent)
		{
			System.out.println("SYSTEM DataSink error.");
			System.exit(0);
		}
	}

	public static void main(String args[])
	{
		if (args.length != 5)
			prUsage();

		int width = Integer.parseInt(args[0]); 
		int height = Integer.parseInt(args[1]); 

		if (width < 0 || height < 0)
			width = height = 100;
		
		int frameRate = Integer.parseInt(args[2]);
		if (frameRate < 1)
			frameRate = 1;

		String outputURL = args[3];
		if (!outputURL.endsWith(".mov") && !outputURL.endsWith(".MOV"))
		{
			System.out.println("The output file extension should end with a .mov extension");
			prUsage();
		}

		String imagesDirectory = args[4];

		JPGAnimator animator = new JPGAnimator(outputURL, imagesDirectory);
		animator.start(width, height, frameRate);
	}

	static void prUsage()
	{
		System.out.println("Usage: java JPGAnimator <width> <height> <frame rate> <output URL> <directory> ...");
		System.exit(0);
	}
}
