//package kr.util.sample;
//
//import java.io.File;
//import java.io.IOException;
//import java.net.MalformedURLException;
//
//import javax.media.Clock;
//import javax.media.Codec;
//import javax.media.ConfigureCompleteEvent;
//import javax.media.Control;
//import javax.media.ControllerEvent;
//import javax.media.ControllerListener;
//import javax.media.DataSink;
//import javax.media.EndOfMediaEvent;
//import javax.media.Format;
//import javax.media.IncompatibleSourceException;
//import javax.media.Manager;
//import javax.media.MediaLocator;
//import javax.media.MediaTimeSetEvent;
//import javax.media.NotRealizedError;
//import javax.media.Owned;
//import javax.media.Player;
//import javax.media.PrefetchCompleteEvent;
//import javax.media.Processor;
//import javax.media.RealizeCompleteEvent;
//import javax.media.ResourceUnavailableEvent;
//import javax.media.StopAtTimeEvent;
//import javax.media.Time;
//import javax.media.control.QualityControl;
//import javax.media.control.TrackControl;
//import javax.media.datasink.DataSinkErrorEvent;
//import javax.media.datasink.DataSinkEvent;
//import javax.media.datasink.DataSinkListener;
//import javax.media.datasink.EndOfStreamEvent;
//import javax.media.format.AudioFormat;
//import javax.media.format.VideoFormat;
//import javax.media.protocol.ContentDescriptor;
//import javax.media.protocol.DataSource;
//import javax.media.protocol.FileTypeDescriptor;
//
//import kr.util.Util;
//import com.sun.media.format.WavAudioFormat;
//
//import kr.util.audio.AudioClip;
//import kr.util.audio.MemAudioClip;
//import kr.util.audio.WritableAudioClip;
//import kr.util.sample.jmf.AudioClipDataSource;
//import kr.util.sample.jmf.ByteDataDataSink;
//
//public class JMFManager implements ControllerListener, DataSinkListener {
//	
//	static
//	{
//		WavAudioFormat.formatMapper.put(new Integer(0x69), AudioFormat.IMA4_MS); //allows the jmf manager to read a kr file 
//	}
//
//	private boolean doIt(MediaLocator inML, Format outputFmt,
//			WritableAudioClip byteData) throws IncompatibleSourceException,
//			NotRealizedError, IOException {
//
//		Processor p;
//
//		try {
//			System.err.println("- create processor for: " + inML);
//			p = Manager.createProcessor(inML);
//		} catch (Exception e) {
//			System.err
//					.println("Yikes!  Cannot create a processor from the given url: "
//							+ e);
//			return false;
//		}
//
//		realizeProcessor(p, outputFmt);
//		
//		Time duration = p.getDuration();
//		if(duration.getNanoseconds() == Time.TIME_UNKNOWN.getNanoseconds())
//			duration = new Time(60.*5);
//		
//		byteData.ensureCapacity(duration);
//		
//		// Now, we'll need to create a DataSink.
//		DataSink dsink = new ByteDataDataSink(byteData);
//
//		return doIt(p, dsink, outputFmt);
//	}
//
//	private boolean doIt(AudioClip in, Format outputFmt, File out)
//			throws IncompatibleSourceException, NotRealizedError, IOException {
//
//		Processor p;
//
//		AudioClipDataSource audioClipDataSource = new AudioClipDataSource(in);
//
//		try {
//			System.err.println("- create processor for datasource");
//			p = Manager.createProcessor(audioClipDataSource);
//		} catch (Exception e) {
//			System.err
//					.println("Yikes!  Cannot create a processor from the given url: "
//							+ e);
//			return false;
//		}
//		
//		realizeProcessor(p, outputFmt);
//
//		// Now, we'll need to create a DataSink.
//		DataSink dsink;
//		if ((dsink = createDataSink(p, new MediaLocator(out.toURL()))) == null) {
//			System.err
//					.println("Failed to create a DataSink for the given output MediaLocator: "
//							+ out.toURL());
//			return false;
//		}
//
//		return doIt(p, dsink, outputFmt);
//
//	}
//
//	/**
//	 * Create the DataSink.
//	 */
//	DataSink createDataSink(Processor p, MediaLocator outML) {
//
//		DataSource ds;
//
//		if ((ds = p.getDataOutput()) == null) {
//			System.err
//					.println("Something is really wrong: the processor does not have an output DataSource");
//			return null;
//		}
//
//
//		DataSink dsink;
//
//		try {
//			System.err.println("- create DataSink for: " + outML);
//			dsink = Manager.createDataSink(ds, outML);
//			dsink.open();
//		} catch (Exception e) {
//			System.err.println("Cannot create the DataSink: " + e);
//			return null;
//		}
//
//		return dsink;
//	}
//
//	private boolean realizeProcessor(Processor p, Format fmt) {
//		// TODO Auto-generated method stub
//		p.addControllerListener(this);
//
//		// Put the Processor into configured state.
//		p.configure();
//		if (!waitForState(p, p.Configured)) {
//			System.err.println("Failed to configure the processor.");
//			return false;
//		}
//
//		// Set the output content descriptor based on the media locator.
//		p.setContentDescriptor(new ContentDescriptor(ContentDescriptor.RAW));
//
//		// Program the tracks to the given output formats.
//		if (!setEachTrackFormat(p, fmt))
//			return false;
//
//		// We are done with programming the processor. Let's just
//		// realize the it.
//		p.realize();
//		if (!waitForState(p, p.Realized)) {
//			System.err.println("Failed to realize the processor.");
//			return false;
//		}
//		return true; //bliss
//		
//	}
//
//	private boolean doIt(Processor p, DataSink dsink, Format fmt)
//			throws IncompatibleSourceException, NotRealizedError, IOException {
//		dsink.setSource(p.getDataOutput());
//
//		dsink.addDataSinkListener(this);
//		fileDone = false;
//
//		System.err.println("start transcoding...");
//
//		// OK, we can now start the actual transcoding.
//		try {
//			p.start();
//			dsink.start();
//		} catch (IOException e) {
//			System.err.println("IO error during transcoding");
//			return false;
//		}
//
//		
//		// Wait for EndOfStream event.
//		waitForFileDone();
//
//		// Cleanup.
//		dsink.close();
//
//		p.removeControllerListener(this);
//
//		System.err.println("...done transcoding.");
//
//		return true;
//	}
//
//	/**
//	 * We'll loop through the tracks and try to find a track that can be
//	 * converted to the given format.
//	 */
//	private boolean setEachTrackFormat(Processor p, Format fmt) {
//		TrackControl tcs[];
//
//		if ((tcs = p.getTrackControls()) == null) {
//			// The processor does not support any track control.
//			System.err
//					.println("The Processor cannot transcode the tracks to the given formats");
//			return false;
//		}
//
//		Format supported[];
//		Format f;
//
//		for (int i = 0; i < tcs.length; i++) {
//
//			supported = tcs[i].getSupportedFormats();
//
//			if (supported == null)
//				continue;
//
//			for (int j = 0; j < supported.length; j++) {
//
//				if (fmt.matches(supported[j])
//						&& (f = fmt.intersects(supported[j])) != null
//						&& tcs[i].setFormat(f) != null) {
//
//					// Success.
//					return true;
//				}
//			}
//		}
//
//		return false;
//	}
//
//	Object waitSync = new Object();
//
//	boolean stateTransitionOK = true;
//
//	/**
//	 * Block until the processor has transitioned to the given state. Return
//	 * false if the transition failed.
//	 */
//	boolean waitForState(Processor p, int state) {
//		synchronized (waitSync) {
//			try {
//				while (p.getState() < state && stateTransitionOK)
//					waitSync.wait();
//			} catch (Exception e) {
//			}
//		}
//		return stateTransitionOK;
//	}
//
//	/**
//	 * Controller Listener.
//	 */
//	public void controllerUpdate(ControllerEvent evt) {
//
//		if (evt instanceof ConfigureCompleteEvent
//				|| evt instanceof RealizeCompleteEvent
//				|| evt instanceof PrefetchCompleteEvent) {
//			synchronized (waitSync) {
//				stateTransitionOK = true;
//				waitSync.notifyAll();
//			}
//		} else if (evt instanceof ResourceUnavailableEvent) {
//			synchronized (waitSync) {
//				stateTransitionOK = false;
//				waitSync.notifyAll();
//			}
//		} else if (evt instanceof EndOfMediaEvent) {
//			evt.getSourceController().close();
//		} else if (evt instanceof MediaTimeSetEvent) {
//			System.err.println("- mediaTime set: "
//					+ ((MediaTimeSetEvent) evt).getMediaTime().getSeconds());
//		} else if (evt instanceof StopAtTimeEvent) {
//			System.err.println("- stop at time: "
//					+ ((StopAtTimeEvent) evt).getMediaTime().getSeconds());
//			evt.getSourceController().close();
//		}
//	}
//
//	Object waitFileSync = new Object();
//
//	boolean fileDone = false;
//
//	boolean fileSuccess = true;
//
//	/**
//	 * Block until file writing is done.
//	 */
//	boolean waitForFileDone() {
//		System.err.print("  ");
//		synchronized (waitFileSync) {
//			try {
//				while (!fileDone) {
//					waitFileSync.wait(1000);
//					System.err.print(".");
//				}
//			} catch (Exception e) {
//			}
//		}
//		System.err.println("");
//		return fileSuccess;
//	}
//
//	/**
//	 * Event handler for the file writer.
//	 */
//	public void dataSinkUpdate(DataSinkEvent evt) {
//
//		if (evt instanceof EndOfStreamEvent) {
//			synchronized (waitFileSync) {
//				fileDone = true;
//				waitFileSync.notifyAll();
//			}
//		} else if (evt instanceof DataSinkErrorEvent) {
//			synchronized (waitFileSync) {
//				fileDone = true;
//				fileSuccess = false;
//				waitFileSync.notifyAll();
//			}
//		}
//	}
//
//	/**
//	 * Convert a file name to a content type. The extension is parsed to
//	 * determine the content type.
//	 */
//	ContentDescriptor fileExtToCD(String name) {
//
//		String ext;
//		int p;
//
//		// Extract the file extension.
//		if ((p = name.lastIndexOf('.')) < 0)
//			return null;
//
//		ext = (name.substring(p + 1)).toLowerCase();
//
//		String type;
//
//		// Use the MimeManager to get the mime type from the file extension.
//		if (ext.equals("mp3")) {
//			type = FileTypeDescriptor.MPEG_AUDIO;
//		} else {
//			if ((type = com.sun.media.MimeManager.getMimeType(ext)) == null)
//				return null;
//			type = ContentDescriptor.mimeTypeToPackageName(type);
//		}
//
//		return new FileTypeDescriptor(type);
//	}
//
//	/*
//	 * javax.media.format.AudioFormat(inFormat.getEncoding().toString(),
//	 * (double)inFormat.getSampleRate(), inFormat.getSampleSizeInBits(),
//	 * inFormat.getChannels(), inFormat.isBigEndian() ?
//	 * javax.media.format.AudioFormat.BIG_ENDIAN :
//	 * javax.media.format.AudioFormat.LITTLE_ENDIAN, signed ?
//	 * javax.media.format.AudioFormat.SIGNED :
//	 * javax.media.format.AudioFormat.UNSIGNED);
//	 */
//	public void appendJMFData(File sampleFile, WritableAudioClip byteData)
//			throws IncompatibleSourceException, NotRealizedError, IOException {
//		AudioFormat audioFormat = new AudioFormat(AudioFormat.LINEAR, // encoding
//				AudioFormat.NOT_SPECIFIED, // sample rate TODO: this must be
//				// set to 48000 at some point
//				byteData.getSampleSizeInBits(),//TIMHACK8, // sample size in bits
//				2, // channels
//				AudioFormat.LITTLE_ENDIAN, 
//				javax.media.format.AudioFormat.SIGNED // signed
//		);
//
//		MediaLocator ml;
//		try {
//			ml = new MediaLocator(sampleFile.toURL());
//		} catch (MalformedURLException e) {
//			throw new IllegalArgumentException(e);
//		}
//		
//		doIt(ml, audioFormat, byteData);
//	}
//
//	public void writeJMFData(AudioClip byteData, File out)
//			throws IncompatibleSourceException, NotRealizedError, IOException {
//		AudioFormat audioFormat = new AudioFormat(AudioFormat.IMA4_MS, // encoding
//				48000, // sample rate
//				4, // sample size in bits
//				2, // channels
//				AudioFormat.NOT_SPECIFIED, // big endian? 8 bit sample size so
//				// who cares?
//				javax.media.format.AudioFormat.UNSIGNED // signed
//		);
//
//		doIt(byteData, audioFormat, out);
//	}
//}
//
//class JMFManagerTest {
//	public static void main(String[] argv) throws Exception {
//		JMFManager jmf = new JMFManager();
//
//		MemAudioClip byteData = new MemAudioClip(2, 41000, 16);
//
//		jmf.appendJMFData(new File(argv[0]), byteData);
//
//		System.out.println("Mem Byte Data length is " + byteData.length());
//
//		byte[] buf = new byte[1000];
//		byteData.copyTo(0, 1000, buf, 0);
//		System.out.println(Util.toHex(buf));
//		
//		//doesn't work
////		System.out.println("saving in KR format to "+argv[1]);
////		
////		jmf.writeJMFData(byteData, new File(argv[1]));
//
//	}
//
//}
