FileDocCategorySizeDatePackage
SunVideoPlusManual.javaAPI DocJMF 2.1.1e15706Mon May 12 12:20:34 BST 2003None

SunVideoPlusManual.java

/*
 * @(#)SunVideoPlusManual.java	1.4 02/08/21
 *
 * Copyright (c) 1996-2002 Sun Microsystems, Inc.  All rights reserved.
 */

import javax.media.*;
import javax.media.format.VideoFormat;
import javax.media.format.RGBFormat;
import javax.media.format.YUVFormat;
import javax.media.format.AudioFormat;
import java.util.*;
import java.awt.*;
import java.awt.event.*;
import java.io.File;
import com.sun.media.protocol.sunvideoplus.*;

public class SunVideoPlusManual extends Frame {

    private static String DEVICE_PREFIX = "/dev/o1k";
    CaptureDeviceInfo [] devices = null;
    int currentID = -1;
    
    public SunVideoPlusManual() {
	super("SunVideoPlus");

	Font lblFont = new Font("Dialog", Font.BOLD + Font.ITALIC, 12);
	setLayout(new BorderLayout());
	BorderPanel bp = new BorderPanel();
	bp.setLayout(new BorderLayout(0, 0));

	Panel p = new Panel();
	p.setLayout(new FlowLayout(FlowLayout.LEFT));
	Label lbl = new Label("Configure Capture Devices");
	lbl.setFont(lblFont);
	p.add(lbl);
	bp.add(BorderLayout.NORTH, p);

	p = new Panel();
	p.setLayout(new FlowLayout());

	int nDevices = 0;
	for (int i = 0; i < 10; i++) {
	    File fl = new File(DEVICE_PREFIX + i);
	    if (fl.exists()) {
		Button device = new Button(DEVICE_PREFIX + i);
		p.add(device);
		device.addActionListener( new DBListener(i) );
		nDevices++;
	    }
	}
	bp.add(BorderLayout.CENTER, p);
	add(BorderLayout.NORTH, bp);

	devices = new CaptureDeviceInfo[nDevices];

	p = new Panel();
	p.setLayout(new FlowLayout());
	Button bDone = new Button("Done");
	bDone.addActionListener( new ActionListener() {
	    public void actionPerformed(ActionEvent ae) {
		if (currentID != -1) {
		    System.err.println("Need to close other window first");
		    return;
		}
		dispose();
		System.exit(0);
	    }
	} );
	p.add(bDone);
	add(BorderLayout.SOUTH, p);

	pack();
	addWindowListener( new WindowAdapter() {
	    public void windowClosing(WindowEvent we) {
		if (currentID != -1) {
		    System.err.println("Need to close other window first");
		    return;
		}
		dispose();
		System.exit(0);
	    }
	} );
    }

    public void createDialog(int id) {
	if (currentID == id)
	    return;
	currentID = id;
	Thread t = new Thread( new Runnable() {
	    public void run() {
		FormatsDialog fd = new FormatsDialog(currentID);
		fd.setVisible(true);
		Vector cdiv = fd.getDeviceInfo();
		if (cdiv != null && cdiv.size() > 0) {
		    for (int i = 0; i < cdiv.size(); i++) {
			CaptureDeviceInfo cdi = 
					(CaptureDeviceInfo) cdiv.elementAt(i);
			// At the moment, the name and locator are identical
			System.err.println("CaptureDeviceInfo = "
						+ cdi.getName());
//			System.err.println("CaptureDeviceInfo = "
//						+ cdi.getName() + " "
//						+ cdi.getLocator());
		    }
		}
		
		currentID = -1;
	    }
	} );
	t.start();
	// Create a CaptureDeviceInfo....
    }

    class FormatsDialog extends Frame {

	int id;

	Button bFormat, bCancel;
	CheckboxGroup cAnalogGroup;
	Checkbox cNTSC, cPAL;
	CheckboxGroup cPortGroup;
	Checkbox cPort1, cPort2, cSvhs;
	Checkbox cH261, cH263, cJpeg, cRGB, cYUV;
	Checkbox cFull, cCif, cQuarter;

	boolean fullVideo = false;
	boolean anyVideo = true;

	String sAnalog, sPort, sVideoFormat, sSize;

	Hashtable videoFormats = new Hashtable();

	OPICapture opiVidCap = null;

	Integer lock = new Integer(1);
	boolean finished = false;
	boolean needFormat = false;
	
	public FormatsDialog(int id) {
	    super("sunvideoplus:" + DEVICE_PREFIX + id);
	    this.id = id;
	    setLayout(new BorderLayout());
	    cAnalogGroup = new CheckboxGroup();
	    cNTSC = new Checkbox("NTSC", true, cAnalogGroup);
	    cPAL = new Checkbox("PAL", false, cAnalogGroup);
	    cPortGroup = new CheckboxGroup();
	    cPort1 = new Checkbox("1", true, cPortGroup);
	    cPort2 = new Checkbox("2", false, cPortGroup);
	    cSvhs = new Checkbox("S-VHS", false, cPortGroup);

	    ItemListener videoListener = new ItemListener() {
		public void itemStateChanged(ItemEvent e) {
		    fullVideo = (cRGB.getState() | cYUV.getState());
		    anyVideo = (cH261.getState() | cH263.getState()
				| cJpeg.getState() | fullVideo);
		    cFull.setEnabled(fullVideo);
		    cCif.setEnabled(anyVideo);
		    cQuarter.setEnabled(anyVideo);
		}
	    };

	    cH261 = new Checkbox("h.261", false);
	    cH261.addItemListener(videoListener);
	    cH263 = new Checkbox("h.263", false);
	    cH263.addItemListener(videoListener);
	    cJpeg = new Checkbox("Jpeg", true);
	    cJpeg.addItemListener(videoListener);
	    cRGB = new Checkbox("RGB", false);
	    cRGB.addItemListener(videoListener);
	    cYUV = new Checkbox("YUV", false);
	    cYUV.addItemListener(videoListener);
	    cFull = new Checkbox("full cif", false);
	    cFull.setEnabled(false);
	    cCif = new Checkbox("cif", true);
	    cQuarter = new Checkbox("quarter cif", false);


	    bFormat = new Button("Add Formats");
	    bCancel = new Button("Cancel");
	    
	    opiVidCap = new OPICapture(null);
	    if (!opiVidCap.connect(id)) {
		throw new Error("Unable to connect to device");
	    }

	    Font lblFont = new Font("Dialog", Font.BOLD + Font.ITALIC, 12);

	    BorderPanel bp = new BorderPanel();
	    bp.setLayout(new BorderLayout(0, 0));

	    Panel p = new Panel();
	    p.setLayout(new FlowLayout(FlowLayout.LEFT));
	    Label lbl = new Label("Video Input Formats");
	    lbl.setFont(lblFont);
	    p.add(lbl);
	    bp.add(BorderLayout.NORTH, p);

	    Panel cp = new Panel();
	    cp.setLayout(new BorderLayout());

	    p = new Panel();
	    p.setLayout(new FlowLayout());
	    p.add(new Label("Analog"));
	    p.add(cNTSC);
	    p.add(cPAL);
	    cp.add(BorderLayout.NORTH, p);

	    p = new Panel();
	    p.setLayout(new FlowLayout());
	    p.add(new Label("Port"));
	    p.add(cPort1);
	    p.add(cPort2);
	    p.add(cSvhs);
	    cp.add(BorderLayout.SOUTH, p);
	    bp.add(BorderLayout.CENTER, cp);
	    
	    cp = new Panel();
	    cp.setLayout(new BorderLayout());

	    p = new Panel();
	    p.setLayout(new FlowLayout());
	    p.add(new Label("Formats"));
	    p.add(cH261);
	    p.add(cH263);
	    p.add(cJpeg);
	    p.add(cRGB);
	    p.add(cYUV);
	    cp.add(BorderLayout.CENTER, p);

	    p = new Panel();
	    p.setLayout(new FlowLayout());
	    p.add(new Label("Sizes"));
	    p.add(cFull);
	    p.add(cCif);
	    p.add(cQuarter);
	    cp.add(BorderLayout.SOUTH, p);
	    bp.add(BorderLayout.SOUTH, cp);
	    add(BorderLayout.NORTH, bp);

	    p = new Panel();
	    p.setLayout(new FlowLayout());
	    p.add(bFormat);
	    p.add(bCancel);
	    add(BorderLayout.SOUTH, p);
	    pack();

	    addWindowListener( new WindowAdapter() {
		public void windowClosing(WindowEvent we) {
		    synchronized (lock) {
			finished = true;
			lock.notify();
		    }
		}
	    } );

	    bCancel.addActionListener( new ActionListener() {
		public void actionPerformed(ActionEvent ae) {
		    synchronized (lock) {
			finished = true;
			lock.notify();
		    }
		}
	    } );

	    bFormat.addActionListener( new ActionListener() {
		public void actionPerformed(ActionEvent ae) {
		    needFormat = true;
		    synchronized (lock) {
			lock.notify();
		    }
		}
	    } );
	}

	private void addVideoFormat(Format fin) {
	    String sVideo = sPort + "/" + sVideoFormat + "/"
					+ sSize + "/"
					+ sAnalog;
	    System.err.println("New format " + sVideo + " = " + fin);
	    videoFormats.put(sVideo, fin);
	}

	public void mydispose() {
	    opiVidCap.disconnect();
	    dispose();
	    System.err.println("Disconnected driver");
	}
	
	public void doFormat() {
	    if (!checkVideoFormats())
		return;

	    if (anyVideo) {
		doVideoFormats();
	    }
	    finished = true;
	}

	public boolean checkVideoFormats() {
	    if (!anyVideo)
		return true;
	    if (cCif.getState() | cQuarter.getState() |
				    (cFull.getState() && cFull.isEnabled()))
		return true;
	    // Issue error popup dialog
	    issueError("Must specify at least one Video size");
	    return false;
	}

	public void doVideoFormats() {
	    if (!anyVideo) {
		// add a dummy format entry
		videoFormats.put("off", new VideoFormat(VideoFormat.RGB));
	    }

	    Checkbox cAnalog = cAnalogGroup.getSelectedCheckbox();
	    sAnalog = "";
	    if (cAnalog == cNTSC) {
		sAnalog = "ntsc";
	    } else if (cAnalog == cPAL) {
		sAnalog = "pal";
	    } else {
		System.err.println("No analog signal specified");
		return;
	    }
	    if (!opiVidCap.setSignal(sAnalog)) {
		System.err.println("Video analog signal not recognized");
		return;
	    }
	    Checkbox cPort = cPortGroup.getSelectedCheckbox();
	    int port = 1;
	    if (cPort == cPort1) {
		port = 1;
	    } else if (cPort == cPort2) {
		port = 2;
	    } else if (cPort == cSvhs) {
		port = 0;
	    } else {
		System.err.println("No port specified");
		return;
	    }
	    if (!opiVidCap.setPort(port)) {
		System.err.println("Video source not recognized on port");
		return;
	    }
	    sPort = "" + port;
	    if (cCif.getState()) {
		opiVidCap.setScale(2);
		sSize = "cif";
		getVideoFormats();
	    }
	    if (cQuarter.getState()) {
		opiVidCap.setScale(4);
		sSize = "qcif";
		getVideoFormats();
	    }
	    if (cFull.getState() && cFull.isEnabled()) {
		opiVidCap.setScale(1);
		sSize = "fcif";
		getVideoFormats();
	    }
	    
	}

	private void getVideoFormats() {
	    if (cH261.getState()) {
		if (!(sSize.equals("fcif"))) {
		    sVideoFormat = "h261";
		    getH261Format();
		}
	    }
	    if (cH263.getState()) {
		if (!(sSize.equals("fcif"))) {
		    sVideoFormat = "h263";
		    getH263Format();
		}
	    }
	    if (cJpeg.getState()) {
		if (!(sSize.equals("fcif"))) {
		    sVideoFormat = "jpeg";
		    getJpegFormat();
		}
	    }
	    if (cRGB.getState()) {
		sVideoFormat = "rgb";
		getRGBFormat();
	    }
	    if (cYUV.getState()) {
		sVideoFormat = "yuv";
		getYUVFormat();
	    }
	}

	private void getRGBFormat() {
	    if (!opiVidCap.setCompress("RGB"))
		return;
	    /*
	     * If sizes are wanted, the only valid sizes are
	     *	NTSC
	     *		fcif	(640 x 480)
	     *		cif	(320 x 240)
	     *		qcif	(160 x 120)
	     *	PAL
	     *		fcif	(768 x 576)
	     *		cif	(384 x 288)
	     *		qcif	(192 x 144)
	     */
	    Dimension size = new Dimension(opiVidCap.getWidth(),
						opiVidCap.getHeight());
	    addVideoFormat(new RGBFormat(size, Format.NOT_SPECIFIED,
					Format.byteArray,
					Format.NOT_SPECIFIED,
					16,
					0xF800, 0x7E0, 0x1F, 2,
					Format.NOT_SPECIFIED,
					Format.FALSE,
					Format.NOT_SPECIFIED));
	}

	private void getYUVFormat() {
	    if (!opiVidCap.setCompress("YUV"))
		return;
	    /*
	     * If sizes are wanted, the only valid sizes are
	     *	NTSC
	     *		fcif	(640 x 480)
	     *		cif	(320 x 240)
	     *		qcif	(160 x 120)
	     *	PAL
	     *		fcif	(768 x 576)
	     *		cif	(384 x 288)
	     *		qcif	(192 x 144)
	     *
	     * The capture stream is actually interleaved YVYU format.
	     * This is defined in the offset values below.
	     */
	    Dimension size = new Dimension(opiVidCap.getWidth(),
						opiVidCap.getHeight());
	    addVideoFormat(new YUVFormat(size, Format.NOT_SPECIFIED,
					Format.byteArray,
					Format.NOT_SPECIFIED,
					YUVFormat.YUV_YUYV,
					Format.NOT_SPECIFIED,
					Format.NOT_SPECIFIED,
					0, 3, 1));
	}

	private void getJpegFormat() {
	    if (!opiVidCap.setCompress("Jpeg"))
		return;
	    /*
	     * If sizes are wanted, the only valid sizes are
	     *	NTSC
	     *		cif	(320 x 240)
	     *		qcif	(160 x 120)
	     *	PAL
	     *		cif	(384 x 288)
	     *		qcif	(192 x 144)
	     */
	    Dimension size = new Dimension(opiVidCap.getWidth(),
						opiVidCap.getHeight());
	    addVideoFormat(new VideoFormat(VideoFormat.JPEG, size,
	    				Format.NOT_SPECIFIED,
					Format.byteArray,
					Format.NOT_SPECIFIED));
	}

	private void getH261Format() {
	    if (!opiVidCap.setCompress("H261"))
		return;
	    /*
	     * If sizes are wanted, the only valid sizes are
	     *		cif	(352 x 288)
	     *		qcif	(176 x 144)
	     */
	    Dimension size = new Dimension(opiVidCap.getWidth(),
						opiVidCap.getHeight());
	    addVideoFormat(new VideoFormat(VideoFormat.H261, size,
	    				Format.NOT_SPECIFIED,
					Format.byteArray,
					Format.NOT_SPECIFIED));
	}

	private void getH263Format() {
	    if (!opiVidCap.setCompress("H263"))
		return;
	    /*
	     * If sizes are wanted, the only valid sizes are
	     *		cif	(352 x 288)
	     *		qcif	(176 x 144)
	     */
	    Dimension size = new Dimension(opiVidCap.getWidth(),
						opiVidCap.getHeight());
	    addVideoFormat(new VideoFormat(VideoFormat.H263, size,
	    				Format.NOT_SPECIFIED,
					Format.byteArray,
					Format.NOT_SPECIFIED));
	}


	public void issueError(String err) {
	    System.err.println(err);
	    Toolkit.getDefaultToolkit().beep();
	}

	public Enumeration sortedFormats(Hashtable formats) {
	    Vector sorted = new Vector();
	    keyloop: for (Enumeration en = formats.keys();
						en.hasMoreElements(); ) {
		String key = (String) en.nextElement();
		for (int i = 0; i < sorted.size(); i++) {
		    if (key.compareTo((String)sorted.elementAt(i)) < 0) {
			sorted.insertElementAt(key, i);
			continue keyloop;
		    }
		}
		sorted.addElement(key);
	    }
	    return sorted.elements();
	}



	public Vector getDeviceInfo() {
	    try {
		while (!finished) {
		    synchronized (lock) {
			lock.wait();
		    }
		    
		    if (needFormat) {
			needFormat = false;
			doFormat();
		    }
		}
	    } catch (InterruptedException ie) {
		mydispose();
		return null;
	    }
	    String locatorPrefix = "sunvideoplus://" + id;
	    mydispose();
	    
	    /*
	     * First remove any old entries
	     */
	    Vector devices = (Vector) CaptureDeviceManager.
						getDeviceList(null).clone();
	    Enumeration enum = devices.elements();
	    while (enum.hasMoreElements()) {
		CaptureDeviceInfo cdi = (CaptureDeviceInfo) enum.nextElement();
		String devName = cdi.getName();
		if (devName.startsWith(locatorPrefix))
		    CaptureDeviceManager.removeDevice(cdi);
	    }

	    devices = new Vector();
	    if (anyVideo) {


		for (Enumeration ve = sortedFormats(videoFormats);
						ve.hasMoreElements(); ) {
		    String vKey = (String) ve.nextElement();
		    Format vForm = (VideoFormat)videoFormats.get(vKey);
		    Format[] farray = null;
		    farray = new Format[1];
		    farray[0] = vForm;
		    String name = locatorPrefix + "/" + vKey;
		    CaptureDeviceInfo cdi = new CaptureDeviceInfo(name,
					new MediaLocator(name), farray);
		    CaptureDeviceManager.addDevice(cdi);
		    devices.addElement(cdi);
		}
	    }
	    try {
		CaptureDeviceManager.commit();
		System.err.println("SunVideoPlusManual: Committed ok");
	    } catch (java.io.IOException ioe) {
		System.err.println("SunVideoPlusManual: error committing cdm");
	    }
	    return devices;
	}

    }

    class DBListener implements ActionListener {
	
	int id;

	public DBListener(int id) {
	    this.id = id;
	}

	public void actionPerformed(ActionEvent ae) {
	    createDialog(id);
	}
    }

    class BorderPanel extends Panel {
	int insets = 7;

	public BorderPanel() {
	}
	
	public BorderPanel(int insets) {
	    this.insets = insets;
	}
	
	public Insets getInsets() {
	    return new Insets(insets, insets, insets, insets);
	}

	public void paint(Graphics g) {
	    if (insets != 0) {
		Color bc = getBackground();
		super.paint(g);
		Dimension size = getSize();
		g.setColor(bc.darker());
		g.drawLine(2, 2, size.width - 3, 2);
		g.drawLine(2, 2, 2, size.height - 3);
		g.setColor(bc.brighter());
		g.drawLine(size.width - 3, 2, size.width - 3, size.height - 3);
		g.drawLine(2, size.height - 3, size.width - 3, size.height - 3);
	    }
	}
    } 

    public static void main(String [] args) {
	SunVideoPlusManual m = new SunVideoPlusManual();
	m.setVisible(true);
    }
}