/**
* WebcamStudio for GNU/Linux
* Copyright (C) 2008 Patrick Balleux
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
*
*/
package webcamstudio.exporter.vloopback;
import com.sun.jna.Library;
import com.sun.jna.Native;
import com.sun.jna.Platform;
import java.io.File;
import java.util.ArrayList;
/**
*
* @author pballeux
*/
public class VideoDevice {
static final int O_RDWR = 2;
static final int VIDIOCGCAP = -2143521279;
static final int VIDIOC_QUERYCAP = -2140645888;
public static VideoDevice[] getInputDevices() {
VideoDevice[] d = new VideoDevice[0];
VideoDevice[] dAll = new VideoDevice[0];
ArrayList<VideoDevice> devices = new ArrayList<>();
dAll = getDevices();
for (VideoDevice dAll1 : dAll) {
if (dAll1.getType() == Type.Input || dAll1.getType() == Type.InputOutput) {
devices.add(dAll1);
}
}
d = new VideoDevice[devices.size()];
for (int i = 0; i < d.length; i++) {
d[i] = devices.get(i);
}
devices.clear();
devices = null;
return d;
}
public static VideoDevice[] getOutputDevices() {
VideoDevice[] d = new VideoDevice[0];
VideoDevice[] dAll = new VideoDevice[0];
ArrayList<VideoDevice> devices = new ArrayList<>();
dAll = getDevices();
for (VideoDevice dAll1 : dAll) {
if (dAll1.getType() == Type.Output) {
devices.add(dAll1);
}
}
d = new VideoDevice[devices.size()];
for (int i = 0; i < d.length; i++) {
d[i] = devices.get(i);
}
devices.clear();
devices = null;
return d;
}
public static VideoDevice[] getDevices() {
VideoDevice[] d = new VideoDevice[0];
File[] fs = new File("/dev/").listFiles();
ArrayList<VideoDevice> devices = new ArrayList<>();
if (fs != null) {
for (File f : fs) {
if (f.getName().startsWith("video") && !f.isDirectory()) {
devices.add(new VideoDevice(f.getAbsolutePath()));
}
}
}
d = new VideoDevice[devices.size()];
for (int i = 0; i < d.length; i++) {
d[i] = devices.get(i);
}
devices.clear();
devices = null;
return d;
}
private Version version = Version.Unknown;
private Type type = Type.Unknown;
private String name = "";
private File device = null;
private int deviceFD = 0;
public VideoDevice(String name) {
device = new File(name);
loadInfo();
}
private void loadInfo() {
openDevice();
initDevice();
closeDevice();
}
private void openDevice() {
deviceFD = CLibrary.INSTANCE.open(device.getAbsolutePath(), 4002);
}
private void initDevice() {
video_capability.ByReference vid_caps = new video_capability.ByReference();
v4l2_capability.ByReference v4l2_caps = new v4l2_capability.ByReference();
if (CLibrary.INSTANCE.ioctl(deviceFD, VIDIOC_QUERYCAP, v4l2_caps) == 0) {
version = Version.V4L2;
// System.out.println("Cap="+(v4l2_caps.capabilities & 3));
if ((v4l2_caps.capabilities & 3) == 3) {
type = Type.InputOutput;
} else if ((v4l2_caps.capabilities & 1) == 1) {
type = Type.Output;
} else if ((v4l2_caps.capabilities & 2) == 2) {
type = Type.Input;
} else {
type = Type.Unknown;
}
// String longName = name = new String(v4l2_caps.card).trim();
// System.out.println("Name="+longName);
name = new String(v4l2_caps.card).trim() + " ("+device.getName().replace("video", "")+")";
} else if (CLibrary.INSTANCE.ioctl(deviceFD, VIDIOCGCAP, vid_caps) == 0) {
version = Version.V4L;
if ((vid_caps.type & 1) == 1) {
type = Type.Output;
} else {
type = Type.Input;
}
name = new String(vid_caps.name);
if (name.indexOf(0) >= 0) {
name = name.substring(0, name.indexOf(0));
}
}
}
public Version getVersion() {
return version;
}
public Type getType() {
return type;
}
public String getName() {
return name;
}
public File getFile() {
return device;
}
@Override
public String toString() {
return name;
}
private void closeDevice() {
CLibrary.INSTANCE.close(deviceFD);
}
public enum Type {
Input, Output, InputOutput, Unknown
}
public enum Version {
V4L, V4L2, Unknown
}
public interface CLibrary extends Library {
CLibrary INSTANCE = (CLibrary) Native.loadLibrary((Platform.isWindows() ? "msvcrt" : "c"),
CLibrary.class);
void printf(String format, Object... args);
int open(String device, int mode);
void close(int device);
int ioctl(int device, int command, Object struct);
String strerr(int no);
int write(int device, byte[] buffer, int count);
}
}