mirror of https://github.com/sipwise/jitsi.git
Some portaudio fixes. Add to configuration panel option to select portaudio and the devices to use. Javasound left as default, as portaudio is not currently enabled (missing native binaries). Removed some old and unused jmf stuff like v4l, sun audio, directsound.
parent
3932e0f779
commit
b5ae6c1a91
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
@ -1,111 +0,0 @@
|
||||
/*
|
||||
* SIP Communicator, the OpenSource Java VoIP and Instant Messaging client.
|
||||
*
|
||||
* Distributable under LGPL license.
|
||||
* See terms of license at gnu.org.
|
||||
*
|
||||
* File based on:
|
||||
* @(#)DirectSoundAuto.java 1.3 01/03/13
|
||||
* Copyright (c) 1999-2001 Sun Microsystems, Inc. All Rights Reserved.
|
||||
*/
|
||||
package net.java.sip.communicator.impl.media.device;
|
||||
|
||||
import java.util.*;
|
||||
import javax.media.*;
|
||||
import javax.media.format.*;
|
||||
|
||||
import net.java.sip.communicator.util.*;
|
||||
|
||||
public class DirectSoundAuto {
|
||||
|
||||
private static final Logger logger = Logger.getLogger(DirectSoundAuto.class);
|
||||
|
||||
private static final String detectClass = "com.sun.media.protocol.dsound.DSound";
|
||||
CaptureDeviceInfo[] devices = null;
|
||||
|
||||
public static void main(String[] args) {
|
||||
new DirectSoundAuto();
|
||||
System.exit(0);
|
||||
}
|
||||
|
||||
private boolean supports(AudioFormat af) {
|
||||
try {
|
||||
com.sun.media.protocol.dsound.DSound ds;
|
||||
ds = new com.sun.media.protocol.dsound.DSound(af, 1024);
|
||||
ds.open();
|
||||
ds.close();
|
||||
} catch (Exception e) {
|
||||
logger.error(e);
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked") //legacy JMF code.
|
||||
public DirectSoundAuto() {
|
||||
boolean supported = false;
|
||||
// instance JavaSoundDetector to check is javasound's capture is availabe
|
||||
try {
|
||||
Class.forName(detectClass);
|
||||
supported = true;
|
||||
} catch (Throwable t) {
|
||||
supported = false;
|
||||
// t.printStackTrace();
|
||||
}
|
||||
|
||||
logger.info("DirectSound Capture Supported = " + supported);
|
||||
|
||||
if (supported) {
|
||||
// It's there, start to register JavaSound with CaptureDeviceManager
|
||||
Vector<CaptureDeviceInfo> devices
|
||||
= (Vector<CaptureDeviceInfo>)CaptureDeviceManager
|
||||
.getDeviceList(null).clone();
|
||||
|
||||
// remove the old direct sound capturers
|
||||
String name;
|
||||
Enumeration<CaptureDeviceInfo> enumeration = devices.elements();
|
||||
while (enumeration.hasMoreElements()) {
|
||||
CaptureDeviceInfo cdi = enumeration.nextElement();
|
||||
name = cdi.getName();
|
||||
if (name.startsWith(com.sun.media.protocol.dsound.DataSource.NAME))
|
||||
CaptureDeviceManager.removeDevice(cdi);
|
||||
}
|
||||
int LE = AudioFormat.LITTLE_ENDIAN;
|
||||
int SI = AudioFormat.SIGNED;
|
||||
int US = AudioFormat.UNSIGNED;
|
||||
int UN = AudioFormat.NOT_SPECIFIED;
|
||||
float [] Rates = new float[] {
|
||||
48000, 44100, 32000, 22050, 16000, 11025, 8000
|
||||
};
|
||||
Vector<AudioFormat> formats = new Vector<AudioFormat>(4);
|
||||
for (int rateIndex = 0; rateIndex < Rates.length; rateIndex++) {
|
||||
float rate = Rates[rateIndex];
|
||||
AudioFormat af;
|
||||
af = new AudioFormat(AudioFormat.LINEAR, rate, 16, 2, LE, SI);
|
||||
if (supports(af)) formats.addElement(af);
|
||||
af = new AudioFormat(AudioFormat.LINEAR, rate, 16, 1, LE, SI);
|
||||
if (supports(af)) formats.addElement(af);
|
||||
af = new AudioFormat(AudioFormat.LINEAR, rate, 8, 2, UN, US);
|
||||
if (supports(af)) formats.addElement(af);
|
||||
af = new AudioFormat(AudioFormat.LINEAR, rate, 8, 1, UN, US);
|
||||
if (supports(af)) formats.addElement(af);
|
||||
}
|
||||
|
||||
AudioFormat [] formatArray = new AudioFormat[formats.size()];
|
||||
for (int fa = 0; fa < formatArray.length; fa++)
|
||||
formatArray[fa] = formats.elementAt(fa);
|
||||
|
||||
CaptureDeviceInfo cdi = new CaptureDeviceInfo(
|
||||
com.sun.media.protocol.dsound.DataSource.NAME,
|
||||
new MediaLocator("dsound://"),
|
||||
formatArray);
|
||||
CaptureDeviceManager.addDevice(cdi);
|
||||
try {
|
||||
CaptureDeviceManager.commit();
|
||||
logger.info("DirectSoundAuto: Committed ok");
|
||||
} catch (java.io.IOException ioe) {
|
||||
logger.error("DirectSoundAuto: error committing cdm");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -1,357 +0,0 @@
|
||||
/*
|
||||
* SIP Communicator, the OpenSource Java VoIP and Instant Messaging client.
|
||||
*
|
||||
* Distributable under LGPL license.
|
||||
* See terms of license at gnu.org.
|
||||
*
|
||||
* File based on:
|
||||
* @(#)JMFInit.java 1.14 03/04/30
|
||||
* Copyright (c) 1996-2002 Sun Microsystems, Inc. All rights reserved.
|
||||
*/
|
||||
package net.java.sip.communicator.impl.media.device;
|
||||
|
||||
import java.io.*;
|
||||
import java.util.*;
|
||||
import javax.media.*;
|
||||
import javax.media.format.*;
|
||||
|
||||
import net.java.sip.communicator.util.*;
|
||||
|
||||
|
||||
public class JMFInit
|
||||
implements Runnable {
|
||||
|
||||
private static final Logger logger = Logger.getLogger(JMFInit.class);
|
||||
|
||||
public JMFInit() {
|
||||
|
||||
// try {
|
||||
// Registry.commit();
|
||||
// }
|
||||
// catch (Exception e) {
|
||||
// logger.error("Failed to commit to JMFRegistry!", e );
|
||||
// }
|
||||
|
||||
|
||||
Thread detectThread = new Thread(this);
|
||||
detectThread.run();
|
||||
|
||||
/*
|
||||
int slept = 0;
|
||||
while (!done && slept < 60 * 1000 * 2) {
|
||||
try {
|
||||
Thread.currentThread().sleep(500);
|
||||
}
|
||||
catch (InterruptedException ie) {
|
||||
}
|
||||
slept += 500;
|
||||
}
|
||||
|
||||
if (!done) {
|
||||
console.error("Detection is taking too long! Aborting!");
|
||||
message("Detection is taking too long! Aborting!");
|
||||
}
|
||||
|
||||
try {
|
||||
Thread.currentThread().sleep(2000);
|
||||
}
|
||||
catch (InterruptedException ie) {
|
||||
}
|
||||
*/
|
||||
}
|
||||
|
||||
/**
|
||||
* Detect all capture devices
|
||||
*/
|
||||
public void run() {
|
||||
detectDirectAudio();
|
||||
detectS8DirectAudio();
|
||||
detectCaptureDevices();
|
||||
}
|
||||
|
||||
private void detectCaptureDevices() {
|
||||
// check if JavaSound capture is available
|
||||
logger.info("Looking for Audio capturer");
|
||||
Class<?> dsauto = null;
|
||||
try {
|
||||
dsauto = Class.forName(
|
||||
"net.java.sip.communicator.impl.media.device.DirectSoundAuto");
|
||||
dsauto.newInstance();
|
||||
logger.info("Finished detecting DirectSound capturer");
|
||||
}
|
||||
catch (ThreadDeath td) {
|
||||
throw td;
|
||||
}
|
||||
catch (Throwable t) {
|
||||
logger.warn("DirectSound capturer detection failed!", t);
|
||||
}
|
||||
|
||||
Class<?> jsauto = null;
|
||||
try {
|
||||
jsauto = Class.forName(
|
||||
"net.java.sip.communicator.impl.media.device.JavaSoundAuto");
|
||||
jsauto.newInstance();
|
||||
logger.info("Finished detecting JavaSound capturer");
|
||||
}
|
||||
catch (ThreadDeath td) {
|
||||
throw td;
|
||||
}
|
||||
catch (Throwable t) {
|
||||
logger.warn("JavaSound capturer detection failed!", t);
|
||||
}
|
||||
|
||||
// Check if VFWAuto or SunVideoAuto is available
|
||||
logger.info("Looking for video capture devices");
|
||||
Class<?> auto = null;
|
||||
Class<?> autoPlus = null;
|
||||
try {
|
||||
auto = Class.forName(
|
||||
"net.java.sip.communicator.impl.media.device.VFWAuto");
|
||||
}
|
||||
catch (Exception e) {
|
||||
logger.warn("VFWAuto capturer detection failed!", e);
|
||||
}
|
||||
if (auto == null) {
|
||||
try {
|
||||
auto = Class.forName(
|
||||
"net.java.sip.communicator.impl.media.device.SunVideoAuto");
|
||||
}
|
||||
catch (Exception ee) {
|
||||
logger.warn("SunVideoAuto capturer detection failed!", ee);
|
||||
}
|
||||
try {
|
||||
autoPlus = Class.forName(
|
||||
"net.java.sip.communicator.impl.media.device.SunVideoPlusAuto");
|
||||
}
|
||||
catch (Exception ee) {
|
||||
logger.warn("SunVideoPlusAuto capturer detection failed!", ee);
|
||||
}
|
||||
}
|
||||
if (auto == null) {
|
||||
try {
|
||||
auto = Class.forName(
|
||||
"net.java.sip.communicator.impl.media.device.V4LAuto");
|
||||
}
|
||||
catch (Exception ee) {
|
||||
logger.warn("V4lAuto capturer detection failed!", ee);
|
||||
}
|
||||
}
|
||||
try {
|
||||
auto.newInstance();
|
||||
if (autoPlus != null) {
|
||||
autoPlus.newInstance();
|
||||
}
|
||||
logger.info("Finished detecting video capture devices");
|
||||
}
|
||||
catch (ThreadDeath td) {
|
||||
throw td;
|
||||
}
|
||||
catch (Throwable t) {
|
||||
logger.error("Capture device detection failed!", t);
|
||||
}
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked") //legacy JMF code.
|
||||
private void detectDirectAudio() {
|
||||
Class<?> cls;
|
||||
int plType = PlugInManager.RENDERER;
|
||||
String dar = "com.sun.media.renderer.audio.DirectAudioRenderer";
|
||||
try {
|
||||
// Check if this is the Windows Performance Pack - hack
|
||||
cls = Class.forName(
|
||||
"net.java.sip.communicator.impl.media.device.VFWAuto");
|
||||
// Check if DS capture is supported, otherwise fail DS renderer
|
||||
// since NT doesn't have capture
|
||||
cls = Class.forName("com.sun.media.protocol.dsound.DSound");
|
||||
// Find the renderer class and instantiate it.
|
||||
cls = Class.forName(dar);
|
||||
|
||||
Renderer rend = (Renderer) cls.newInstance();
|
||||
try {
|
||||
// Set the format and open the device
|
||||
AudioFormat af = new AudioFormat(AudioFormat.LINEAR,
|
||||
44100, 16, 2);
|
||||
rend.setInputFormat(af);
|
||||
rend.open();
|
||||
Format[] inputFormats = rend.getSupportedInputFormats();
|
||||
// Register the device
|
||||
PlugInManager.addPlugIn(dar, inputFormats, new Format[0],
|
||||
plType);
|
||||
// Move it to the top of the list
|
||||
Vector<String> rendList =
|
||||
PlugInManager.getPlugInList(null, null, plType);
|
||||
int listSize = rendList.size();
|
||||
if (rendList.elementAt(listSize - 1).equals(dar)) {
|
||||
rendList.removeElementAt(listSize - 1);
|
||||
rendList.insertElementAt(dar, 0);
|
||||
PlugInManager.setPlugInList(rendList, plType);
|
||||
PlugInManager.commit();
|
||||
//System.err.println("registered");
|
||||
}
|
||||
rend.close();
|
||||
}
|
||||
catch (Throwable t) {
|
||||
//System.err.println("Error " + t);
|
||||
}
|
||||
}
|
||||
catch (Throwable tt) {
|
||||
}
|
||||
}
|
||||
|
||||
private void detectS8DirectAudio() {
|
||||
try
|
||||
{
|
||||
new S8DirectAudioAuto();
|
||||
}
|
||||
catch (Throwable tt)
|
||||
{
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Runs JMFInit the first time the application is started so that capture
|
||||
* devices are properly detected and initialized by JMF.
|
||||
*/
|
||||
public static void setupJMF()
|
||||
{
|
||||
try
|
||||
{
|
||||
logger.logEntry();
|
||||
|
||||
// .jmf is the place where we store the jmf.properties file used
|
||||
// by JMF. if the directory does not exist or it does not contain
|
||||
// a jmf.properties file, or if the jmf.properties file has 0 length
|
||||
// then this is the first time we're running and should detect capture
|
||||
// devices
|
||||
String homeDir = System.getProperty("user.home");
|
||||
File jmfDir = new File(homeDir, ".jmf");
|
||||
String classpath = System.getProperty("java.class.path");
|
||||
classpath += System.getProperty("path.separator") +
|
||||
jmfDir.getAbsolutePath();
|
||||
System.setProperty("java.class.path", classpath);
|
||||
|
||||
if (!jmfDir.exists())
|
||||
jmfDir.mkdir();
|
||||
|
||||
File jmfProperties = new File(jmfDir, "jmf.properties");
|
||||
|
||||
if (!jmfProperties.exists()) {
|
||||
try {
|
||||
jmfProperties.createNewFile();
|
||||
}
|
||||
catch (IOException ex) {
|
||||
logger.error(
|
||||
"Failed to create jmf.properties - " +
|
||||
jmfProperties.getAbsolutePath());
|
||||
}
|
||||
}
|
||||
|
||||
//if we're running on linux checkout that libjmutil.so is where it
|
||||
//should be and put it there.
|
||||
// runLinuxPreInstall();
|
||||
|
||||
if (jmfProperties.length() == 0) {
|
||||
new JMFInit();
|
||||
}
|
||||
}
|
||||
finally
|
||||
{
|
||||
logger.logExit();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
// private static void runLinuxPreInstall()
|
||||
// {
|
||||
// try {
|
||||
// logger.logEntry();
|
||||
//
|
||||
// if (Utils.getProperty("os.name") == null
|
||||
// || !Utils.getProperty("os.name").equalsIgnoreCase("Linux"))
|
||||
// return;
|
||||
//
|
||||
// try {
|
||||
// System.loadLibrary("jmv4l");
|
||||
// console.debug("Successfully loaded libjmv4l.so");
|
||||
// }
|
||||
// catch (UnsatisfiedLinkError err) {
|
||||
// console.debug("Failed to load libjmv4l.so. Will try and copy libjmutil.so", err);
|
||||
//
|
||||
// String destinationPathStr = Utils.getProperty("java.home")
|
||||
// + File.separator + "lib"
|
||||
// + File.separator + "i386";
|
||||
// String libjmutilFileStr = "libjmutil.so";
|
||||
//
|
||||
// try {
|
||||
// InputStream libIS =
|
||||
// MediaManager.class.getClassLoader().
|
||||
// getResourceAsStream(libjmutilFileStr);
|
||||
// File outFile = new File(destinationPathStr
|
||||
// +File.separator + libjmutilFileStr);
|
||||
//
|
||||
// //Check if file is already there - Ben Asselstine
|
||||
// if (outFile.exists()) {
|
||||
// //if we're here then libjmutil is already where it should be
|
||||
// // but yet we failed to load libjmv4l.
|
||||
// //so notify log and bail out
|
||||
// console.error(
|
||||
// "An error occurred while trying to load JMF. This "
|
||||
// +"error is probably due to a JMF installation problem. "
|
||||
// +"Please copy libjmutil.so to a location contained by "
|
||||
// + "$LD_LIBRARY_PATH and try again!",
|
||||
// err);
|
||||
// return;
|
||||
//
|
||||
// }
|
||||
//
|
||||
// outFile.createNewFile();
|
||||
//
|
||||
// console.debug("jmutil");
|
||||
//
|
||||
// FileOutputStream fileOS = new FileOutputStream(outFile);
|
||||
// int available = libIS.available();
|
||||
// byte[] bytes = new byte[libIS.available()];
|
||||
// int read = 0;
|
||||
// int i = 0;
|
||||
// for (i = 0; i<available ; i++)
|
||||
// {
|
||||
// bytes[i] = (byte)libIS.read();
|
||||
// }
|
||||
//
|
||||
// console.debug("Read " + i + " bytes out of " + available );
|
||||
//
|
||||
// fileOS.write(bytes, 0, bytes.length);
|
||||
// console.debug("Wrote " + available + " bytes.");
|
||||
// bytes = null;
|
||||
// libIS.close();
|
||||
// fileOS.close();
|
||||
// }
|
||||
// catch (IOException exc) {
|
||||
// if( exc.getMessage() != null
|
||||
// && exc.getMessage().toLowerCase().indexOf("permission denied") != -1)
|
||||
// console.showError("Permission denied!",
|
||||
// "Because of insufficient permissions SIP Communicator has failed "
|
||||
// + "to copy a required library to\n\n\t"
|
||||
// + destinationPathStr + "!\n\nPlease run the application as root or "
|
||||
// + "manually copy the " +libjmutilFileStr
|
||||
// + " file to the above location!\n");
|
||||
// exc.printStackTrace();
|
||||
// }
|
||||
// }
|
||||
// /** @todo check whether we have a permissions problem and alert the
|
||||
// * user that they should be running as root */
|
||||
// catch(Throwable t)
|
||||
// {
|
||||
// console.debug("Error while loading");
|
||||
// }
|
||||
// }
|
||||
// finally {
|
||||
// console.logExit();
|
||||
// }
|
||||
// }
|
||||
|
||||
public static void start() {
|
||||
setupJMF();
|
||||
}
|
||||
}
|
||||
@ -1,62 +0,0 @@
|
||||
package net.java.sip.communicator.impl.media.device;
|
||||
|
||||
import java.util.*;
|
||||
|
||||
import javax.media.*;
|
||||
|
||||
import com.sun.media.*;
|
||||
|
||||
/**
|
||||
* Probes for JMF Solaris 8 direct audio.
|
||||
*
|
||||
* @author Emil Ivov
|
||||
* @author Ken Larson
|
||||
*/
|
||||
public class S8DirectAudioAuto
|
||||
{
|
||||
@SuppressWarnings("unchecked") //legacy JMF code.
|
||||
public S8DirectAudioAuto() throws Exception
|
||||
{
|
||||
Class<?> cls;
|
||||
int plType = PlugInManager.RENDERER;
|
||||
String dar = "com.sun.media.renderer.audio.DirectAudioRenderer";
|
||||
|
||||
// Check if this is the solaris Performance Pack - hack
|
||||
cls = Class.forName(
|
||||
"net.java.sip.communicator.impl.media.device.SunVideoAuto");
|
||||
|
||||
// Find the renderer class and instantiate it.
|
||||
cls = Class.forName(dar);
|
||||
|
||||
Renderer rend = (Renderer) cls.newInstance();
|
||||
|
||||
if (rend instanceof ExclusiveUse &&
|
||||
! ( (ExclusiveUse) rend).isExclusive())
|
||||
{
|
||||
// sol8+, DAR supports mixing
|
||||
Vector<String> rendList = PlugInManager.getPlugInList(null, null,
|
||||
plType);
|
||||
int listSize = rendList.size();
|
||||
boolean found = false;
|
||||
String rname = null;
|
||||
|
||||
for (int i = 0; i < listSize; i++)
|
||||
{
|
||||
rname = rendList.elementAt(i);
|
||||
if (rname.equals(dar))
|
||||
{ // DAR is in the registry
|
||||
found = true;
|
||||
rendList.removeElementAt(i);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (found)
|
||||
{
|
||||
rendList.insertElementAt(dar, 0);
|
||||
PlugInManager.setPlugInList(rendList, plType);
|
||||
PlugInManager.commit();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -1,206 +0,0 @@
|
||||
/*
|
||||
* SIP Communicator, the OpenSource Java VoIP and Instant Messaging client.
|
||||
*
|
||||
* Distributable under LGPL license.
|
||||
* See terms of license at gnu.org.
|
||||
*
|
||||
* File based on:
|
||||
* @(#)SunVideoAuto.java 1.8 01/03/13
|
||||
* Copyright (c) 1999-2001 Sun Microsystems, Inc. All Rights Reserved.
|
||||
*/
|
||||
package net.java.sip.communicator.impl.media.device;
|
||||
|
||||
import java.io.*;
|
||||
import java.util.*;
|
||||
import javax.media.*;
|
||||
import javax.media.format.*;
|
||||
|
||||
import java.awt.*;
|
||||
|
||||
import net.java.sip.communicator.util.*;
|
||||
import com.sun.media.protocol.sunvideo.*;
|
||||
|
||||
|
||||
public class SunVideoAuto
|
||||
{
|
||||
|
||||
private static final Logger logger = Logger.getLogger(SunVideoAuto.class);
|
||||
|
||||
private static String DEVICE_PREFIX = "/dev/rtvc";
|
||||
private static String PROTOCOL = "sunvideo";
|
||||
private static String LOCATOR_PREFIX = PROTOCOL + "://";
|
||||
CaptureDeviceInfo [] devices = null;
|
||||
int currentID = -1;
|
||||
|
||||
XILCapture xilCap;
|
||||
|
||||
Vector<Format> formats = null;
|
||||
|
||||
int [] ports = { 1, 2, 0 }; // most likely ports for a device
|
||||
|
||||
int [] scales = { 2, 4, 1 }; // supported scales / sizes
|
||||
|
||||
/**
|
||||
* Default constructor. Does nothing.
|
||||
*/
|
||||
public SunVideoAuto()
|
||||
{
|
||||
}
|
||||
|
||||
/**
|
||||
* Removes from the CaptureDeviceManager all currently detected vfw devices
|
||||
* and runs a new detection loop to rediscover those that are currently
|
||||
* available.
|
||||
*
|
||||
* @return the number of devices detected.
|
||||
*/
|
||||
@SuppressWarnings("unchecked") //legacy JMF code.
|
||||
public int autoDetectDevices()
|
||||
{
|
||||
Vector<CaptureDeviceInfo> devices
|
||||
= (Vector) CaptureDeviceManager.getDeviceList(null).clone();
|
||||
Enumeration<CaptureDeviceInfo> enumeration = devices.elements();
|
||||
while (enumeration.hasMoreElements()) {
|
||||
CaptureDeviceInfo cdi = enumeration.nextElement();
|
||||
String devName = cdi.getLocator().getProtocol();
|
||||
if (devName.equals(PROTOCOL))
|
||||
CaptureDeviceManager.removeDevice(cdi);
|
||||
}
|
||||
|
||||
int nDevices = 0;
|
||||
for (int i = 0; i < 7; i++) {
|
||||
File fl = new File(DEVICE_PREFIX + i);
|
||||
if (fl.exists()) {
|
||||
doDevice(i);
|
||||
nDevices++;
|
||||
}
|
||||
}
|
||||
try {
|
||||
CaptureDeviceManager.commit();
|
||||
} catch (java.io.IOException ioe) {
|
||||
logger.error("SunVideoAuto: error committing cdm", ioe);
|
||||
return 0;
|
||||
}
|
||||
|
||||
return nDevices;
|
||||
}
|
||||
|
||||
private void addFormat(Format fin)
|
||||
{
|
||||
Enumeration<Format> enumeration = formats.elements();
|
||||
while (enumeration.hasMoreElements()) {
|
||||
Format format = enumeration.nextElement();
|
||||
if (format.equals(fin))
|
||||
return;
|
||||
}
|
||||
|
||||
//System.err.println("New format = " + fin);
|
||||
formats.addElement(fin);
|
||||
}
|
||||
|
||||
private void doDevice(int index)
|
||||
{
|
||||
|
||||
xilCap = new XILCapture(null);
|
||||
formats = new Vector<Format>();
|
||||
//boolean gotPort = false;
|
||||
|
||||
if (!xilCap.connect(index)) {
|
||||
dummyDevice(index);
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
for (int i = 0; i < ports.length; i++) {
|
||||
if (xilCap.setPort(ports[i])) {
|
||||
getJpegFormats();
|
||||
getRGBFormats();
|
||||
}
|
||||
}
|
||||
xilCap.disconnect();
|
||||
|
||||
if (formats.size() > 0)
|
||||
addDevice(index);
|
||||
else
|
||||
dummyDevice(index);
|
||||
}
|
||||
|
||||
|
||||
private void getRGBFormats()
|
||||
{
|
||||
if (!xilCap.setCompress("RGB"))
|
||||
return;
|
||||
for (int i = 0; i < scales.length; i++) {
|
||||
xilCap.setScale(scales[i]);
|
||||
// To get the real values, start the device
|
||||
if (xilCap.start()) {
|
||||
Dimension size = new Dimension(xilCap.getWidth(),
|
||||
xilCap.getHeight());
|
||||
int stride = xilCap.getLineStride();
|
||||
int maxbuf = stride * size.width;
|
||||
addFormat(new RGBFormat(size, maxbuf, byte[].class,
|
||||
15f,
|
||||
24,
|
||||
3, 2, 1, 3, stride,
|
||||
Format.FALSE,
|
||||
Format.NOT_SPECIFIED));
|
||||
}
|
||||
xilCap.stop();
|
||||
}
|
||||
}
|
||||
|
||||
private void getJpegFormats() {
|
||||
if (!xilCap.setCompress("Jpeg"))
|
||||
return;
|
||||
for (int i = 0; i < scales.length; i++) {
|
||||
xilCap.setScale(scales[i]);
|
||||
// To get the real values, start the device
|
||||
if (xilCap.start()) {
|
||||
Dimension size = new Dimension(xilCap.getWidth(),
|
||||
xilCap.getHeight());
|
||||
// approximate the max for high quality
|
||||
int maxbuf = 3 * size.width * size.height;
|
||||
addFormat(new VideoFormat(VideoFormat.JPEG, size, maxbuf,
|
||||
byte[].class, 15f));
|
||||
}
|
||||
xilCap.stop();
|
||||
}
|
||||
}
|
||||
|
||||
private void dummyDevice(int index)
|
||||
{
|
||||
// Can't get to the device, use the barest formats
|
||||
addFormat(new VideoFormat(VideoFormat.JPEG));
|
||||
addFormat(new RGBFormat());
|
||||
addDevice(index);
|
||||
}
|
||||
|
||||
|
||||
private void addDevice(int index)
|
||||
{
|
||||
|
||||
String name = "SunVideo device " + index;
|
||||
String locator = LOCATOR_PREFIX + index;
|
||||
|
||||
Format [] farray = new Format[formats.size()];
|
||||
Enumeration<Format> enumeration = formats.elements();
|
||||
|
||||
int i = 0;
|
||||
while (enumeration.hasMoreElements()) {
|
||||
Format format = enumeration.nextElement();
|
||||
farray[i++] = format;
|
||||
}
|
||||
|
||||
CaptureDeviceInfo cdi = new CaptureDeviceInfo(name,
|
||||
new MediaLocator(locator), farray);
|
||||
CaptureDeviceManager.addDevice(cdi);
|
||||
}
|
||||
|
||||
public static void main(String [] args)
|
||||
{
|
||||
SunVideoAuto sunVideoAuto = new SunVideoAuto();
|
||||
sunVideoAuto.autoDetectDevices();
|
||||
System.exit(0);
|
||||
}
|
||||
}
|
||||
|
||||
@ -1,456 +0,0 @@
|
||||
/*
|
||||
* SIP Communicator, the OpenSource Java VoIP and Instant Messaging client.
|
||||
*
|
||||
* Distributable under LGPL license.
|
||||
* See terms of license at gnu.org.
|
||||
*
|
||||
* File based on:
|
||||
* @(#)SunVideoPlusAuto.java 1.6 01/03/13
|
||||
* Copyright (c) 1999-2001 Sun Microsystems, Inc. All Rights Reserved.
|
||||
*/
|
||||
package net.java.sip.communicator.impl.media.device;
|
||||
|
||||
import java.io.*;
|
||||
import java.util.*;
|
||||
import javax.media.*;
|
||||
import javax.media.format.*;
|
||||
import javax.media.protocol.*;
|
||||
|
||||
import java.awt.*;
|
||||
|
||||
import com.sun.media.protocol.sunvideoplus.*;
|
||||
import net.java.sip.communicator.util.*;
|
||||
|
||||
/**
|
||||
* SIP Communicator modifications.
|
||||
* @author Emil Ivov
|
||||
*/
|
||||
public class SunVideoPlusAuto
|
||||
{
|
||||
private static final Logger logger
|
||||
= Logger.getLogger(SunVideoPlusAuto.class);
|
||||
|
||||
private static String DEVICE_PREFIX = "/dev/o1k";
|
||||
private static String PROTOCOL = "sunvideoplus";
|
||||
private static String LOCATOR_PREFIX = PROTOCOL + "://";
|
||||
|
||||
private static boolean DO_PAL = false;
|
||||
|
||||
int currentID = -1;
|
||||
|
||||
/**
|
||||
* Removes from the CaptureDeviceManager all currently detected sun video
|
||||
* devices and runs a new detection loop to rediscover those that are
|
||||
* currently available.
|
||||
*
|
||||
* @return the number of devices detected.
|
||||
*/
|
||||
@SuppressWarnings("unchecked") //legacy JMF code.
|
||||
public int autoDetectDevices()
|
||||
{
|
||||
/*
|
||||
* First remove any old entries
|
||||
*/
|
||||
Vector<CaptureDeviceInfo> devices = (Vector) CaptureDeviceManager.
|
||||
getDeviceList(null).clone();
|
||||
Enumeration<CaptureDeviceInfo> enumeration = devices.elements();
|
||||
while (enumeration.hasMoreElements())
|
||||
{
|
||||
CaptureDeviceInfo cdi = enumeration.nextElement();
|
||||
String devName = cdi.getLocator().getProtocol();
|
||||
if (devName.equals(PROTOCOL))
|
||||
CaptureDeviceManager.removeDevice(cdi);
|
||||
}
|
||||
|
||||
int nDevices = 0;
|
||||
for (int i = 0; i < 10; i++)
|
||||
{
|
||||
File fl = new File(DEVICE_PREFIX + i);
|
||||
if (fl.exists())
|
||||
{
|
||||
if (DO_PAL)
|
||||
{
|
||||
generalDevice(i, "PAL");
|
||||
// If generating PAL, do both
|
||||
// Garbage collect to release the PAL datasource
|
||||
// otherwise it sometimes hangs before completing NTSC
|
||||
System.gc();
|
||||
generalDevice(i, "NTSC");
|
||||
}
|
||||
else
|
||||
{
|
||||
generalDevice(i, null);
|
||||
}
|
||||
// No longer generate specific configurations,
|
||||
// let capture preview handle selection.
|
||||
// doDevice(i);
|
||||
nDevices++;
|
||||
}
|
||||
}
|
||||
|
||||
try
|
||||
{
|
||||
CaptureDeviceManager.commit();
|
||||
}
|
||||
catch (java.io.IOException ioe)
|
||||
{
|
||||
logger.error("SunVideoPlusAuto: error committing cdm", ioe);
|
||||
return 0;
|
||||
}
|
||||
|
||||
return nDevices;
|
||||
}
|
||||
|
||||
protected void generalDevice(int id, String signal)
|
||||
{
|
||||
// Add the general device
|
||||
javax.media.protocol.DataSource dsource = null;
|
||||
String url = LOCATOR_PREFIX + id;
|
||||
if (signal != null)
|
||||
url += "////" + signal.toLowerCase();
|
||||
try
|
||||
{
|
||||
dsource = Manager.createDataSource(new MediaLocator(url));
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
}
|
||||
if (dsource != null && dsource instanceof
|
||||
com.sun.media.protocol.sunvideoplus.DataSource)
|
||||
{
|
||||
CaptureDeviceInfo cdi = ( (CaptureDevice) dsource).
|
||||
getCaptureDeviceInfo();
|
||||
if (cdi != null)
|
||||
{
|
||||
String name = cdi.getName();
|
||||
if (signal == null)
|
||||
{
|
||||
CaptureDeviceManager.addDevice(cdi);
|
||||
}
|
||||
else
|
||||
{
|
||||
name = cdi.getName() + " (" + signal + ")";
|
||||
CaptureDeviceManager.addDevice(new CaptureDeviceInfo(name,
|
||||
cdi.getLocator(), cdi.getFormats()));
|
||||
}
|
||||
System.err.println("CaptureDeviceInfo = "
|
||||
+ name + " "
|
||||
+ cdi.getLocator());
|
||||
}
|
||||
dsource.disconnect();
|
||||
}
|
||||
}
|
||||
|
||||
protected void doDevice(int id)
|
||||
{
|
||||
currentID = id;
|
||||
FormatSetup fd = new FormatSetup(currentID);
|
||||
Vector<CaptureDeviceInfo> cdiv = fd.getDeviceInfo();
|
||||
if (cdiv != null && cdiv.size() > 0)
|
||||
{
|
||||
for (int i = 0; i < cdiv.size(); i++)
|
||||
{
|
||||
CaptureDeviceInfo cdi = 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());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static class FormatSetup
|
||||
{
|
||||
|
||||
int id;
|
||||
|
||||
boolean fullVideo = false;
|
||||
boolean anyVideo = true;
|
||||
|
||||
String sAnalog, sPort, sVideoFormat, sSize;
|
||||
|
||||
Hashtable<String, Format> videoFormats = new Hashtable<String, Format>();
|
||||
|
||||
OPICapture opiVidCap = null;
|
||||
|
||||
public FormatSetup(int id)
|
||||
{
|
||||
this.id = id;
|
||||
opiVidCap = new OPICapture(null);
|
||||
if (!opiVidCap.connect(id))
|
||||
{
|
||||
throw new Error("Unable to connect to device");
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
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();
|
||||
System.err.println("Disconnected driver");
|
||||
}
|
||||
|
||||
public void doFormat()
|
||||
{
|
||||
if (anyVideo)
|
||||
{
|
||||
doVideoFormats();
|
||||
}
|
||||
}
|
||||
|
||||
public void doVideoFormats()
|
||||
{
|
||||
if (!anyVideo)
|
||||
{
|
||||
// add a dummy format entry
|
||||
videoFormats.put("off", new VideoFormat(VideoFormat.RGB));
|
||||
}
|
||||
|
||||
sAnalog = "ntsc";
|
||||
if (DO_PAL)
|
||||
sAnalog = "pal";
|
||||
if (!opiVidCap.setSignal(sAnalog))
|
||||
{
|
||||
System.err.println("Video analog signal not recognized");
|
||||
return;
|
||||
}
|
||||
int port = 1;
|
||||
if (!opiVidCap.setPort(port))
|
||||
{
|
||||
System.err.println("Video source not recognized on port");
|
||||
return;
|
||||
}
|
||||
sPort = "" + port;
|
||||
opiVidCap.setScale(2);
|
||||
sSize = "cif";
|
||||
getVideoFormats();
|
||||
}
|
||||
|
||||
private void getVideoFormats()
|
||||
{
|
||||
sVideoFormat = "h261";
|
||||
getH261Format();
|
||||
sVideoFormat = "h263";
|
||||
getH263Format();
|
||||
sVideoFormat = "jpeg";
|
||||
getJpegFormat();
|
||||
sVideoFormat = "rgb";
|
||||
getRGBFormat();
|
||||
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<String> sortedFormats(Hashtable<String, Format> formats)
|
||||
{
|
||||
Vector<String> sorted = new Vector<String>();
|
||||
keyloop:for (Enumeration<String> en = formats.keys();
|
||||
en.hasMoreElements(); )
|
||||
{
|
||||
String key = en.nextElement();
|
||||
for (int i = 0; i < sorted.size(); i++)
|
||||
{
|
||||
if (key.compareTo( sorted.elementAt(i)) < 0)
|
||||
{
|
||||
sorted.insertElementAt(key, i);
|
||||
continue keyloop;
|
||||
}
|
||||
}
|
||||
sorted.addElement(key);
|
||||
}
|
||||
return sorted.elements();
|
||||
}
|
||||
|
||||
public Vector<CaptureDeviceInfo> getDeviceInfo()
|
||||
{
|
||||
doFormat();
|
||||
mydispose();
|
||||
|
||||
String locatorPrefix = LOCATOR_PREFIX + id;
|
||||
Vector<CaptureDeviceInfo> devices = new Vector<CaptureDeviceInfo>();
|
||||
if (anyVideo)
|
||||
{
|
||||
|
||||
for (Enumeration<String> ve = sortedFormats(videoFormats);
|
||||
ve.hasMoreElements(); )
|
||||
{
|
||||
String vKey = ve.nextElement();
|
||||
Format vForm = 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);
|
||||
}
|
||||
}
|
||||
return devices;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
public static void setPALSignal(boolean pal)
|
||||
{
|
||||
DO_PAL = pal;
|
||||
}
|
||||
|
||||
public static void main(String[] args)
|
||||
{
|
||||
if (args.length > 0)
|
||||
{
|
||||
if (args.length > 1)
|
||||
{
|
||||
System.err.println(
|
||||
"Usage: java SunVideoPlusAuto [ ntsc | pal ]");
|
||||
System.exit(1);
|
||||
}
|
||||
if (args[0].equalsIgnoreCase("ntsc"))
|
||||
{
|
||||
SunVideoPlusAuto.setPALSignal(false);
|
||||
}
|
||||
else if (args[0].equalsIgnoreCase("pal"))
|
||||
{
|
||||
SunVideoPlusAuto.setPALSignal(true);
|
||||
}
|
||||
else
|
||||
{
|
||||
System.err.println(
|
||||
"Usage: java SunVideoPlusAuto [ ntsc | pal ]");
|
||||
System.exit(1);
|
||||
}
|
||||
}
|
||||
SunVideoPlusAuto sunVideoPlus = new SunVideoPlusAuto();
|
||||
sunVideoPlus.autoDetectDevices();
|
||||
System.exit(0);
|
||||
}
|
||||
}
|
||||
|
||||
@ -1,110 +0,0 @@
|
||||
/*
|
||||
* SIP Communicator, the OpenSource Java VoIP and Instant Messaging client.
|
||||
*
|
||||
* Distributable under LGPL license.
|
||||
* See terms of license at gnu.org.
|
||||
*
|
||||
* File based on:
|
||||
* @(#)V4LAuto.java 1.2 01/03/13
|
||||
* Copyright (c) 1999-2001 Sun Microsystems, Inc. All Rights Reserved.
|
||||
*/
|
||||
package net.java.sip.communicator.impl.media.device;
|
||||
|
||||
import java.util.*;
|
||||
|
||||
import javax.media.*;
|
||||
|
||||
import net.java.sip.communicator.util.*;
|
||||
|
||||
import com.sun.media.protocol.v4l.*;
|
||||
|
||||
/**
|
||||
* Probes for video capture devices present on linux systems.
|
||||
* @author Emil Ivov
|
||||
*/
|
||||
public class V4LAuto {
|
||||
|
||||
private static final Logger logger = Logger.getLogger(V4LAuto.class);
|
||||
|
||||
/**
|
||||
* Removes from the CaptureDeviceManager all currently detected devices and
|
||||
* runs a new detection loop to rediscover those that are currently
|
||||
* available.
|
||||
*
|
||||
* @return the number of devices detected.
|
||||
*/
|
||||
@SuppressWarnings("unchecked") //JMF legacy code
|
||||
public int autoDetectDevices()
|
||||
{
|
||||
Vector<CaptureDeviceInfo> devices
|
||||
= (Vector) CaptureDeviceManager.getDeviceList(null).clone();
|
||||
Enumeration<CaptureDeviceInfo> enumeration = devices.elements();
|
||||
while (enumeration.hasMoreElements())
|
||||
{
|
||||
CaptureDeviceInfo cdi = enumeration.nextElement();
|
||||
String name = cdi.getName();
|
||||
if (name.startsWith("v4l:"))
|
||||
CaptureDeviceManager.removeDevice(cdi);
|
||||
}
|
||||
|
||||
int nDevices = 0;
|
||||
for (int i = 0; i < 10; i++)
|
||||
{
|
||||
CaptureDeviceInfo cdi = autoDetect(i);
|
||||
if (cdi != null)
|
||||
nDevices++;
|
||||
}
|
||||
|
||||
return nDevices;
|
||||
}
|
||||
/**
|
||||
* Runs a device query for the capture card with the specified card number
|
||||
* and returns its corresponding CaptureDeviceInfo or null if detection
|
||||
* failed or nos such card exists.
|
||||
* @param cardNo the index of the card to discover.
|
||||
* @return the CaptureDeviceInfo corresponsing to the newly discovered
|
||||
* device.
|
||||
*/
|
||||
protected CaptureDeviceInfo autoDetect(int cardNo)
|
||||
{
|
||||
CaptureDeviceInfo cdi = null;
|
||||
try
|
||||
{
|
||||
cdi = new V4LDeviceQuery();
|
||||
|
||||
((V4LDeviceQuery)cdi).sendQuery(cardNo);
|
||||
if ( cdi.getFormats() != null
|
||||
&& cdi.getFormats().length > 0)
|
||||
{
|
||||
// Commit it to disk. Its a new device
|
||||
if (CaptureDeviceManager.addDevice(cdi))
|
||||
{
|
||||
logger.info("Added device " + cdi);
|
||||
CaptureDeviceManager.commit();
|
||||
}
|
||||
}
|
||||
}
|
||||
catch (Throwable thr)
|
||||
{
|
||||
logger.debug("No device for index "
|
||||
+ cardNo + ". "
|
||||
+ thr.getMessage());
|
||||
if (thr instanceof ThreadDeath)
|
||||
throw (ThreadDeath)thr;
|
||||
}
|
||||
|
||||
return cdi;
|
||||
}
|
||||
|
||||
/**
|
||||
* Test method, present for testing only.
|
||||
* @param args String[]
|
||||
*/
|
||||
public static void main(String [] args)
|
||||
{
|
||||
V4LAuto auto = new V4LAuto();
|
||||
auto.autoDetectDevices();
|
||||
System.exit(0);
|
||||
}
|
||||
}
|
||||
|
||||
@ -1,72 +0,0 @@
|
||||
/*
|
||||
* SIP Communicator, the OpenSource Java VoIP and Instant Messaging client.
|
||||
*
|
||||
* Distributable under LGPL license.
|
||||
* See terms of license at gnu.org.
|
||||
*
|
||||
* File based on:
|
||||
* @(#)VFWAuto.java 1.2 01/03/13
|
||||
* Copyright (c) 1999-2001 Sun Microsystems, Inc. All Rights Reserved.
|
||||
*/
|
||||
package net.java.sip.communicator.impl.media.device;
|
||||
|
||||
import java.util.*;
|
||||
import javax.media.*;
|
||||
import com.sun.media.protocol.vfw.*;
|
||||
import net.java.sip.communicator.util.*;
|
||||
|
||||
/**
|
||||
* SIP Communicator modifications
|
||||
* @author Emil Ivov
|
||||
*/
|
||||
public class VFWAuto
|
||||
{
|
||||
private static final Logger logger
|
||||
= Logger.getLogger(VFWAuto.class);
|
||||
|
||||
/**
|
||||
* Removes from the CaptureDeviceManager all currently detected vfw devices
|
||||
* and runs a new detection loop to rediscover those that are currently
|
||||
* available.
|
||||
*
|
||||
* @return the number of devices detected.
|
||||
*/
|
||||
@SuppressWarnings("unchecked") // jmf legacy code
|
||||
public int autoDetectDevices()
|
||||
{
|
||||
Vector<CaptureDeviceInfo> devices
|
||||
= (Vector) CaptureDeviceManager.getDeviceList(null).clone();
|
||||
Enumeration<CaptureDeviceInfo> devicesEnum = devices.elements();
|
||||
|
||||
while (devicesEnum.hasMoreElements())
|
||||
{
|
||||
CaptureDeviceInfo cdi = devicesEnum.nextElement();
|
||||
String name = cdi.getName();
|
||||
if (name.startsWith("vfw:"))
|
||||
CaptureDeviceManager.removeDevice(cdi);
|
||||
}
|
||||
|
||||
int nDevices = 0;
|
||||
for (int i = 0; i < 10; i++)
|
||||
{
|
||||
String name = VFWCapture.capGetDriverDescriptionName(i);
|
||||
if (name != null && name.length() > 1)
|
||||
{
|
||||
logger.debug("Found device " + name);
|
||||
logger.debug("Querying device. Please wait...");
|
||||
com.sun.media.protocol.vfw.VFWSourceStream.autoDetect(i);
|
||||
nDevices++;
|
||||
}
|
||||
}
|
||||
|
||||
return nDevices;
|
||||
}
|
||||
|
||||
public static void main(String [] args)
|
||||
{
|
||||
VFWAuto vfwAuto = new VFWAuto();
|
||||
vfwAuto.autoDetectDevices();
|
||||
System.exit(0);
|
||||
}
|
||||
}
|
||||
|
||||
@ -0,0 +1,159 @@
|
||||
/*
|
||||
* SIP Communicator, the OpenSource Java VoIP and Instant Messaging client.
|
||||
*
|
||||
* Distributable under LGPL license.
|
||||
* See terms of license at gnu.org.
|
||||
*/
|
||||
package net.java.sip.communicator.impl.media.notify;
|
||||
|
||||
import java.net.*;
|
||||
import java.util.*;
|
||||
|
||||
import net.java.sip.communicator.impl.media.*;
|
||||
import net.java.sip.communicator.impl.media.device.*;
|
||||
import net.java.sip.communicator.service.audionotifier.*;
|
||||
|
||||
/**
|
||||
* The implementation of the AudioNotifierService.
|
||||
*
|
||||
* @author Yana Stamcheva
|
||||
*/
|
||||
public class AudioNotifierServiceImpl
|
||||
implements AudioNotifierService
|
||||
{
|
||||
private static final Map<String, SCAudioClipImpl> audioClips =
|
||||
new HashMap<String, SCAudioClipImpl>();
|
||||
|
||||
private boolean isMute;
|
||||
|
||||
/**
|
||||
* Device config to look for notify device.
|
||||
*/
|
||||
private DeviceConfiguration deviceConfiguration;
|
||||
|
||||
/**
|
||||
* Creates audio notify service.
|
||||
* @param deviceConfiguration the device configuration.
|
||||
*/
|
||||
public AudioNotifierServiceImpl(DeviceConfiguration deviceConfiguration)
|
||||
{
|
||||
this.deviceConfiguration = deviceConfiguration;
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates an SCAudioClip from the given URI and adds it to the list of
|
||||
* available audio-s.
|
||||
*
|
||||
* @param uri the path where the audio file could be found
|
||||
*/
|
||||
public SCAudioClipImpl createAudio(String uri)
|
||||
{
|
||||
SCAudioClipImpl audioClip;
|
||||
|
||||
synchronized (audioClips)
|
||||
{
|
||||
if(audioClips.containsKey(uri))
|
||||
{
|
||||
audioClip = audioClips.get(uri);
|
||||
}
|
||||
else
|
||||
{
|
||||
URL url =
|
||||
MediaActivator.getResources().getSoundURLForPath(uri);
|
||||
|
||||
if (url == null)
|
||||
{
|
||||
// Not found by the class loader. Perhaps it's a local file.
|
||||
try
|
||||
{
|
||||
url = new URL(uri);
|
||||
}
|
||||
catch (MalformedURLException e)
|
||||
{
|
||||
//logger.error("The given uri could not be parsed.", e);
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
try
|
||||
{
|
||||
if(getDeviceConfiguration().getAudioSystem().equals(
|
||||
DeviceConfiguration.AUDIO_SYSTEM_JAVASOUND))
|
||||
{
|
||||
audioClip = new JMFAudioClipImpl(url, this);
|
||||
}
|
||||
else if(getDeviceConfiguration().getAudioSystem().equals(
|
||||
DeviceConfiguration.AUDIO_SYSTEM_PORTAUDIO))
|
||||
{
|
||||
audioClip = new PortAudioClipImpl(url, this);
|
||||
}
|
||||
else
|
||||
return null;
|
||||
}
|
||||
catch (Throwable e)
|
||||
{
|
||||
// Cannot create audio to play
|
||||
return null;
|
||||
}
|
||||
|
||||
audioClips.put(uri, audioClip);
|
||||
}
|
||||
}
|
||||
|
||||
return audioClip;
|
||||
}
|
||||
|
||||
/**
|
||||
* Removes the given audio from the list of available audio clips.
|
||||
*
|
||||
* @param audioClip the audio to destroy
|
||||
*/
|
||||
public void destroyAudio(SCAudioClip audioClip)
|
||||
{
|
||||
synchronized (audioClips) {
|
||||
audioClips.remove(audioClip);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Enables or disables the sound in the application. If FALSE, we try to
|
||||
* restore all looping sounds if any.
|
||||
*
|
||||
* @param isMute when TRUE disables the sound, otherwise enables the sound.
|
||||
*/
|
||||
public void setMute(boolean isMute)
|
||||
{
|
||||
this.isMute = isMute;
|
||||
|
||||
for (SCAudioClipImpl audioClip : audioClips.values())
|
||||
{
|
||||
if (isMute)
|
||||
{
|
||||
audioClip.internalStop();
|
||||
}
|
||||
else if (audioClip.isLooping())
|
||||
{
|
||||
audioClip.playInLoop(audioClip.getLoopInterval());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns TRUE if the sound is currently disabled, FALSE otherwise.
|
||||
* @return TRUE if the sound is currently disabled, FALSE otherwise
|
||||
*/
|
||||
public boolean isMute()
|
||||
{
|
||||
return isMute;
|
||||
}
|
||||
|
||||
/**
|
||||
* The device configuration.
|
||||
*
|
||||
* @return the deviceConfiguration
|
||||
*/
|
||||
public DeviceConfiguration getDeviceConfiguration()
|
||||
{
|
||||
return deviceConfiguration;
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,201 @@
|
||||
/*
|
||||
* SIP Communicator, the OpenSource Java VoIP and Instant Messaging client.
|
||||
*
|
||||
* Distributable under LGPL license.
|
||||
* See terms of license at gnu.org.
|
||||
*/
|
||||
package net.java.sip.communicator.impl.media.notify;
|
||||
|
||||
import java.applet.*;
|
||||
import java.awt.event.*;
|
||||
import java.io.*;
|
||||
import java.lang.reflect.*;
|
||||
import java.net.*;
|
||||
import java.security.*;
|
||||
|
||||
import javax.swing.*;
|
||||
|
||||
import net.java.sip.communicator.service.audionotifier.*;
|
||||
|
||||
/**
|
||||
* Implementation of SCAudioClip.
|
||||
*
|
||||
* @author Yana Stamcheva
|
||||
*/
|
||||
public class JMFAudioClipImpl
|
||||
extends SCAudioClipImpl
|
||||
implements ActionListener
|
||||
|
||||
{
|
||||
private static Constructor<AudioClip> acConstructor = null;
|
||||
|
||||
private final Timer playAudioTimer = new Timer(1000, null);
|
||||
|
||||
private final AudioClip audioClip;
|
||||
|
||||
private final AudioNotifierService audioNotifier;
|
||||
|
||||
/**
|
||||
* Creates the audio clip and initialize the listener used from the
|
||||
* loop timer.
|
||||
*
|
||||
* @param url the url pointing to the audio file
|
||||
* @param audioNotifier the audio notify service
|
||||
* @throws IOException cannot audio clip with supplied url.
|
||||
*/
|
||||
public JMFAudioClipImpl(URL url, AudioNotifierService audioNotifier)
|
||||
throws IOException
|
||||
{
|
||||
this.audioClip = createAppletAudioClip(url.openStream());
|
||||
this.audioNotifier = audioNotifier;
|
||||
|
||||
this.playAudioTimer.addActionListener(this);
|
||||
}
|
||||
|
||||
/**
|
||||
* Plays this audio.
|
||||
*/
|
||||
public void play()
|
||||
{
|
||||
if ((audioClip != null) && !audioNotifier.isMute())
|
||||
audioClip.play();
|
||||
}
|
||||
|
||||
/**
|
||||
* Plays this audio in loop.
|
||||
*
|
||||
* @param interval the loop interval
|
||||
*/
|
||||
public void playInLoop(int interval)
|
||||
{
|
||||
if(!audioNotifier.isMute())
|
||||
{
|
||||
if(interval == 0)
|
||||
audioClip.loop();
|
||||
else
|
||||
{
|
||||
//first play the audio and then start the timer and wait
|
||||
audioClip.play();
|
||||
playAudioTimer.setDelay(interval);
|
||||
playAudioTimer.setRepeats(true);
|
||||
|
||||
playAudioTimer.start();
|
||||
}
|
||||
}
|
||||
|
||||
setLoopInterval(interval);
|
||||
setIsLooping(true);
|
||||
}
|
||||
|
||||
/**
|
||||
* Stops this audio.
|
||||
*/
|
||||
public void stop()
|
||||
{
|
||||
if (audioClip != null)
|
||||
audioClip.stop();
|
||||
|
||||
if (isLooping())
|
||||
{
|
||||
playAudioTimer.stop();
|
||||
setIsLooping(false);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Stops this audio without setting the isLooping property in the case of
|
||||
* a looping audio. The AudioNotifier uses this method to stop the audio
|
||||
* when setMute(true) is invoked. This allows us to restore all looping
|
||||
* audios when the sound is restored by calling setMute(false).
|
||||
*/
|
||||
public void internalStop()
|
||||
{
|
||||
if (audioClip != null)
|
||||
audioClip.stop();
|
||||
|
||||
if (isLooping())
|
||||
playAudioTimer.stop();
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates an AppletAudioClip.
|
||||
*
|
||||
* @param inputstream the audio input stream
|
||||
* @throws IOException
|
||||
*/
|
||||
private static AudioClip createAppletAudioClip(InputStream inputstream)
|
||||
throws IOException
|
||||
{
|
||||
if (acConstructor == null)
|
||||
{
|
||||
try
|
||||
{
|
||||
acConstructor
|
||||
= AccessController.doPrivileged(
|
||||
new PrivilegedExceptionAction<Constructor<AudioClip>>()
|
||||
{
|
||||
public Constructor<AudioClip> run()
|
||||
throws ClassNotFoundException,
|
||||
NoSuchMethodException,
|
||||
SecurityException
|
||||
{
|
||||
return createAcConstructor();
|
||||
}
|
||||
});
|
||||
}
|
||||
catch (PrivilegedActionException paex)
|
||||
{
|
||||
throw
|
||||
new IOException(
|
||||
"Failed to get AudioClip constructor: "
|
||||
+ paex.getException());
|
||||
}
|
||||
}
|
||||
|
||||
try
|
||||
{
|
||||
return acConstructor.newInstance(inputstream);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
throw new IOException("Failed to construct the AudioClip: " + ex);
|
||||
}
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
private static Constructor<AudioClip> createAcConstructor()
|
||||
throws ClassNotFoundException,
|
||||
NoSuchMethodException,
|
||||
SecurityException
|
||||
{
|
||||
Class<?> class1;
|
||||
try
|
||||
{
|
||||
class1
|
||||
= Class.forName(
|
||||
"com.sun.media.sound.JavaSoundAudioClip",
|
||||
true,
|
||||
ClassLoader.getSystemClassLoader());
|
||||
}
|
||||
catch (ClassNotFoundException cnfex)
|
||||
{
|
||||
class1
|
||||
= Class.forName("sun.audio.SunAudioClip", true, null);
|
||||
}
|
||||
return
|
||||
(Constructor<AudioClip>) class1.getConstructor(InputStream.class);
|
||||
}
|
||||
|
||||
/**
|
||||
* Plays an audio clip. Used in the playAudioTimer to play an audio in loop.
|
||||
* @param e the event.
|
||||
*/
|
||||
public void actionPerformed(ActionEvent e)
|
||||
{
|
||||
if (audioClip != null)
|
||||
{
|
||||
audioClip.stop();
|
||||
audioClip.play();
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,204 @@
|
||||
/*
|
||||
* SIP Communicator, the OpenSource Java VoIP and Instant Messaging client.
|
||||
*
|
||||
* Distributable under LGPL license.
|
||||
* See terms of license at gnu.org.
|
||||
*/
|
||||
package net.java.sip.communicator.impl.media.notify;
|
||||
|
||||
import java.io.*;
|
||||
import java.net.*;
|
||||
|
||||
import javax.sound.sampled.*;
|
||||
|
||||
import net.java.sip.communicator.impl.media.protocol.portaudio.*;
|
||||
import net.java.sip.communicator.impl.media.device.*;
|
||||
import net.java.sip.communicator.util.*;
|
||||
|
||||
/**
|
||||
* Implementation of SCAudioClip using PortAudio.
|
||||
*
|
||||
* @author Damian Minkov
|
||||
*/
|
||||
public class PortAudioClipImpl
|
||||
extends SCAudioClipImpl
|
||||
implements PropertyChangeListener
|
||||
{
|
||||
private static final Logger logger
|
||||
= Logger.getLogger(PortAudioClipImpl.class);
|
||||
|
||||
private final AudioNotifierServiceImpl audioNotifier;
|
||||
|
||||
private Thread playThread = new Thread(new PlayThread());
|
||||
|
||||
private boolean started = false;
|
||||
|
||||
private long portAudioStream = 0;
|
||||
|
||||
private URL url = null;
|
||||
|
||||
/**
|
||||
* Creates the audio clip and initialize the listener used from the
|
||||
* loop timer.
|
||||
*
|
||||
* @param url the url pointing to the audio file
|
||||
* @param audioNotifier the audio notify service
|
||||
* @throws IOException cannot audio clip with supplied url.
|
||||
*/
|
||||
public PortAudioClipImpl(URL url, AudioNotifierServiceImpl audioNotifier)
|
||||
throws IOException
|
||||
{
|
||||
this.audioNotifier = audioNotifier;
|
||||
this.url = url;
|
||||
|
||||
audioNotifier.getDeviceConfiguration().addPropertyChangeListener(this);
|
||||
}
|
||||
|
||||
/**
|
||||
* Plays this audio.
|
||||
*/
|
||||
public void play()
|
||||
{
|
||||
if ((url != null) && !audioNotifier.isMute())
|
||||
{
|
||||
started = true;
|
||||
playThread.start();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Plays this audio in loop.
|
||||
*
|
||||
* @param interval the loop interval
|
||||
*/
|
||||
public void playInLoop(int interval)
|
||||
{
|
||||
setLoopInterval(interval);
|
||||
setIsLooping(true);
|
||||
|
||||
if(!audioNotifier.isMute())
|
||||
{
|
||||
started = true;
|
||||
playThread.start();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Stops this audio.
|
||||
*/
|
||||
public void stop()
|
||||
{
|
||||
if (url != null)
|
||||
started = false;
|
||||
setIsLooping(false);
|
||||
}
|
||||
|
||||
/**
|
||||
* Stops this audio without setting the isLooping property in the case of
|
||||
* a looping audio. The AudioNotifier uses this method to stop the audio
|
||||
* when setMute(true) is invoked. This allows us to restore all looping
|
||||
* audios when the sound is restored by calling setMute(false).
|
||||
*/
|
||||
public void internalStop()
|
||||
{
|
||||
if (url != null)
|
||||
started = false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Notified when device configuration has changed.
|
||||
* @param evt the event of the change
|
||||
*/
|
||||
public void propertyChange(PropertyChangeEvent evt)
|
||||
{
|
||||
if(evt.getPropertyName().equals(
|
||||
DeviceConfiguration.AUDIO_NOTIFY_DEVICE))
|
||||
{
|
||||
// make the stream 0, to be sure next time the new
|
||||
// device will be used
|
||||
portAudioStream = 0;
|
||||
}
|
||||
}
|
||||
|
||||
private class PlayThread
|
||||
implements Runnable
|
||||
{
|
||||
byte[] buffer = new byte[1024];
|
||||
|
||||
public void run()
|
||||
{
|
||||
try
|
||||
{
|
||||
while(true)
|
||||
{
|
||||
if (portAudioStream == 0)
|
||||
{
|
||||
long streamParameters
|
||||
= PortAudio.PaStreamParameters_new(
|
||||
PortAudioStream.getDeviceIndexFromLocator(
|
||||
audioNotifier.getDeviceConfiguration().
|
||||
getAudioNotifyDevice().getLocator()),
|
||||
2,
|
||||
PortAudio.SAMPLE_FORMAT_INT16);
|
||||
|
||||
portAudioStream
|
||||
= PortAudio.Pa_OpenStream(
|
||||
0,
|
||||
streamParameters,
|
||||
48000,
|
||||
PortAudio.FRAMES_PER_BUFFER_UNSPECIFIED,
|
||||
PortAudio.STREAM_FLAGS_NO_FLAG,
|
||||
null);
|
||||
|
||||
PortAudio.Pa_StartStream(portAudioStream);
|
||||
}
|
||||
|
||||
AudioInputStream audioStream =
|
||||
AudioSystem.getAudioInputStream(url);
|
||||
|
||||
if(!started)
|
||||
{
|
||||
PortAudio.Pa_CloseStream(portAudioStream);
|
||||
return;
|
||||
}
|
||||
|
||||
int read = 0;
|
||||
while((read = audioStream.read(buffer)) != -1)
|
||||
{
|
||||
PortAudio.Pa_WriteStream(
|
||||
portAudioStream,
|
||||
buffer,
|
||||
buffer.length/audioStream.getFormat().getFrameSize());
|
||||
}
|
||||
|
||||
if(!isLooping())
|
||||
{
|
||||
PortAudio.Pa_CloseStream(portAudioStream);
|
||||
break;
|
||||
}
|
||||
else
|
||||
{
|
||||
Thread.sleep(getLoopInterval());
|
||||
}
|
||||
}
|
||||
}
|
||||
catch (PortAudioException e)
|
||||
{
|
||||
logger.error(
|
||||
"Cannot open portaudio device for notifications", e);
|
||||
}
|
||||
catch (IOException e)
|
||||
{
|
||||
logger.error("Error reading from audio resource", e);
|
||||
}
|
||||
catch (InterruptedException e)
|
||||
{
|
||||
logger.error("Cannot wait the interval between plays", e);
|
||||
}
|
||||
catch (UnsupportedAudioFileException e)
|
||||
{
|
||||
logger.error("Unknown file format", e);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,94 @@
|
||||
/*
|
||||
* SIP Communicator, the OpenSource Java VoIP and Instant Messaging client.
|
||||
*
|
||||
* Distributable under LGPL license.
|
||||
* See terms of license at gnu.org.
|
||||
*/
|
||||
package net.java.sip.communicator.impl.media.notify;
|
||||
|
||||
import net.java.sip.communicator.service.audionotifier.*;
|
||||
|
||||
/**
|
||||
* Common properties impl for SCAudioClip.
|
||||
*
|
||||
* @author Damian Minkov
|
||||
*/
|
||||
public abstract class SCAudioClipImpl
|
||||
implements SCAudioClip
|
||||
{
|
||||
private boolean isLooping;
|
||||
|
||||
private int loopInterval;
|
||||
|
||||
private boolean isInvalid;
|
||||
|
||||
/**
|
||||
* Returns TRUE if this audio is invalid, FALSE otherwise.
|
||||
*
|
||||
* @return TRUE if this audio is invalid, FALSE otherwise
|
||||
*/
|
||||
public boolean isInvalid()
|
||||
{
|
||||
return isInvalid;
|
||||
}
|
||||
|
||||
/**
|
||||
* Marks this audio as invalid or not.
|
||||
*
|
||||
* @param isInvalid TRUE to mark this audio as invalid, FALSE otherwise
|
||||
*/
|
||||
public void setInvalid(boolean isInvalid)
|
||||
{
|
||||
this.setIsInvalid(isInvalid);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns TRUE if this audio is currently playing in loop, FALSE otherwise.
|
||||
* @return TRUE if this audio is currently playing in loop, FALSE otherwise.
|
||||
*/
|
||||
public boolean isLooping()
|
||||
{
|
||||
return isLooping;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the loop interval if this audio is looping.
|
||||
* @return the loop interval if this audio is looping
|
||||
*/
|
||||
public int getLoopInterval()
|
||||
{
|
||||
return loopInterval;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param isLooping the isLooping to set
|
||||
*/
|
||||
public void setIsLooping(boolean isLooping)
|
||||
{
|
||||
this.isLooping = isLooping;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param loopInterval the loopInterval to set
|
||||
*/
|
||||
public void setLoopInterval(int loopInterval)
|
||||
{
|
||||
this.loopInterval = loopInterval;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param isInvalid the isInvalid to set
|
||||
*/
|
||||
public void setIsInvalid(boolean isInvalid)
|
||||
{
|
||||
this.isInvalid = isInvalid;
|
||||
}
|
||||
|
||||
/**
|
||||
* Stops this audio without setting the isLooping property in the case of
|
||||
* a looping audio. The AudioNotifier uses this method to stop the audio
|
||||
* when setMute(true) is invoked. This allows us to restore all looping
|
||||
* audios when the sound is restored by calling setMute(false).
|
||||
*/
|
||||
public abstract void internalStop();
|
||||
}
|
||||
Loading…
Reference in new issue