Use global thread pool instead of creating new threads

This commit is contained in:
0xb00bface 2021-01-10 22:14:20 +01:00
parent ec9c463f80
commit 967b5dec42
34 changed files with 283 additions and 373 deletions

View File

@ -28,11 +28,10 @@ public class ExternalBrowser implements AutoCloseable {
private static final ExternalBrowser INSTANCE = new ExternalBrowser(); private static final ExternalBrowser INSTANCE = new ExternalBrowser();
private Lock lock = new ReentrantLock(); private Lock lock = new ReentrantLock();
private Process p;
private Consumer<String> messageListener; private Consumer<String> messageListener;
private InputStream in; private InputStream in;
private OutputStream out; private OutputStream out;
private Socket socket; private Socket socket; // NOSONAR
private Thread reader; private Thread reader;
private volatile boolean stopped = true; private volatile boolean stopped = true;
private volatile boolean browserReady = false; private volatile boolean browserReady = false;
@ -53,10 +52,10 @@ public class ExternalBrowser implements AutoCloseable {
File configDir = new File(Config.getInstance().getConfigDir(), "ctbrec-minimal-browser"); File configDir = new File(Config.getInstance().getConfigDir(), "ctbrec-minimal-browser");
String[] cmdline = OS.getBrowserCommand(configDir.getCanonicalPath()); String[] cmdline = OS.getBrowserCommand(configDir.getCanonicalPath());
p = new ProcessBuilder(cmdline).start(); Process p = new ProcessBuilder(cmdline).start();
if (LOG.isTraceEnabled()) { if (LOG.isTraceEnabled()) {
new Thread(new StreamRedirector(p.getInputStream(), System.out)).start(); new Thread(new StreamRedirector(p.getInputStream(), System.out)).start(); // NOSONAR
new Thread(new StreamRedirector(p.getErrorStream(), System.err)).start(); new Thread(new StreamRedirector(p.getErrorStream(), System.err)).start(); // NOSONAR
} else { } else {
new Thread(new StreamRedirector(p.getInputStream(), OutputStream.nullOutputStream())).start(); new Thread(new StreamRedirector(p.getInputStream(), OutputStream.nullOutputStream())).start();
new Thread(new StreamRedirector(p.getErrorStream(), OutputStream.nullOutputStream())).start(); new Thread(new StreamRedirector(p.getErrorStream(), OutputStream.nullOutputStream())).start();
@ -81,7 +80,6 @@ public class ExternalBrowser implements AutoCloseable {
LOG.debug("Waiting for browser to terminate"); LOG.debug("Waiting for browser to terminate");
p.waitFor(); p.waitFor();
int exitValue = p.exitValue(); int exitValue = p.exitValue();
p = null;
reader = null; reader = null;
in = null; in = null;
out = null; out = null;
@ -119,7 +117,6 @@ public class ExternalBrowser implements AutoCloseable {
} }
public void executeJavaScript(String javaScript) throws IOException { public void executeJavaScript(String javaScript) throws IOException {
//LOG.debug("Executing JS {}", javaScript);
JSONObject script = new JSONObject(); JSONObject script = new JSONObject();
script.put("execute", javaScript); script.put("execute", javaScript);
out.write(script.toString().getBytes(UTF_8)); out.write(script.toString().getBytes(UTF_8));
@ -141,8 +138,7 @@ public class ExternalBrowser implements AutoCloseable {
private void readBrowserOutput() { private void readBrowserOutput() {
LOG.debug("Browser output reader started"); LOG.debug("Browser output reader started");
try { try (BufferedReader br = new BufferedReader(new InputStreamReader(in))) {
BufferedReader br = new BufferedReader(new InputStreamReader(in));
String line; String line;
synchronized (browserReadyLock) { synchronized (browserReadyLock) {
browserReady = true; browserReady = true;
@ -150,13 +146,10 @@ public class ExternalBrowser implements AutoCloseable {
} }
while( !Thread.interrupted() && (line = br.readLine()) != null ) { while( !Thread.interrupted() && (line = br.readLine()) != null ) {
LOG.debug("Browser output: {}", line); LOG.debug("Browser output: {}", line);
if(!line.startsWith("{")) { if (line.startsWith("{") && messageListener != null) {
} else {
if(messageListener != null) {
messageListener.accept(line); messageListener.accept(line);
} }
} }
}
} catch (IOException e) { } catch (IOException e) {
if(!stopped) { if(!stopped) {
LOG.error("Couldn't read browser output", e); LOG.error("Couldn't read browser output", e);

View File

@ -166,12 +166,10 @@ public class Player {
// create threads, which read stdout and stderr of the player process. these are needed, // create threads, which read stdout and stderr of the player process. these are needed,
// because otherwise the internal buffer for these streams fill up and block the process // because otherwise the internal buffer for these streams fill up and block the process
Thread std = new Thread(new StreamRedirector(playerProcess.getInputStream(), OutputStream.nullOutputStream())); Thread std = new Thread(new StreamRedirector(playerProcess.getInputStream(), OutputStream.nullOutputStream()));
//Thread std = new Thread(new StreamRedirectThread(playerProcess.getInputStream(), System.out));
std.setName("Player stdout pipe"); std.setName("Player stdout pipe");
std.setDaemon(true); std.setDaemon(true);
std.start(); std.start();
Thread err = new Thread(new StreamRedirector(playerProcess.getErrorStream(), OutputStream.nullOutputStream())); Thread err = new Thread(new StreamRedirector(playerProcess.getErrorStream(), OutputStream.nullOutputStream()));
//Thread err = new Thread(new StreamRedirectThread(playerProcess.getErrorStream(), System.err));
err.setName("Player stderr pipe"); err.setName("Player stderr pipe");
err.setDaemon(true); err.setDaemon(true);
err.start(); err.start();

View File

@ -22,7 +22,7 @@ import javafx.scene.layout.StackPane;
import javafx.stage.Popup; import javafx.stage.Popup;
public class PreviewPopupHandler implements EventHandler<MouseEvent> { public class PreviewPopupHandler implements EventHandler<MouseEvent> {
private static final transient Logger LOG = LoggerFactory.getLogger(PreviewPopupHandler.class); private static final Logger LOG = LoggerFactory.getLogger(PreviewPopupHandler.class);
private static final int offset = 10; private static final int offset = 10;
private long timeForPopupOpen = TimeUnit.SECONDS.toMillis(1); private long timeForPopupOpen = TimeUnit.SECONDS.toMillis(1);
@ -67,11 +67,11 @@ public class PreviewPopupHandler implements EventHandler<MouseEvent> {
} else if(event.getEventType() == MouseEvent.MOUSE_ENTERED) { } else if(event.getEventType() == MouseEvent.MOUSE_ENTERED) {
popup.setX(event.getScreenX()+ offset); popup.setX(event.getScreenX()+ offset);
popup.setY(event.getScreenY()+ offset); popup.setY(event.getScreenY()+ offset);
JavaFxModel model = getModel(event); JavaFxModel newModel = getModel(event);
if(model != null) { if(newModel != null) {
closeCountdown = -1; closeCountdown = -1;
boolean modelChanged = model != this.model; boolean modelChanged = newModel != this.model;
this.model = model; this.model = newModel;
if(popup.isShowing()) { if(popup.isShowing()) {
openCountdown = -1; openCountdown = -1;
if(modelChanged) { if(modelChanged) {
@ -97,15 +97,15 @@ public class PreviewPopupHandler implements EventHandler<MouseEvent> {
@SuppressWarnings("unchecked") @SuppressWarnings("unchecked")
TableRow<JavaFxModel> row = (TableRow<JavaFxModel>) event.getSource(); TableRow<JavaFxModel> row = (TableRow<JavaFxModel>) event.getSource();
TableView<JavaFxModel> table = row.getTableView(); TableView<JavaFxModel> table = row.getTableView();
double offset = 0; double columnOffset = 0;
double width = 0; double width = 0;
for (TableColumn<JavaFxModel, ?> col : table.getColumns()) { for (TableColumn<JavaFxModel, ?> col : table.getColumns()) {
offset += width; columnOffset += width;
width = col.getWidth(); width = col.getWidth();
if(Objects.equals(col.getId(), "preview")) { if(Objects.equals(col.getId(), "preview")) {
Point2D screenToLocal = table.screenToLocal(event.getScreenX(), event.getScreenY()); Point2D screenToLocal = table.screenToLocal(event.getScreenX(), event.getScreenY());
double x = screenToLocal.getX(); double x = screenToLocal.getX();
return x >= offset && x <= offset + width; return x >= columnOffset && x <= columnOffset + width;
} }
} }
return false; return false;
@ -176,6 +176,7 @@ public class PreviewPopupHandler implements EventHandler<MouseEvent> {
try { try {
Thread.sleep(100); Thread.sleep(100);
} catch (InterruptedException e) { } catch (InterruptedException e) {
Thread.currentThread().interrupt();
LOG.error("PreviewPopupTimer interrupted"); LOG.error("PreviewPopupTimer interrupted");
break; break;
} }

View File

@ -7,6 +7,7 @@ import java.util.Optional;
import java.util.concurrent.ExecutionException; import java.util.concurrent.ExecutionException;
import java.util.function.Function; import java.util.function.Function;
import ctbrec.GlobalThreadPool;
import ctbrec.Model; import ctbrec.Model;
import ctbrec.recorder.download.StreamSource; import ctbrec.recorder.download.StreamSource;
import ctbrec.ui.controls.Dialogs; import ctbrec.ui.controls.Dialogs;
@ -19,7 +20,8 @@ import javafx.stage.Stage;
public class StreamSourceSelectionDialog { public class StreamSourceSelectionDialog {
private static final StreamSource BEST = new BestStreamSource(); private static final StreamSource BEST = new BestStreamSource();
private StreamSourceSelectionDialog() {} private StreamSourceSelectionDialog() {
}
public static void show(Scene parent, Model model, Function<Model, Void> onSuccess, Function<Throwable, Void> onFail) { public static void show(Scene parent, Model model, Function<Model, Void> onSuccess, Function<Throwable, Void> onFail) {
Task<List<StreamSource>> selectStreamSource = new Task<List<StreamSource>>() { Task<List<StreamSource>> selectStreamSource = new Task<List<StreamSource>>() {
@ -61,7 +63,7 @@ public class StreamSourceSelectionDialog {
} }
}); });
selectStreamSource.setOnFailed(e -> onFail.apply(selectStreamSource.getException())); selectStreamSource.setOnFailed(e -> onFail.apply(selectStreamSource.getException()));
new Thread(selectStreamSource).start(); GlobalThreadPool.submit(selectStreamSource);
} }
private static class BestStreamSource extends StreamSource { private static class BestStreamSource extends StreamSource {

View File

@ -7,7 +7,7 @@ import java.util.concurrent.ExecutionException;
import org.slf4j.Logger; import org.slf4j.Logger;
import org.slf4j.LoggerFactory; import org.slf4j.LoggerFactory;
import ctbrec.Model; import ctbrec.GlobalThreadPool;
import ctbrec.sites.Site; import ctbrec.sites.Site;
import javafx.application.Platform; import javafx.application.Platform;
import javafx.concurrent.Task; import javafx.concurrent.Task;
@ -19,11 +19,11 @@ import javafx.stage.Stage;
public class TipDialog extends TextInputDialog { public class TipDialog extends TextInputDialog {
private static final transient Logger LOG = LoggerFactory.getLogger(TipDialog.class); private static final Logger LOG = LoggerFactory.getLogger(TipDialog.class);
private Site site; private Site site;
private Scene parent; private Scene parent;
public TipDialog(Scene parent, Site site, Model model) { public TipDialog(Scene parent, Site site) {
this.parent = parent; this.parent = parent;
this.site = site; this.site = site;
setTitle("Send Tip"); setTitle("Send Tip");
@ -72,13 +72,20 @@ public class TipDialog extends TextInputDialog {
setHeaderText("Current token balance: " + df.format(tokens)); setHeaderText("Current token balance: " + df.format(tokens));
} }
}); });
} catch (InterruptedException | ExecutionException e) { } catch (InterruptedException e) {
LOG.error("Couldn't retrieve account balance", e); Thread.currentThread().interrupt();
showErrorDialog(e); handleExcetion(e);
} catch (ExecutionException e) {
handleExcetion(e);
} }
} }
}; };
new Thread(task).start(); GlobalThreadPool.submit(task);
}
private void handleExcetion(Exception e) {
LOG.error("Couldn't retrieve account balance", e);
showErrorDialog(e);
} }
private void showErrorDialog(Throwable throwable) { private void showErrorDialog(Throwable throwable) {

View File

@ -10,6 +10,7 @@ import org.slf4j.LoggerFactory;
import com.google.common.eventbus.Subscribe; import com.google.common.eventbus.Subscribe;
import ctbrec.GlobalThreadPool;
import ctbrec.event.EventBusHolder; import ctbrec.event.EventBusHolder;
import ctbrec.sites.Site; import ctbrec.sites.Site;
import javafx.application.Platform; import javafx.application.Platform;
@ -19,7 +20,7 @@ import javafx.scene.control.Tooltip;
public class TokenLabel extends Label { public class TokenLabel extends Label {
private static final transient Logger LOG = LoggerFactory.getLogger(TokenLabel.class); private static final Logger LOG = LoggerFactory.getLogger(TokenLabel.class);
private double tokens = -1; private double tokens = -1;
private Site site; private Site site;
@ -72,17 +73,24 @@ public class TokenLabel extends Label {
@Override @Override
protected void done() { protected void done() {
try { try {
double tokens = get(); tokens = get();
update(tokens); update(tokens);
} catch (InterruptedException | ExecutionException e) { } catch (InterruptedException e) {
Thread.currentThread().interrupt();
handleException(e);
} catch (ExecutionException e) {
handleException(e);
}
}
private void handleException(Exception e) {
LOG.error("Couldn't retrieve account balance", e); LOG.error("Couldn't retrieve account balance", e);
Platform.runLater(() -> { Platform.runLater(() -> {
setText("Tokens: error"); setText("Tokens: error");
setTooltip(new Tooltip(e.getMessage())); setTooltip(new Tooltip(e.getMessage()));
}); });
} }
}
}; };
new Thread(task).start(); GlobalThreadPool.submit(task);
} }
} }

View File

@ -9,6 +9,7 @@ import java.util.stream.Collectors;
import org.slf4j.Logger; import org.slf4j.Logger;
import org.slf4j.LoggerFactory; import org.slf4j.LoggerFactory;
import ctbrec.GlobalThreadPool;
import ctbrec.Model; import ctbrec.Model;
import ctbrec.recorder.Recorder; import ctbrec.recorder.Recorder;
import ctbrec.ui.controls.Dialogs; import ctbrec.ui.controls.Dialogs;
@ -70,6 +71,6 @@ public class CheckModelAccountAction {
}); });
} }
}); });
new Thread(checker).start(); GlobalThreadPool.submit(checker);
} }
} }

View File

@ -10,7 +10,6 @@ import ctbrec.Config;
import ctbrec.Model; import ctbrec.Model;
import ctbrec.ui.JavaFxModel; import ctbrec.ui.JavaFxModel;
import ctbrec.ui.controls.Dialogs; import ctbrec.ui.controls.Dialogs;
import javafx.application.Platform;
import javafx.scene.Cursor; import javafx.scene.Cursor;
import javafx.scene.Node; import javafx.scene.Node;
import javafx.scene.control.TableView; import javafx.scene.control.TableView;
@ -30,7 +29,6 @@ public class EditNotesAction {
public void execute() { public void execute() {
source.setCursor(Cursor.WAIT); source.setCursor(Cursor.WAIT);
new Thread(() -> Platform.runLater(() -> {
String notes = Config.getInstance().getSettings().modelNotes.getOrDefault(model.getUrl(), ""); String notes = Config.getInstance().getSettings().modelNotes.getOrDefault(model.getUrl(), "");
Optional<String> newNotes = Dialogs.showTextInput(source.getScene(), "Model Notes", "Notes for " + model.getName(), notes); Optional<String> newNotes = Dialogs.showTextInput(source.getScene(), "Model Notes", "Notes for " + model.getName(), notes);
newNotes.ifPresent(n -> { newNotes.ifPresent(n -> {
@ -47,6 +45,5 @@ public class EditNotesAction {
}); });
table.refresh(); table.refresh();
source.setCursor(Cursor.DEFAULT); source.setCursor(Cursor.DEFAULT);
})).start();
} }
} }

View File

@ -2,13 +2,9 @@ package ctbrec.ui.action;
import java.util.List; import java.util.List;
import java.util.Objects; import java.util.Objects;
import java.util.concurrent.BlockingQueue;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.LinkedBlockingQueue;
import java.util.concurrent.ThreadPoolExecutor;
import java.util.concurrent.TimeUnit;
import java.util.function.Consumer; import java.util.function.Consumer;
import ctbrec.GlobalThreadPool;
import ctbrec.Model; import ctbrec.Model;
import javafx.application.Platform; import javafx.application.Platform;
import javafx.scene.Cursor; import javafx.scene.Cursor;
@ -16,9 +12,6 @@ import javafx.scene.Node;
public class ModelMassEditAction { public class ModelMassEditAction {
static BlockingQueue<Runnable> queue = new LinkedBlockingQueue<>();
static ExecutorService threadPool = new ThreadPoolExecutor(2, 10, 10, TimeUnit.MINUTES, queue);
protected List<? extends Model> models; protected List<? extends Model> models;
protected Consumer<Model> action; protected Consumer<Model> action;
protected Node source; protected Node source;
@ -42,7 +35,7 @@ public class ModelMassEditAction {
Consumer<Model> cb = Objects.requireNonNull(callback, "Callback is null, call execute() instead"); Consumer<Model> cb = Objects.requireNonNull(callback, "Callback is null, call execute() instead");
source.setCursor(Cursor.WAIT); source.setCursor(Cursor.WAIT);
for (Model model : models) { for (Model model : models) {
threadPool.submit(() -> { GlobalThreadPool.submit(() -> {
action.accept(model); action.accept(model);
cb.accept(model); cb.accept(model);
Platform.runLater(() -> source.setCursor(Cursor.DEFAULT)); Platform.runLater(() -> source.setCursor(Cursor.DEFAULT));

View File

@ -4,6 +4,7 @@ import java.io.File;
import java.time.Instant; import java.time.Instant;
import ctbrec.Config; import ctbrec.Config;
import ctbrec.GlobalThreadPool;
import ctbrec.Model; import ctbrec.Model;
import ctbrec.Settings.DirectoryStructure; import ctbrec.Settings.DirectoryStructure;
import ctbrec.ui.DesktopIntegration; import ctbrec.ui.DesktopIntegration;
@ -26,7 +27,7 @@ public class OpenRecordingsDir {
File fileForRecording = Config.getInstance().getFileForRecording(selectedModel, ".mp4", Instant.now()); File fileForRecording = Config.getInstance().getFileForRecording(selectedModel, ".mp4", Instant.now());
final File dir = getModelDirectory(fileForRecording); final File dir = getModelDirectory(fileForRecording);
if (dir.exists()) { if (dir.exists()) {
new Thread(() -> DesktopIntegration.open(dir)).start(); GlobalThreadPool.submit(() -> DesktopIntegration.open(dir));
} else { } else {
Dialogs.showError(source.getScene(), "Directory does not exist", "There are no recordings for this model", null); Dialogs.showError(source.getScene(), "Directory does not exist", "There are no recordings for this model", null);
} }

View File

@ -1,5 +1,6 @@
package ctbrec.ui.action; package ctbrec.ui.action;
import ctbrec.GlobalThreadPool;
import ctbrec.recorder.Recorder; import ctbrec.recorder.Recorder;
import ctbrec.ui.controls.Dialogs; import ctbrec.ui.controls.Dialogs;
import javafx.application.Platform; import javafx.application.Platform;
@ -20,7 +21,7 @@ public class ToggleRecordingAction {
public void execute() { public void execute() {
toggleButton.setCursor(Cursor.WAIT); toggleButton.setCursor(Cursor.WAIT);
Thread t = new Thread(() -> { GlobalThreadPool.submit(() -> {
try { try {
if (pause) { if (pause) {
recorder.pause(); recorder.pause();
@ -36,7 +37,5 @@ public class ToggleRecordingAction {
Platform.runLater(() -> toggleButton.setCursor(Cursor.DEFAULT)); Platform.runLater(() -> toggleButton.setCursor(Cursor.DEFAULT));
} }
}); });
t.setDaemon(true);
t.start();
} }
} }

View File

@ -38,6 +38,7 @@ import java.util.Optional;
import org.slf4j.Logger; import org.slf4j.Logger;
import org.slf4j.LoggerFactory; import org.slf4j.LoggerFactory;
import ctbrec.GlobalThreadPool;
import ctbrec.Model; import ctbrec.Model;
import ctbrec.recorder.Recorder; import ctbrec.recorder.Recorder;
import ctbrec.ui.action.PlayAction; import ctbrec.ui.action.PlayAction;
@ -167,7 +168,7 @@ public class SearchPopoverTreeList extends PopoverTreeList<Model> implements Pop
follow = new Button("Follow"); follow = new Button("Follow");
follow.setOnAction(evt -> { follow.setOnAction(evt -> {
setCursor(Cursor.WAIT); setCursor(Cursor.WAIT);
new Thread(new Task<Boolean>() { GlobalThreadPool.submit(new Task<Boolean>() {
@Override @Override
protected Boolean call() throws Exception { protected Boolean call() throws Exception {
model.getSite().login(); model.getSite().login();
@ -183,12 +184,12 @@ public class SearchPopoverTreeList extends PopoverTreeList<Model> implements Pop
} }
Platform.runLater(() -> setCursor(Cursor.DEFAULT)); Platform.runLater(() -> setCursor(Cursor.DEFAULT));
} }
}).start(); });
}); });
record = new Button("Record"); record = new Button("Record");
record.setOnAction(evt -> { record.setOnAction(evt -> {
setCursor(Cursor.WAIT); setCursor(Cursor.WAIT);
new Thread(new Task<Void>() { GlobalThreadPool.submit(new Task<Void>() {
@Override @Override
protected Void call() throws Exception { protected Void call() throws Exception {
recorder.addModel(model); recorder.addModel(model);
@ -199,7 +200,7 @@ public class SearchPopoverTreeList extends PopoverTreeList<Model> implements Pop
protected void done() { protected void done() {
Platform.runLater(() -> setCursor(Cursor.DEFAULT)); Platform.runLater(() -> setCursor(Cursor.DEFAULT));
} }
}).start(); });
}); });
getChildren().addAll(thumb, title, follow, record); getChildren().addAll(thumb, title, follow, record);
@ -296,12 +297,12 @@ public class SearchPopoverTreeList extends PopoverTreeList<Model> implements Pop
@Override @Override
protected double computePrefHeight(double width) { protected double computePrefHeight(double width) {
return thumbSize + 20; return thumbSize + 20.0;
} }
@Override @Override
protected double computeMaxHeight(double width) { protected double computeMaxHeight(double width) {
return thumbSize + 20; return thumbSize + 20.0;
} }
@Override @Override

View File

@ -12,6 +12,7 @@ import org.slf4j.Logger;
import org.slf4j.LoggerFactory; import org.slf4j.LoggerFactory;
import ctbrec.Config; import ctbrec.Config;
import ctbrec.GlobalThreadPool;
import ctbrec.Model; import ctbrec.Model;
import ctbrec.io.HttpException; import ctbrec.io.HttpException;
import ctbrec.recorder.download.StreamSource; import ctbrec.recorder.download.StreamSource;
@ -79,7 +80,7 @@ public class StreamPreview extends StackPane {
double w = Config.getInstance().getSettings().thumbWidth; double w = Config.getInstance().getSettings().thumbWidth;
double h = w / aspect; double h = w / aspect;
resizeTo(w, h); resizeTo(w, h);
} catch (Exception e) {} } catch (Exception e) { /* nothing to do */ }
} }
if(future != null && !future.isDone()) { if(future != null && !future.isDone()) {
@ -157,14 +158,14 @@ public class StreamPreview extends StackPane {
running = false; running = false;
MediaPlayer old = videoPlayer; MediaPlayer old = videoPlayer;
Future<?> oldFuture = future; Future<?> oldFuture = future;
new Thread(() -> { GlobalThreadPool.submit(() -> {
if(oldFuture != null && !oldFuture.isDone()) { if(oldFuture != null && !oldFuture.isDone()) {
oldFuture.cancel(true); oldFuture.cancel(true);
} }
if(old != null) { if(old != null) {
old.dispose(); old.dispose();
} }
}).start(); });
} }
private void onError(MediaPlayer videoPlayer) { private void onError(MediaPlayer videoPlayer) {

View File

@ -1,5 +1,6 @@
package ctbrec.ui.controls; package ctbrec.ui.controls;
import ctbrec.GlobalThreadPool;
import javafx.animation.KeyFrame; import javafx.animation.KeyFrame;
import javafx.animation.KeyValue; import javafx.animation.KeyValue;
import javafx.animation.Timeline; import javafx.animation.Timeline;
@ -13,6 +14,8 @@ import javafx.stage.StageStyle;
import javafx.util.Duration; import javafx.util.Duration;
public final class Toast { public final class Toast {
private Toast() {}
public static void makeText(Scene owner, String toastMsg, int toastDelay, int fadeInDelay, int fadeOutDelay) { public static void makeText(Scene owner, String toastMsg, int toastDelay, int fadeInDelay, int fadeOutDelay) {
Stage toastStage = new Stage(); Stage toastStage = new Stage();
toastStage.initOwner(owner.getWindow()); toastStage.initOwner(owner.getWindow());
@ -35,8 +38,7 @@ public final class Toast {
Timeline fadeInTimeline = new Timeline(); Timeline fadeInTimeline = new Timeline();
KeyFrame fadeInKey1 = new KeyFrame(Duration.millis(fadeInDelay), new KeyValue(toastStage.getScene().getRoot().opacityProperty(), 1)); KeyFrame fadeInKey1 = new KeyFrame(Duration.millis(fadeInDelay), new KeyValue(toastStage.getScene().getRoot().opacityProperty(), 1));
fadeInTimeline.getKeyFrames().add(fadeInKey1); fadeInTimeline.getKeyFrames().add(fadeInKey1);
fadeInTimeline.setOnFinished((ae) -> { fadeInTimeline.setOnFinished(ae -> GlobalThreadPool.submit(() -> {
new Thread(() -> {
try { try {
Thread.sleep(toastDelay); Thread.sleep(toastDelay);
} catch (InterruptedException e) { } catch (InterruptedException e) {
@ -45,10 +47,9 @@ public final class Toast {
Timeline fadeOutTimeline = new Timeline(); Timeline fadeOutTimeline = new Timeline();
KeyFrame fadeOutKey1 = new KeyFrame(Duration.millis(fadeOutDelay), new KeyValue(toastStage.getScene().getRoot().opacityProperty(), 0)); KeyFrame fadeOutKey1 = new KeyFrame(Duration.millis(fadeOutDelay), new KeyValue(toastStage.getScene().getRoot().opacityProperty(), 0));
fadeOutTimeline.getKeyFrames().add(fadeOutKey1); fadeOutTimeline.getKeyFrames().add(fadeOutKey1);
fadeOutTimeline.setOnFinished((aeb) -> toastStage.close()); fadeOutTimeline.setOnFinished(aeb -> toastStage.close());
fadeOutTimeline.play(); fadeOutTimeline.play();
}).start(); }));
});
fadeInTimeline.play(); fadeInTimeline.play();
} }
} }

View File

@ -1,7 +1,16 @@
package ctbrec.ui.news; package ctbrec.ui.news;
import static ctbrec.io.HttpConstants.*;
import java.io.IOException;
import java.util.Objects;
import org.json.JSONObject;
import com.squareup.moshi.JsonAdapter; import com.squareup.moshi.JsonAdapter;
import com.squareup.moshi.Moshi; import com.squareup.moshi.Moshi;
import ctbrec.GlobalThreadPool;
import ctbrec.io.HttpException; import ctbrec.io.HttpException;
import ctbrec.ui.CamrecApplication; import ctbrec.ui.CamrecApplication;
import ctbrec.ui.controls.Dialogs; import ctbrec.ui.controls.Dialogs;
@ -14,12 +23,6 @@ import javafx.scene.control.Tab;
import javafx.scene.layout.VBox; import javafx.scene.layout.VBox;
import okhttp3.Request; import okhttp3.Request;
import okhttp3.Response; import okhttp3.Response;
import org.json.JSONObject;
import java.io.IOException;
import java.util.Objects;
import static ctbrec.io.HttpConstants.USER_AGENT;
public class NewsTab extends Tab implements TabSelectionListener { public class NewsTab extends Tab implements TabSelectionListener {
private static final String ACCESS_TOKEN = "a2804d73a89951a22e0f8483a6fcec8943afd88b7ba17c459c095aa9e6f94fd0"; private static final String ACCESS_TOKEN = "a2804d73a89951a22e0f8483a6fcec8943afd88b7ba17c459c095aa9e6f94fd0";
@ -36,7 +39,7 @@ public class NewsTab extends Tab implements TabSelectionListener {
@Override @Override
public void selected() { public void selected() {
new Thread(this::loadToots).start(); GlobalThreadPool.submit(this::loadToots);
} }
private void loadToots() { private void loadToots() {

View File

@ -22,7 +22,7 @@ import okhttp3.HttpUrl;
public class BongaCamsElectronLoginDialog { public class BongaCamsElectronLoginDialog {
private static final transient Logger LOG = LoggerFactory.getLogger(BongaCamsElectronLoginDialog.class); private static final Logger LOG = LoggerFactory.getLogger(BongaCamsElectronLoginDialog.class);
public static final String DOMAIN = "bongacams.com"; public static final String DOMAIN = "bongacams.com";
public static final String URL = BongaCams.baseUrl + "/login"; public static final String URL = BongaCams.baseUrl + "/login";
private CookieJar cookieJar; private CookieJar cookieJar;
@ -40,18 +40,18 @@ public class BongaCamsElectronLoginDialog {
msg.put("config", config); msg.put("config", config);
browser.run(msg, msgHandler); browser.run(msg, msgHandler);
} catch (InterruptedException e) { } catch (InterruptedException e) {
Thread.currentThread().interrupt();
throw new IOException("Couldn't wait for login dialog", e); throw new IOException("Couldn't wait for login dialog", e);
} finally { } finally {
browser.close(); browser.close();
} }
} }
private Consumer<String> msgHandler = (line) -> { private Consumer<String> msgHandler = line -> {
if(!line.startsWith("{")) { if(!line.startsWith("{")) {
System.err.println(line); LOG.error("Didn't received a JSON object {}", line);
} else { } else {
JSONObject json = new JSONObject(line); JSONObject json = new JSONObject(line);
//LOG.debug("Browser: {}", json.toString(2));
if(json.has("url")) { if(json.has("url")) {
String url = json.getString("url"); String url = json.getString("url");
if(url.endsWith("/login")) { if(url.endsWith("/login")) {
@ -82,16 +82,16 @@ public class BongaCamsElectronLoginDialog {
} }
if(json.has("cookies")) { if(json.has("cookies")) {
JSONArray _cookies = json.getJSONArray("cookies"); JSONArray cookiesFromBrowser = json.getJSONArray("cookies");
for (int i = 0; i < _cookies.length(); i++) { for (int i = 0; i < cookiesFromBrowser.length(); i++) {
JSONObject cookie = _cookies.getJSONObject(i); JSONObject cookie = cookiesFromBrowser.getJSONObject(i);
if(cookie.getString("domain").contains(DOMAIN)) { if(cookie.getString("domain").contains(DOMAIN)) {
Builder b = new Cookie.Builder() Builder b = new Cookie.Builder()
.path(cookie.getString("path")) .path(cookie.getString("path"))
.domain(DOMAIN) .domain(DOMAIN)
.name(cookie.getString("name")) .name(cookie.getString("name"))
.value(cookie.getString("value")) .value(cookie.getString("value"))
.expiresAt(Double.valueOf(cookie.optDouble("expirationDate")).longValue()); .expiresAt((long) cookie.optDouble("expirationDate"));
if(cookie.optBoolean("hostOnly")) { if(cookie.optBoolean("hostOnly")) {
b.hostOnlyDomain(DOMAIN); b.hostOnlyDomain(DOMAIN);
} }
@ -108,8 +108,7 @@ public class BongaCamsElectronLoginDialog {
} }
try { try {
URL _url = new URL(url); if (Objects.equals(new URL(url).getPath(), "/")) {
if (Objects.equals(_url.getPath(), "/")) {
browser.close(); browser.close();
} }
} catch (MalformedURLException e) { } catch (MalformedURLException e) {

View File

@ -1,17 +1,16 @@
package ctbrec.ui.sites.bonga; package ctbrec.ui.sites.bonga;
import java.io.IOException;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import ctbrec.sites.bonga.BongaCams; import ctbrec.sites.bonga.BongaCams;
import ctbrec.sites.bonga.BongaCamsHttpClient; import ctbrec.sites.bonga.BongaCamsHttpClient;
import ctbrec.ui.controls.Dialogs; import ctbrec.ui.controls.Dialogs;
import ctbrec.ui.sites.AbstractSiteUi; import ctbrec.ui.sites.AbstractSiteUi;
import ctbrec.ui.sites.ConfigUI; import ctbrec.ui.sites.ConfigUI;
import ctbrec.ui.tabs.TabProvider; import ctbrec.ui.tabs.TabProvider;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.io.IOException;
import java.util.concurrent.BlockingQueue;
import java.util.concurrent.LinkedBlockingQueue;
public class BongaCamsSiteUi extends AbstractSiteUi { public class BongaCamsSiteUi extends AbstractSiteUi {
@ -42,9 +41,6 @@ public class BongaCamsSiteUi extends AbstractSiteUi {
if (automaticLogin) { if (automaticLogin) {
return true; return true;
} else { } else {
BlockingQueue<Boolean> queue = new LinkedBlockingQueue<>();
try {
new Thread(() -> {
// login with external browser window // login with external browser window
try { try {
new BongaCamsElectronLoginDialog(bongaCams.getHttpClient().getCookieJar()); new BongaCamsElectronLoginDialog(bongaCams.getHttpClient().getCookieJar());
@ -53,20 +49,6 @@ public class BongaCamsSiteUi extends AbstractSiteUi {
Dialogs.showError("Login error", "Couldn't login to " + bongaCams.getName(), e1); Dialogs.showError("Login error", "Couldn't login to " + bongaCams.getName(), e1);
} }
try {
queue.put(true);
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
LOG.error("Error while signaling termination", e);
}
}).start();
queue.take();
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
LOG.error("Error while waiting for login dialog to close", e);
throw new IOException(e);
}
BongaCamsHttpClient httpClient = (BongaCamsHttpClient) bongaCams.getHttpClient(); BongaCamsHttpClient httpClient = (BongaCamsHttpClient) bongaCams.getHttpClient();
boolean loggedIn = httpClient.checkLoginSuccess(); boolean loggedIn = httpClient.checkLoginSuccess();
if (loggedIn) { if (loggedIn) {

View File

@ -22,7 +22,7 @@ import okhttp3.HttpUrl;
public class Cam4ElectronLoginDialog { public class Cam4ElectronLoginDialog {
private static final transient Logger LOG = LoggerFactory.getLogger(Cam4ElectronLoginDialog.class); private static final Logger LOG = LoggerFactory.getLogger(Cam4ElectronLoginDialog.class);
public static final String DOMAIN = "cam4.com"; public static final String DOMAIN = "cam4.com";
public static final String URL = Cam4.BASE_URI + "/login"; public static final String URL = Cam4.BASE_URI + "/login";
private CookieJar cookieJar; private CookieJar cookieJar;
@ -40,15 +40,16 @@ public class Cam4ElectronLoginDialog {
msg.put("config", config); msg.put("config", config);
browser.run(msg, msgHandler); browser.run(msg, msgHandler);
} catch (InterruptedException e) { } catch (InterruptedException e) {
Thread.currentThread().interrupt();
throw new IOException("Couldn't wait for login dialog", e); throw new IOException("Couldn't wait for login dialog", e);
} finally { } finally {
browser.close(); browser.close();
} }
} }
private Consumer<String> msgHandler = (line) -> { private Consumer<String> msgHandler = line -> {
if(!line.startsWith("{")) { if(!line.startsWith("{")) {
System.err.println(line); LOG.error("Didn't received a JSON object {}", line);
} else { } else {
JSONObject json = new JSONObject(line); JSONObject json = new JSONObject(line);
if(json.has("url")) { if(json.has("url")) {
@ -75,11 +76,10 @@ public class Cam4ElectronLoginDialog {
} }
if(json.has("cookies")) { if(json.has("cookies")) {
JSONArray _cookies = json.getJSONArray("cookies"); JSONArray cookiesFromBrowser = json.getJSONArray("cookies");
try { try {
URL _url = new URL(url); for (int i = 0; i < cookiesFromBrowser.length(); i++) {
for (int i = 0; i < _cookies.length(); i++) { JSONObject cookie = cookiesFromBrowser.getJSONObject(i);
JSONObject cookie = _cookies.getJSONObject(i);
if(cookie.getString("domain").contains("cam4")) { if(cookie.getString("domain").contains("cam4")) {
String domain = cookie.getString("domain"); String domain = cookie.getString("domain");
if(domain.startsWith(".")) { if(domain.startsWith(".")) {
@ -91,12 +91,8 @@ public class Cam4ElectronLoginDialog {
cookieJar.saveFromResponse(HttpUrl.parse(Cam4.BASE_URI), Collections.singletonList(c)); cookieJar.saveFromResponse(HttpUrl.parse(Cam4.BASE_URI), Collections.singletonList(c));
} }
} }
if (Objects.equals(_url.getPath(), "/")) { if (Objects.equals(new URL(url).getPath(), "/")) {
try { closeBrowser();
browser.close();
} catch(IOException e) {
LOG.error("Couldn't send close request to browser", e);
}
} }
} catch (MalformedURLException e) { } catch (MalformedURLException e) {
LOG.error("Couldn't parse new url {}", url, e); LOG.error("Couldn't parse new url {}", url, e);
@ -112,7 +108,7 @@ public class Cam4ElectronLoginDialog {
.domain(domain) .domain(domain)
.name(cookie.getString("name")) .name(cookie.getString("name"))
.value(cookie.getString("value")) .value(cookie.getString("value"))
.expiresAt(Double.valueOf(cookie.optDouble("expirationDate")).longValue()); .expiresAt((long) cookie.optDouble("expirationDate"));
if(cookie.optBoolean("hostOnly")) { if(cookie.optBoolean("hostOnly")) {
b.hostOnlyDomain(domain); b.hostOnlyDomain(domain);
} }
@ -124,4 +120,12 @@ public class Cam4ElectronLoginDialog {
} }
return b.build(); return b.build();
} }
private void closeBrowser() {
try {
browser.close();
} catch(IOException e) {
LOG.error("Couldn't send close request to browser", e);
}
}
} }

View File

@ -1,8 +1,6 @@
package ctbrec.ui.sites.cam4; package ctbrec.ui.sites.cam4;
import java.io.IOException; import java.io.IOException;
import java.util.concurrent.BlockingQueue;
import java.util.concurrent.LinkedBlockingQueue;
import org.slf4j.Logger; import org.slf4j.Logger;
import org.slf4j.LoggerFactory; import org.slf4j.LoggerFactory;
@ -13,10 +11,9 @@ import ctbrec.ui.controls.Dialogs;
import ctbrec.ui.sites.AbstractSiteUi; import ctbrec.ui.sites.AbstractSiteUi;
import ctbrec.ui.sites.ConfigUI; import ctbrec.ui.sites.ConfigUI;
import ctbrec.ui.tabs.TabProvider; import ctbrec.ui.tabs.TabProvider;
import javafx.application.Platform;
public class Cam4SiteUi extends AbstractSiteUi { public class Cam4SiteUi extends AbstractSiteUi {
private static final transient Logger LOG = LoggerFactory.getLogger(Cam4SiteUi.class); private static final Logger LOG = LoggerFactory.getLogger(Cam4SiteUi.class);
private Cam4TabProvider tabProvider; private Cam4TabProvider tabProvider;
private Cam4ConfigUI configUI; private Cam4ConfigUI configUI;
@ -44,10 +41,6 @@ public class Cam4SiteUi extends AbstractSiteUi {
if (automaticLogin) { if (automaticLogin) {
return true; return true;
} else { } else {
BlockingQueue<Boolean> queue = new LinkedBlockingQueue<>();
Runnable showDialog = () -> {
// login with external browser // login with external browser
try { try {
new Cam4ElectronLoginDialog(cam4.getHttpClient().getCookieJar()); new Cam4ElectronLoginDialog(cam4.getHttpClient().getCookieJar());
@ -55,22 +48,6 @@ public class Cam4SiteUi extends AbstractSiteUi {
LOG.error("Error logging in with external browser", e1); LOG.error("Error logging in with external browser", e1);
Dialogs.showError("Login error", "Couldn't login to " + cam4.getName(), e1); Dialogs.showError("Login error", "Couldn't login to " + cam4.getName(), e1);
} }
try {
queue.put(true);
} catch (InterruptedException e) {
LOG.error("Error while signaling termination", e);
}
};
Platform.runLater(showDialog);
try {
queue.take();
} catch (InterruptedException e) {
LOG.error("Error while waiting for login dialog to close", e);
throw new IOException(e);
}
Cam4HttpClient httpClient = (Cam4HttpClient) cam4.getHttpClient(); Cam4HttpClient httpClient = (Cam4HttpClient) cam4.getHttpClient();
boolean loggedIn = httpClient.checkLoginSuccess(); boolean loggedIn = httpClient.checkLoginSuccess();
return loggedIn; return loggedIn;

View File

@ -10,7 +10,6 @@ import java.util.List;
import java.util.Locale; import java.util.Locale;
import java.util.concurrent.ExecutorService; import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors; import java.util.concurrent.Executors;
import java.util.concurrent.ThreadFactory;
import org.json.JSONObject; import org.json.JSONObject;
import org.jsoup.nodes.Element; import org.jsoup.nodes.Element;
@ -43,14 +42,11 @@ public class Cam4UpdateService extends PaginatedScheduledService {
this.url = url; this.url = url;
this.loginRequired = loginRequired; this.loginRequired = loginRequired;
ExecutorService executor = Executors.newSingleThreadExecutor(new ThreadFactory() { ExecutorService executor = Executors.newSingleThreadExecutor(r -> {
@Override
public Thread newThread(Runnable r) {
Thread t = new Thread(r); Thread t = new Thread(r);
t.setDaemon(true); t.setDaemon(true);
t.setName("ThumbOverviewTab UpdateService"); t.setName("ThumbOverviewTab UpdateService");
return t; return t;
}
}); });
setExecutor(executor); setExecutor(executor);
} }
@ -63,13 +59,13 @@ public class Cam4UpdateService extends PaginatedScheduledService {
if (loginRequired && StringUtil.isBlank(Config.getInstance().getSettings().cam4Username)) { if (loginRequired && StringUtil.isBlank(Config.getInstance().getSettings().cam4Username)) {
return Collections.emptyList(); return Collections.emptyList();
} else { } else {
String url = Cam4UpdateService.this.url + "&page=" + page; String pageUrl = Cam4UpdateService.this.url + "&page=" + page;
LOG.debug("Fetching page {}", url); LOG.debug("Fetching page {}", pageUrl);
if (loginRequired) { if (loginRequired) {
SiteUiFactory.getUi(site).login(); SiteUiFactory.getUi(site).login();
} }
Request request = new Request.Builder() Request request = new Request.Builder()
.url(url) .url(pageUrl)
.header(ACCEPT_LANGUAGE, Locale.ENGLISH.getLanguage()) .header(ACCEPT_LANGUAGE, Locale.ENGLISH.getLanguage())
.header(USER_AGENT, Config.getInstance().getSettings().httpUserAgent) .header(USER_AGENT, Config.getInstance().getSettings().httpUserAgent)
.build(); .build();

View File

@ -5,7 +5,6 @@ import java.util.Collections;
import java.util.List; import java.util.List;
import java.util.concurrent.ExecutorService; import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors; import java.util.concurrent.Executors;
import java.util.concurrent.ThreadFactory;
import org.slf4j.Logger; import org.slf4j.Logger;
import org.slf4j.LoggerFactory; import org.slf4j.LoggerFactory;
@ -21,7 +20,7 @@ import okhttp3.Response;
public class ChaturbateUpdateService extends PaginatedScheduledService { public class ChaturbateUpdateService extends PaginatedScheduledService {
private static final transient Logger LOG = LoggerFactory.getLogger(ChaturbateUpdateService.class); private static final Logger LOG = LoggerFactory.getLogger(ChaturbateUpdateService.class);
private String url; private String url;
private boolean loginRequired; private boolean loginRequired;
private Chaturbate chaturbate; private Chaturbate chaturbate;
@ -31,14 +30,11 @@ public class ChaturbateUpdateService extends PaginatedScheduledService {
this.loginRequired = loginRequired; this.loginRequired = loginRequired;
this.chaturbate = chaturbate; this.chaturbate = chaturbate;
ExecutorService executor = Executors.newSingleThreadExecutor(new ThreadFactory() { ExecutorService executor = Executors.newSingleThreadExecutor(r -> {
@Override
public Thread newThread(Runnable r) {
Thread t = new Thread(r); Thread t = new Thread(r);
t.setDaemon(true); t.setDaemon(true);
t.setName("ThumbOverviewTab UpdateService"); t.setName("ThumbOverviewTab UpdateService");
return t; return t;
}
}); });
setExecutor(executor); setExecutor(executor);
} }
@ -51,12 +47,12 @@ public class ChaturbateUpdateService extends PaginatedScheduledService {
if(loginRequired && !chaturbate.credentialsAvailable()) { if(loginRequired && !chaturbate.credentialsAvailable()) {
return Collections.emptyList(); return Collections.emptyList();
} else { } else {
String url = ChaturbateUpdateService.this.url + "?page="+page+"&keywords=&_=" + System.currentTimeMillis(); String pageUrl = ChaturbateUpdateService.this.url + "?page="+page+"&keywords=&_=" + System.currentTimeMillis();
LOG.debug("Fetching page {}", url); LOG.debug("Fetching page {}", pageUrl);
if(loginRequired) { if(loginRequired) {
SiteUiFactory.getUi(chaturbate).login(); SiteUiFactory.getUi(chaturbate).login();
} }
Request request = new Request.Builder().url(url).build(); Request request = new Request.Builder().url(pageUrl).build();
Response response = chaturbate.getHttpClient().execute(request); Response response = chaturbate.getHttpClient().execute(request);
if (response.isSuccessful()) { if (response.isSuccessful()) {
List<Model> models = ChaturbateModelParser.parseModels(chaturbate, response.body().string()); List<Model> models = ChaturbateModelParser.parseModels(chaturbate, response.body().string());

View File

@ -5,6 +5,7 @@ import java.io.IOException;
import org.slf4j.Logger; import org.slf4j.Logger;
import org.slf4j.LoggerFactory; import org.slf4j.LoggerFactory;
import ctbrec.GlobalThreadPool;
import ctbrec.Model; import ctbrec.Model;
import ctbrec.sites.fc2live.Fc2Live; import ctbrec.sites.fc2live.Fc2Live;
import ctbrec.sites.fc2live.Fc2Model; import ctbrec.sites.fc2live.Fc2Model;
@ -16,7 +17,7 @@ import ctbrec.ui.sites.ConfigUI;
import ctbrec.ui.tabs.TabProvider; import ctbrec.ui.tabs.TabProvider;
public class Fc2LiveSiteUi extends AbstractSiteUi { public class Fc2LiveSiteUi extends AbstractSiteUi {
private static final transient Logger LOG = LoggerFactory.getLogger(Fc2LiveSiteUi.class); private static final Logger LOG = LoggerFactory.getLogger(Fc2LiveSiteUi.class);
private Fc2Live fc2live; private Fc2Live fc2live;
private Fc2TabProvider tabProvider; private Fc2TabProvider tabProvider;
private Fc2LiveConfigUI configUi; private Fc2LiveConfigUI configUi;
@ -44,7 +45,7 @@ public class Fc2LiveSiteUi extends AbstractSiteUi {
@Override @Override
public boolean play(Model model) { public boolean play(Model model) {
new Thread(() -> { GlobalThreadPool.submit(() -> {
Fc2Model m; Fc2Model m;
if (model instanceof JavaFxModel) { if (model instanceof JavaFxModel) {
m = (Fc2Model) ((JavaFxModel) model).getDelegate(); m = (Fc2Model) ((JavaFxModel) model).getDelegate();
@ -55,12 +56,20 @@ public class Fc2LiveSiteUi extends AbstractSiteUi {
m.openWebsocket(); m.openWebsocket();
LOG.debug("Starting player for {}", model); LOG.debug("Starting player for {}", model);
Player.play(model, false); Player.play(model, false);
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
handleException(e);
} catch (IOException e) {
handleException(e);
} finally {
m.closeWebsocket(); m.closeWebsocket();
} catch (InterruptedException | IOException e) { }
});
return true;
}
private void handleException(Exception e) {
LOG.error("Error playing the stream", e); LOG.error("Error playing the stream", e);
Dialogs.showError("Player", "Error playing the stream", e); Dialogs.showError("Player", "Error playing the stream", e);
} }
}).start();
return true;
}
} }

View File

@ -1,8 +1,6 @@
package ctbrec.ui.sites.jasmin; package ctbrec.ui.sites.jasmin;
import java.io.IOException; import java.io.IOException;
import java.util.concurrent.BlockingQueue;
import java.util.concurrent.LinkedBlockingQueue;
import java.util.concurrent.TimeUnit; import java.util.concurrent.TimeUnit;
import org.slf4j.Logger; import org.slf4j.Logger;
@ -17,7 +15,7 @@ import ctbrec.ui.tabs.TabProvider;
public class LiveJasminSiteUi extends AbstractSiteUi { public class LiveJasminSiteUi extends AbstractSiteUi {
private static final transient Logger LOG = LoggerFactory.getLogger(LiveJasminSiteUi.class); private static final Logger LOG = LoggerFactory.getLogger(LiveJasminSiteUi.class);
private LiveJasmin liveJasmin; private LiveJasmin liveJasmin;
private LiveJasminTabProvider tabProvider; private LiveJasminTabProvider tabProvider;
private LiveJasminConfigUi configUi; private LiveJasminConfigUi configUi;
@ -53,9 +51,7 @@ public class LiveJasminSiteUi extends AbstractSiteUi {
return true; return true;
} else { } else {
lastLoginTime = System.currentTimeMillis(); lastLoginTime = System.currentTimeMillis();
BlockingQueue<Boolean> queue = new LinkedBlockingQueue<>();
new Thread (() -> {
// login with external browser window // login with external browser window
try { try {
new LiveJasminElectronLoginDialog(liveJasmin.getHttpClient().getCookieJar()); new LiveJasminElectronLoginDialog(liveJasmin.getHttpClient().getCookieJar());
@ -64,20 +60,6 @@ public class LiveJasminSiteUi extends AbstractSiteUi {
Dialogs.showError("Login error", "Couldn't login to " + liveJasmin.getName(), e1); Dialogs.showError("Login error", "Couldn't login to " + liveJasmin.getName(), e1);
} }
try {
queue.put(true);
} catch (InterruptedException e) {
LOG.error("Error while signaling termination", e);
}
}).start();
try {
queue.take();
} catch (InterruptedException e) {
LOG.error("Error while waiting for login dialog to close", e);
throw new IOException(e);
}
LiveJasminHttpClient httpClient = (LiveJasminHttpClient) liveJasmin.getHttpClient(); LiveJasminHttpClient httpClient = (LiveJasminHttpClient) liveJasmin.getHttpClient();
boolean loggedIn = httpClient.checkLoginSuccess(); boolean loggedIn = httpClient.checkLoginSuccess();
if (loggedIn) { if (loggedIn) {

View File

@ -33,6 +33,7 @@ import com.iheartradio.m3u8.ParseException;
import com.iheartradio.m3u8.PlaylistException; import com.iheartradio.m3u8.PlaylistException;
import ctbrec.Config; import ctbrec.Config;
import ctbrec.GlobalThreadPool;
import ctbrec.Model; import ctbrec.Model;
import ctbrec.Settings; import ctbrec.Settings;
import ctbrec.StringUtil; import ctbrec.StringUtil;
@ -353,7 +354,7 @@ public class MyFreeCamsTableTab extends Tab implements TabSelectionListener {
if (Objects.equals(System.getenv("CTBREC_DEV"), "1")) { if (Objects.equals(System.getenv("CTBREC_DEV"), "1")) {
MenuItem debug = new MenuItem("debug"); MenuItem debug = new MenuItem("debug");
debug.setOnAction(e -> new Thread(() -> { debug.setOnAction(e -> GlobalThreadPool.submit(() -> {
for (Model m : selectedModels) { for (Model m : selectedModels) {
try { try {
List<StreamSource> sources = m.getStreamSources(); List<StreamSource> sources = m.getStreamSources();
@ -365,7 +366,7 @@ public class MyFreeCamsTableTab extends Tab implements TabSelectionListener {
LOG.error("Couldn't get stream sources", e1); LOG.error("Couldn't get stream sources", e1);
} }
} }
}).start()); }));
menu.getItems().add(debug); menu.getItems().add(debug);
} }
@ -464,7 +465,7 @@ public class MyFreeCamsTableTab extends Tab implements TabSelectionListener {
private String escape(Property<?> prop) { private String escape(Property<?> prop) {
String value = prop.getValue() != null ? prop.getValue().toString() : ""; String value = prop.getValue() != null ? prop.getValue().toString() : "";
return "\"" + value.replaceAll("\"", "\"\"") + "\""; return "\"" + value.replace("\"", "\"\"") + "\"";
} }
private void showColumnSelection(ActionEvent evt) { private void showColumnSelection(ActionEvent evt) {
@ -566,7 +567,7 @@ public class MyFreeCamsTableTab extends Tab implements TabSelectionListener {
if(!file.exists()) { if(!file.exists()) {
return; return;
} }
String json = new String(Files.readAllBytes(file.toPath()), "utf-8"); String json = new String(Files.readAllBytes(file.toPath()), UTF_8);
JSONArray data = new JSONArray(json); JSONArray data = new JSONArray(json);
for (int i = 0; i < data.length(); i++) { for (int i = 0; i < data.length(); i++) {
try { try {
@ -701,7 +702,6 @@ public class MyFreeCamsTableTab extends Tab implements TabSelectionListener {
setProperty(continent, Optional.ofNullable(st.getM()).map(ctbrec.sites.mfc.Model::getContinent)); setProperty(continent, Optional.ofNullable(st.getM()).map(ctbrec.sites.mfc.Model::getContinent));
setProperty(occupation, Optional.ofNullable(st.getU()).map(User::getOccupation)); setProperty(occupation, Optional.ofNullable(st.getU()).map(User::getOccupation));
int flags = Optional.ofNullable(st.getM()).map(ctbrec.sites.mfc.Model::getFlags).orElse(0); int flags = Optional.ofNullable(st.getM()).map(ctbrec.sites.mfc.Model::getFlags).orElse(0);
//isHd.set((flags & 1024) == 1024);
isWebrtc.set((flags & 524288) == 524288); isWebrtc.set((flags & 524288) == 524288);
isHd.set(Optional.ofNullable(st.getU()).map(User::getPhase).orElse("z").equalsIgnoreCase("a")); isHd.set(Optional.ofNullable(st.getU()).map(User::getPhase).orElse("z").equalsIgnoreCase("a"));
flagsProperty.setValue(flags); flagsProperty.setValue(flags);

View File

@ -1,8 +1,6 @@
package ctbrec.ui.sites.showup; package ctbrec.ui.sites.showup;
import java.io.IOException; import java.io.IOException;
import java.util.concurrent.BlockingQueue;
import java.util.concurrent.LinkedBlockingQueue;
import org.slf4j.Logger; import org.slf4j.Logger;
import org.slf4j.LoggerFactory; import org.slf4j.LoggerFactory;
@ -44,9 +42,6 @@ public class ShowupSiteUi extends AbstractSiteUi {
if (automaticLogin) { if (automaticLogin) {
return true; return true;
} else { } else {
BlockingQueue<Boolean> queue = new LinkedBlockingQueue<>();
try {
new Thread(() -> {
// login with external browser window // login with external browser window
try { try {
new ShowupElectronLoginDialog(site.getHttpClient().getCookieJar()); new ShowupElectronLoginDialog(site.getHttpClient().getCookieJar());
@ -55,19 +50,6 @@ public class ShowupSiteUi extends AbstractSiteUi {
Dialogs.showError("Login error", "Couldn't login to " + site.getName(), e1); Dialogs.showError("Login error", "Couldn't login to " + site.getName(), e1);
} }
try {
queue.put(true);
} catch (InterruptedException e) {
LOG.error("Error while signaling termination", e);
Thread.currentThread().interrupt();
}
}).start();
queue.take();
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
throw new IOException(e);
}
ShowupHttpClient httpClient = (ShowupHttpClient) site.getHttpClient(); ShowupHttpClient httpClient = (ShowupHttpClient) site.getHttpClient();
boolean loggedIn = httpClient.checkLoginSuccess(); boolean loggedIn = httpClient.checkLoginSuccess();
if (loggedIn) { if (loggedIn) {
@ -78,5 +60,4 @@ public class ShowupSiteUi extends AbstractSiteUi {
return loggedIn; return loggedIn;
} }
} }
} }

View File

@ -1,8 +1,6 @@
package ctbrec.ui.sites.stripchat; package ctbrec.ui.sites.stripchat;
import java.io.IOException; import java.io.IOException;
import java.util.concurrent.BlockingQueue;
import java.util.concurrent.LinkedBlockingQueue;
import org.slf4j.Logger; import org.slf4j.Logger;
import org.slf4j.LoggerFactory; import org.slf4j.LoggerFactory;
@ -13,7 +11,6 @@ import ctbrec.ui.controls.Dialogs;
import ctbrec.ui.sites.AbstractSiteUi; import ctbrec.ui.sites.AbstractSiteUi;
import ctbrec.ui.sites.ConfigUI; import ctbrec.ui.sites.ConfigUI;
import ctbrec.ui.tabs.TabProvider; import ctbrec.ui.tabs.TabProvider;
import javafx.application.Platform;
public class StripchatSiteUi extends AbstractSiteUi { public class StripchatSiteUi extends AbstractSiteUi {
@ -45,10 +42,6 @@ public class StripchatSiteUi extends AbstractSiteUi {
if (automaticLogin) { if (automaticLogin) {
return true; return true;
} else { } else {
BlockingQueue<Boolean> queue = new LinkedBlockingQueue<>();
Runnable showDialog = () -> {
// login with external browser // login with external browser
try { try {
new StripchatElectronLoginDialog(site.getHttpClient().getCookieJar()); new StripchatElectronLoginDialog(site.getHttpClient().getCookieJar());
@ -57,21 +50,6 @@ public class StripchatSiteUi extends AbstractSiteUi {
Dialogs.showError("Login error", "Couldn't login to " + site.getName(), e1); Dialogs.showError("Login error", "Couldn't login to " + site.getName(), e1);
} }
try {
queue.put(true);
} catch (InterruptedException e) {
LOG.error("Error while signaling termination", e);
}
};
Platform.runLater(showDialog);
try {
queue.take();
} catch (InterruptedException e) {
LOG.error("Error while waiting for login dialog to close", e);
throw new IOException(e);
}
StripchatHttpClient httpClient = (StripchatHttpClient) site.getHttpClient(); StripchatHttpClient httpClient = (StripchatHttpClient) site.getHttpClient();
boolean loggedIn = httpClient.checkLoginSuccess(); boolean loggedIn = httpClient.checkLoginSuccess();
return loggedIn; return loggedIn;

View File

@ -28,6 +28,7 @@ import org.slf4j.Logger;
import org.slf4j.LoggerFactory; import org.slf4j.LoggerFactory;
import ctbrec.Config; import ctbrec.Config;
import ctbrec.GlobalThreadPool;
import ctbrec.Model; import ctbrec.Model;
import ctbrec.Recording; import ctbrec.Recording;
import ctbrec.Recording.State; import ctbrec.Recording.State;
@ -496,9 +497,9 @@ public class RecordingsTab extends Tab implements TabSelectionListener {
private void openContactSheet(JavaFxRecording recording) { private void openContactSheet(JavaFxRecording recording) {
if (config.getSettings().localRecording) { if (config.getSettings().localRecording) {
recording.getContactSheet().ifPresent(f -> new Thread(() -> DesktopIntegration.open(f)).start()); recording.getContactSheet().ifPresent(f -> GlobalThreadPool.submit(() -> DesktopIntegration.open(f)));
} else { } else {
recording.getContactSheet().ifPresent(f -> new Thread(() -> { recording.getContactSheet().ifPresent(f -> GlobalThreadPool.submit(() -> {
File target; File target;
try { try {
target = File.createTempFile("cs_", ".jpg"); target = File.createTempFile("cs_", ".jpg");
@ -516,7 +517,7 @@ public class RecordingsTab extends Tab implements TabSelectionListener {
} catch (IOException | InvalidKeyException | NoSuchAlgorithmException | IllegalStateException e) { } catch (IOException | InvalidKeyException | NoSuchAlgorithmException | IllegalStateException e) {
Dialogs.showError(getTabPane().getScene(), "Download Error", "An error occurred while downloading the contact sheet", e); Dialogs.showError(getTabPane().getScene(), "Download Error", "An error occurred while downloading the contact sheet", e);
} }
}).start()); }));
} }
} }
@ -526,7 +527,7 @@ public class RecordingsTab extends Tab implements TabSelectionListener {
Optional<String> newNote = Dialogs.showTextInput(source.getScene(), "Recording Notes", "", notes); Optional<String> newNote = Dialogs.showTextInput(source.getScene(), "Recording Notes", "", notes);
if (newNote.isPresent()) { if (newNote.isPresent()) {
table.setCursor(Cursor.WAIT); table.setCursor(Cursor.WAIT);
Thread backgroundThread = new Thread(() -> { GlobalThreadPool.submit(() -> {
List<Exception> exceptions = new ArrayList<>(); List<Exception> exceptions = new ArrayList<>();
try { try {
recording.setNote(newNote.get()); recording.setNote(newNote.get());
@ -542,13 +543,12 @@ public class RecordingsTab extends Tab implements TabSelectionListener {
}); });
} }
}); });
backgroundThread.start();
} }
} }
private void pin(List<JavaFxRecording> recordings) { private void pin(List<JavaFxRecording> recordings) {
table.setCursor(Cursor.WAIT); table.setCursor(Cursor.WAIT);
Thread backgroundThread = new Thread(() -> { GlobalThreadPool.submit(() -> {
List<Exception> exceptions = new ArrayList<>(); List<Exception> exceptions = new ArrayList<>();
try { try {
for (JavaFxRecording javaFxRecording : recordings) { for (JavaFxRecording javaFxRecording : recordings) {
@ -569,12 +569,11 @@ public class RecordingsTab extends Tab implements TabSelectionListener {
}); });
} }
}); });
backgroundThread.start();
} }
private void unpin(List<JavaFxRecording> recordings) { private void unpin(List<JavaFxRecording> recordings) {
table.setCursor(Cursor.WAIT); table.setCursor(Cursor.WAIT);
Thread backgroundThread = new Thread(() -> { GlobalThreadPool.submit(() -> {
List<Exception> exceptions = new ArrayList<>(); List<Exception> exceptions = new ArrayList<>();
try { try {
for (JavaFxRecording javaFxRecording : recordings) { for (JavaFxRecording javaFxRecording : recordings) {
@ -595,7 +594,6 @@ public class RecordingsTab extends Tab implements TabSelectionListener {
}); });
} }
}); });
backgroundThread.start();
} }
private void jumpToNextModel(KeyCode code) { private void jumpToNextModel(KeyCode code) {
@ -646,11 +644,11 @@ public class RecordingsTab extends Tab implements TabSelectionListener {
private void onOpenDirectory(JavaFxRecording first) { private void onOpenDirectory(JavaFxRecording first) {
File tsFile = first.getAbsoluteFile(); File tsFile = first.getAbsoluteFile();
new Thread(() -> DesktopIntegration.open(tsFile.getParent())).start(); GlobalThreadPool.submit(() -> DesktopIntegration.open(tsFile.getParent()));
} }
private void triggerPostProcessing(List<JavaFxRecording> recs) { private void triggerPostProcessing(List<JavaFxRecording> recs) {
new Thread(() -> { GlobalThreadPool.submit(() -> {
for (JavaFxRecording rec : recs) { for (JavaFxRecording rec : recs) {
try { try {
recorder.rerunPostProcessing(rec.getDelegate()); recorder.rerunPostProcessing(rec.getDelegate());
@ -659,7 +657,7 @@ public class RecordingsTab extends Tab implements TabSelectionListener {
LOG.error("Error while starting post-processing", e1); LOG.error("Error while starting post-processing", e1);
} }
} }
}).start(); });
} }
private void download(Recording recording) { private void download(Recording recording) {
@ -761,12 +759,12 @@ public class RecordingsTab extends Tab implements TabSelectionListener {
} }
private void play(Recording recording) { private void play(Recording recording) {
new Thread(() -> { GlobalThreadPool.submit(() -> {
boolean started = Player.play(recording); boolean started = Player.play(recording);
if (started && Config.getInstance().getSettings().showPlayerStarting) { if (started && Config.getInstance().getSettings().showPlayerStarting) {
Platform.runLater(() -> Toast.makeText(getTabPane().getScene(), "Starting Player", 2000, 500, 500)); Platform.runLater(() -> Toast.makeText(getTabPane().getScene(), "Starting Player", 2000, 500, 500));
} }
}).start(); });
} }
private void play(Model model) { private void play(Model model) {

View File

@ -8,8 +8,6 @@ import java.util.Locale;
import java.util.Objects; import java.util.Objects;
import java.util.concurrent.CompletableFuture; import java.util.concurrent.CompletableFuture;
import java.util.concurrent.ExecutionException; import java.util.concurrent.ExecutionException;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.TimeUnit; import java.util.concurrent.TimeUnit;
import java.util.function.Function; import java.util.function.Function;
@ -107,7 +105,6 @@ public class ThumbCell extends StackPane {
private ObservableList<Node> thumbCellList; private ObservableList<Node> thumbCellList;
private boolean mouseHovering = false; private boolean mouseHovering = false;
private boolean recording = false; private boolean recording = false;
private static ExecutorService imageLoadingThreadPool = Executors.newFixedThreadPool(30);
static LoadingCache<Model, int[]> resolutionCache = CacheBuilder.newBuilder() static LoadingCache<Model, int[]> resolutionCache = CacheBuilder.newBuilder()
.expireAfterAccess(5, TimeUnit.MINUTES) .expireAfterAccess(5, TimeUnit.MINUTES)
.maximumSize(10000) .maximumSize(10000)
@ -388,7 +385,7 @@ public class ThumbCell extends StackPane {
if (!Objects.equals(System.getenv("CTBREC_DEV"), "1")) { if (!Objects.equals(System.getenv("CTBREC_DEV"), "1")) {
boolean updateThumbs = Config.getInstance().getSettings().updateThumbnails; boolean updateThumbs = Config.getInstance().getSettings().updateThumbnails;
if (updateThumbs || iv.getImage() == null) { if (updateThumbs || iv.getImage() == null) {
imageLoadingThreadPool.submit(createThumbDownload(url)); GlobalThreadPool.submit(createThumbDownload(url));
} }
} }
} }
@ -513,7 +510,7 @@ public class ThumbCell extends StackPane {
void pauseResumeAction(boolean pause) { void pauseResumeAction(boolean pause) {
setCursor(Cursor.WAIT); setCursor(Cursor.WAIT);
new Thread(() -> { GlobalThreadPool.submit(() -> {
try { try {
if (pause) { if (pause) {
recorder.suspendRecording(model); recorder.suspendRecording(model);
@ -533,11 +530,11 @@ public class ThumbCell extends StackPane {
} finally { } finally {
Platform.runLater(() -> setCursor(Cursor.DEFAULT)); Platform.runLater(() -> setCursor(Cursor.DEFAULT));
} }
}).start(); });
} }
private void startStopActionAsync(Model model, boolean start) { private void startStopActionAsync(Model model, boolean start) {
new Thread(() -> { GlobalThreadPool.submit(() -> {
try { try {
if (start) { if (start) {
recorder.addModel(model); recorder.addModel(model);
@ -553,7 +550,7 @@ public class ThumbCell extends StackPane {
} finally { } finally {
Platform.runLater(() -> setCursor(Cursor.DEFAULT)); Platform.runLater(() -> setCursor(Cursor.DEFAULT));
} }
}).start(); });
} }
CompletableFuture<Boolean> follow(boolean follow) { CompletableFuture<Boolean> follow(boolean follow) {

View File

@ -27,6 +27,7 @@ import org.slf4j.Logger;
import org.slf4j.LoggerFactory; import org.slf4j.LoggerFactory;
import ctbrec.Config; import ctbrec.Config;
import ctbrec.GlobalThreadPool;
import ctbrec.Model; import ctbrec.Model;
import ctbrec.event.EventBusHolder; import ctbrec.event.EventBusHolder;
import ctbrec.recorder.Recorder; import ctbrec.recorder.Recorder;
@ -299,7 +300,7 @@ public class ThumbOverviewTab extends Tab implements TabSelectionListener {
return; return;
} }
searchTask = new ThumbOverviewTabSearchTask(site, popover, popoverTreeList, newValue); searchTask = new ThumbOverviewTabSearchTask(site, popover, popoverTreeList, newValue);
new Thread(searchTask).start(); GlobalThreadPool.submit(searchTask);
}; };
} }
@ -602,7 +603,7 @@ public class ThumbOverviewTab extends Tab implements TabSelectionListener {
private MenuItem createTipMenuItem(ThumbCell cell) { private MenuItem createTipMenuItem(ThumbCell cell) {
MenuItem sendTip = new MenuItem("Send Tip"); MenuItem sendTip = new MenuItem("Send Tip");
sendTip.setOnAction(e -> { sendTip.setOnAction(e -> {
TipDialog tipDialog = new TipDialog(getTabPane().getScene(), site, cell.getModel()); TipDialog tipDialog = new TipDialog(getTabPane().getScene(), site);
tipDialog.showAndWait(); tipDialog.showAndWait();
String tipText = tipDialog.getResult(); String tipText = tipDialog.getResult();
if(tipText != null) { if(tipText != null) {

View File

@ -8,7 +8,7 @@ import java.util.concurrent.Future;
public class GlobalThreadPool { public class GlobalThreadPool {
private static ExecutorService threadPool = Executors.newCachedThreadPool(r -> { private static ExecutorService threadPool = Executors.newFixedThreadPool(30, r -> {
Thread t = new Thread(r); Thread t = new Thread(r);
t.setDaemon(true); t.setDaemon(true);
t.setName("GlobalWorker-" + UUID.randomUUID().toString().substring(0, 8)); t.setName("GlobalWorker-" + UUID.randomUUID().toString().substring(0, 8));

View File

@ -82,9 +82,6 @@ public class MergedFfmpegHlsDownload extends AbstractHlsDownload {
public void start() throws IOException { public void start() throws IOException {
try { try {
running = true; running = true;
Thread.currentThread().setName("Download " + model.getName());
super.startTime = Instant.now();
String segments = getSegmentPlaylistUrl(model); String segments = getSegmentPlaylistUrl(model);
Files.createDirectories(targetFile.getParentFile().toPath()); Files.createDirectories(targetFile.getParentFile().toPath());

View File

@ -11,6 +11,7 @@ import org.slf4j.Logger;
import org.slf4j.LoggerFactory; import org.slf4j.LoggerFactory;
import ctbrec.Config; import ctbrec.Config;
import ctbrec.GlobalThreadPool;
import ctbrec.Model; import ctbrec.Model;
import ctbrec.io.HttpClient; import ctbrec.io.HttpClient;
import okhttp3.Request; import okhttp3.Request;
@ -78,9 +79,9 @@ public class LiveJasminTippingWebSocket {
LOG.trace("relay <-- {} T{}", model.getName(), text); LOG.trace("relay <-- {} T{}", model.getName(), text);
JSONObject event = new JSONObject(text); JSONObject event = new JSONObject(text);
if (event.optString("event").equals("accept")) { if (event.optString("event").equals("accept")) {
new Thread(() -> { GlobalThreadPool.submit(() -> {
sendToRelay("{\"event\":\"connectSharedObject\",\"name\":\"data/chat_so\"}"); sendToRelay("{\"event\":\"connectSharedObject\",\"name\":\"data/chat_so\"}");
}).start(); });
} else if(event.optString("event").equals("call")) { } else if(event.optString("event").equals("call")) {
String func = event.optString("funcName"); String func = event.optString("funcName");
if (func.equals("setName")) { if (func.equals("setName")) {

View File

@ -1,5 +1,6 @@
package ctbrec.recorder.server; package ctbrec.recorder.server;
import static java.nio.charset.StandardCharsets.*;
import static javax.servlet.http.HttpServletResponse.*; import static javax.servlet.http.HttpServletResponse.*;
import java.io.BufferedReader; import java.io.BufferedReader;
@ -53,6 +54,7 @@ import org.slf4j.LoggerFactory;
import com.google.common.base.Objects; import com.google.common.base.Objects;
import ctbrec.Config; import ctbrec.Config;
import ctbrec.NotLoggedInExcetion;
import ctbrec.Version; import ctbrec.Version;
import ctbrec.event.EventBusHolder; import ctbrec.event.EventBusHolder;
import ctbrec.event.EventHandler; import ctbrec.event.EventHandler;
@ -124,7 +126,7 @@ public class HttpServer {
if (success) { if (success) {
LOG.info("Successfully logged in to {}", site.getName()); LOG.info("Successfully logged in to {}", site.getName());
} else { } else {
throw new RuntimeException("Login returned false"); throw new NotLoggedInExcetion("Login returned false");
} }
} catch (Exception e) { } catch (Exception e) {
LOG.info("Login to {} failed", site.getName()); LOG.info("Login to {} failed", site.getName());
@ -243,7 +245,7 @@ public class HttpServer {
byte[] hmac = Optional.ofNullable(HttpServer.this.config.getSettings().key).orElse(new byte[0]); byte[] hmac = Optional.ofNullable(HttpServer.this.config.getSettings().key).orElse(new byte[0]);
try { try {
JSONObject response = new JSONObject(); JSONObject response = new JSONObject();
response.put("hmac", new String(hmac, "utf-8")); response.put("hmac", new String(hmac, UTF_8));
resp.getOutputStream().println(response.toString()); resp.getOutputStream().println(response.toString());
} catch (Exception e) { } catch (Exception e) {
resp.setStatus(HttpServletResponse.SC_INTERNAL_SERVER_ERROR); resp.setStatus(HttpServletResponse.SC_INTERNAL_SERVER_ERROR);

View File

@ -1,23 +1,7 @@
package ctbrec.recorder.server; package ctbrec.recorder.server;
import com.squareup.moshi.JsonAdapter; import static javax.servlet.http.HttpServletResponse.*;
import com.squareup.moshi.Moshi;
import ctbrec.Config;
import ctbrec.Model;
import ctbrec.Recording;
import ctbrec.io.BandwidthMeter;
import ctbrec.io.FileJsonAdapter;
import ctbrec.io.InstantJsonAdapter;
import ctbrec.io.ModelJsonAdapter;
import ctbrec.recorder.Recorder;
import ctbrec.sites.Site;
import org.json.JSONObject;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.File; import java.io.File;
import java.io.IOException; import java.io.IOException;
import java.security.InvalidKeyException; import java.security.InvalidKeyException;
@ -27,7 +11,27 @@ import java.util.Iterator;
import java.util.List; import java.util.List;
import java.util.Objects; import java.util.Objects;
import static javax.servlet.http.HttpServletResponse.*; import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.json.JSONObject;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import com.squareup.moshi.JsonAdapter;
import com.squareup.moshi.Moshi;
import ctbrec.Config;
import ctbrec.GlobalThreadPool;
import ctbrec.Model;
import ctbrec.Recording;
import ctbrec.io.BandwidthMeter;
import ctbrec.io.FileJsonAdapter;
import ctbrec.io.InstantJsonAdapter;
import ctbrec.io.ModelJsonAdapter;
import ctbrec.recorder.Recorder;
import ctbrec.sites.Site;
public class RecorderServlet extends AbstractCtbrecServlet { public class RecorderServlet extends AbstractCtbrecServlet {
@ -87,24 +91,24 @@ public class RecorderServlet extends AbstractCtbrecServlet {
resp.getWriter().write(response); resp.getWriter().write(response);
break; break;
case "stop": case "stop":
new Thread(() -> { GlobalThreadPool.submit(() -> {
try { try {
recorder.stopRecording(request.model); recorder.stopRecording(request.model);
} catch (InvalidKeyException | NoSuchAlgorithmException | IllegalStateException | IOException e) { } catch (InvalidKeyException | NoSuchAlgorithmException | IllegalStateException | IOException e) {
LOG.error("Couldn't stop recording for model {}", request.model, e); LOG.error("Couldn't stop recording for model {}", request.model, e);
} }
}).start(); });
response = "{\"status\": \"success\", \"msg\": \"Stopping recording\"}"; response = "{\"status\": \"success\", \"msg\": \"Stopping recording\"}";
resp.getWriter().write(response); resp.getWriter().write(response);
break; break;
case "stopAt": case "stopAt":
new Thread(() -> { GlobalThreadPool.submit(() -> {
try { try {
recorder.stopRecordingAt(request.model); recorder.stopRecordingAt(request.model);
} catch (InvalidKeyException | NoSuchAlgorithmException | IllegalStateException | IOException e) { } catch (InvalidKeyException | NoSuchAlgorithmException | IllegalStateException | IOException e) {
LOG.error("Couldn't stop recording for model {}", request.model, e); LOG.error("Couldn't stop recording for model {}", request.model, e);
} }
}).start(); });
response = "{\"status\": \"success\", \"msg\": \"Stopping recording\"}"; response = "{\"status\": \"success\", \"msg\": \"Stopping recording\"}";
resp.getWriter().write(response); resp.getWriter().write(response);
break; break;
@ -189,13 +193,13 @@ public class RecorderServlet extends AbstractCtbrecServlet {
break; break;
case "suspend": case "suspend":
LOG.debug("Suspend recording for model {} - {}", request.model.getName(), request.model.getUrl()); LOG.debug("Suspend recording for model {} - {}", request.model.getName(), request.model.getUrl());
new Thread(() -> { GlobalThreadPool.submit(() -> {
try { try {
recorder.suspendRecording(request.model); recorder.suspendRecording(request.model);
} catch (InvalidKeyException | NoSuchAlgorithmException | IllegalStateException | IOException e) { } catch (InvalidKeyException | NoSuchAlgorithmException | IllegalStateException | IOException e) {
LOG.error("Couldn't suspend recording for model {}", request.model, e); LOG.error("Couldn't suspend recording for model {}", request.model, e);
} }
}).start(); });
response = "{\"status\": \"success\", \"msg\": \"Suspending recording\"}"; response = "{\"status\": \"success\", \"msg\": \"Suspending recording\"}";
resp.getWriter().write(response); resp.getWriter().write(response);
break; break;