Files
swt-cctv/src/main/java/io/swtc/CCTVManager.java
2026-01-04 18:13:21 +01:00

192 lines
7.3 KiB
Java

package io.swtc;
import com.github.sarxos.webcam.Webcam;
import com.github.sarxos.webcam.WebcamCompositeDriver;
import com.github.sarxos.webcam.ds.buildin.WebcamDefaultDriver;
import com.github.sarxos.webcam.ds.ipcam.IpCamDeviceRegistry;
import com.github.sarxos.webcam.ds.ipcam.IpCamDriver;
import com.github.sarxos.webcam.ds.ipcam.IpCamMode;
import io.swtc.networking.CameraConfig;
import io.swtc.networking.CameraSettings;
import org.eclipse.swt.SWT;
import org.eclipse.swt.graphics.Font;
import org.eclipse.swt.layout.GridData;
import org.eclipse.swt.layout.GridLayout;
import org.eclipse.swt.widgets.*;
import java.net.MalformedURLException;
import java.util.List;
public class CCTVManager {
static {
Webcam.setDriver(new WebcamCompositeDriver() {{
add(new WebcamDefaultDriver());
add(new IpCamDriver());
}});
for (CameraConfig config : CameraSettings.load()) {
try {
IpCamDeviceRegistry.register(config.getName(), config.getUrl(), IpCamMode.PUSH);
} catch (MalformedURLException e) {
e.printStackTrace();
}
}
}
public static void main(String[] args) {
Display display = new Display();
Shell shell = new Shell(display);
shell.setText("Dashboard");
shell.setSize(900, 600);
renderUI(shell, display);
shell.open();
while (!shell.isDisposed()) {
if (!display.readAndDispatch()) display.sleep();
}
display.dispose();
}
private static void renderUI(Shell shell, Display display) {
// Clear existing children if refreshing
for (Control child : shell.getChildren()) child.dispose();
List<Webcam> webcams = Webcam.getWebcams();
int columnCount = Math.min(3, Math.max(1, webcams.size()));
GridLayout mainLayout = new GridLayout(columnCount, true);
mainLayout.marginWidth = 20;
mainLayout.marginHeight = 20;
shell.setLayout(mainLayout);
// Header Section
Composite header = new Composite(shell, SWT.NONE);
header.setLayout(new GridLayout(2, false));
header.setLayoutData(new GridData(SWT.FILL, SWT.CENTER, true, false, columnCount, 1));
Label title = new Label(header, SWT.NONE);
title.setText("Connected Devices (" + webcams.size() + ")");
title.setFont(new Font(display, "Segoe UI", 16, SWT.BOLD));
title.setLayoutData(new GridData(SWT.FILL, SWT.CENTER, true, false));
Button addBtn = new Button(header, SWT.PUSH);
addBtn.setText("+ Add IP Camera");
addBtn.addListener(SWT.Selection, e -> showAddCameraDialog(shell, display));
if (webcams.isEmpty()) {
Label note = new Label(shell, SWT.NONE);
note.setText("No cameras detected. Add an IP camera to begin.");
} else {
for (Webcam webcam : webcams) {
createCameraCard(shell, display, webcam);
}
}
shell.layout(true, true);
}
private static void createCameraCard(Composite parent, Display display, Webcam webcam) {
// We check if its a IP Cam by getting the class, if it is then we show the delete button
boolean isIpCam = webcam.getDevice().getClass().getSimpleName().contains("IpCam");
Group card = new Group(parent, SWT.NONE);
card.setText(webcam.getName());
card.setLayout(new GridLayout(2, false));
card.setLayoutData(new GridData(SWT.FILL, SWT.TOP, true, false));
Label info = new Label(card, SWT.WRAP);
info.setText("Type: " + (isIpCam ? "Network IP" : "Local USB"));
info.setLayoutData(new GridData(SWT.FILL, SWT.CENTER, true, false, 2, 1));
Button viewBtn = new Button(card, SWT.PUSH);
viewBtn.setText("Launch");
viewBtn.setLayoutData(new GridData(SWT.FILL, SWT.CENTER, true, false));
viewBtn.addListener(SWT.Selection, e -> new CameraWindow(display, webcam).open());
Button deleteBtn = new Button(card, SWT.PUSH);
deleteBtn.setText("Delete");
deleteBtn.setLayoutData(new GridData(SWT.FILL, SWT.CENTER, true, false));
// this is where we do that, this is where the ipcam class is used
deleteBtn.setEnabled(isIpCam);
deleteBtn.addListener(SWT.Selection, e -> {
MessageBox mb = new MessageBox(parent.getShell(), SWT.ICON_QUESTION | SWT.YES | SWT.NO);
mb.setText("Confirm");
mb.setMessage("Remove " + webcam.getName() + "?");
if (mb.open() == SWT.YES) {
CameraSettings.delete(webcam.getName());
IpCamDeviceRegistry.unregister(webcam.getName());
renderUI(parent.getShell(), display);
}
});
}
private static void showAddCameraDialog(Shell parent, Display display) {
Shell dialog = new Shell(parent, SWT.DIALOG_TRIM | SWT.APPLICATION_MODAL);
dialog.setText("Register New IP Camera");
dialog.setLayout(new GridLayout(2, false));
new Label(dialog, SWT.NONE).setText("Name:");
Text nameIn = new Text(dialog, SWT.BORDER);
nameIn.setLayoutData(new GridData(SWT.FILL, SWT.CENTER, true, false));
new Label(dialog, SWT.NONE).setText("MJPEG URL:");
Text urlIn = new Text(dialog, SWT.BORDER);
urlIn.setLayoutData(new GridData(SWT.FILL, SWT.CENTER, true, false));
urlIn.setMessage("http://10.0.0.x/mjpeg");
// Error message label
Label errorLabel = new Label(dialog, SWT.NONE);
errorLabel.setForeground(display.getSystemColor(SWT.COLOR_RED));
errorLabel.setLayoutData(new GridData(SWT.FILL, SWT.CENTER, true, false, 2, 1));
errorLabel.setVisible(false);
Button save = new Button(dialog, SWT.PUSH);
save.setText("Add Camera");
save.setLayoutData(new GridData(SWT.FILL, SWT.CENTER, true, false, 2, 1));
// error handling for stoopid people
save.addListener(SWT.Selection, e -> {
String name = nameIn.getText().trim();
String urlString = urlIn.getText().trim();
if (name.isEmpty() || urlString.isEmpty()) {
errorLabel.setText("Error: All fields are required.");
errorLabel.setVisible(true);
dialog.pack();
return;
}
try {
if (!urlString.toLowerCase().startsWith("http://") && !urlString.toLowerCase().startsWith("https://")) {
throw new MalformedURLException("URL must start with http:// or https://");
}
java.net.URL validatedUrl = new java.net.URL(urlString);
IpCamDeviceRegistry.register(name, validatedUrl.toExternalForm(), IpCamMode.PUSH);
CameraSettings.save(new CameraConfig(name, validatedUrl.toExternalForm()));
dialog.close();
renderUI(parent, display);
} catch (MalformedURLException ex) {
errorLabel.setText("Invalid URL: " + ex.getMessage());
errorLabel.setVisible(true);
dialog.pack();
} catch (Exception ex) {
errorLabel.setText("Registration failed: " + ex.getMessage());
errorLabel.setVisible(true);
dialog.pack();
}
});
dialog.pack();
dialog.open();
}
}