Convert Logback calls to Slf4j
This commit is contained in:
parent
31badfcc9c
commit
23f0d533c6
|
@ -1,5 +1,7 @@
|
||||||
package ctbrec.ui;
|
package ctbrec.ui;
|
||||||
|
|
||||||
|
|
||||||
|
import lombok.extern.slf4j.Slf4j;
|
||||||
import com.fasterxml.jackson.annotation.JsonProperty;
|
import com.fasterxml.jackson.annotation.JsonProperty;
|
||||||
import com.google.common.eventbus.Subscribe;
|
import com.google.common.eventbus.Subscribe;
|
||||||
import ctbrec.Config;
|
import ctbrec.Config;
|
||||||
|
@ -55,9 +57,6 @@ import javafx.scene.paint.Color;
|
||||||
import javafx.stage.Stage;
|
import javafx.stage.Stage;
|
||||||
import javafx.stage.WindowEvent;
|
import javafx.stage.WindowEvent;
|
||||||
import lombok.Data;
|
import lombok.Data;
|
||||||
import org.slf4j.Logger;
|
|
||||||
import org.slf4j.LoggerFactory;
|
|
||||||
|
|
||||||
import java.awt.*;
|
import java.awt.*;
|
||||||
import java.io.File;
|
import java.io.File;
|
||||||
import java.io.FileOutputStream;
|
import java.io.FileOutputStream;
|
||||||
|
@ -76,10 +75,9 @@ import static ctbrec.event.Event.Type.*;
|
||||||
import static javafx.scene.control.TabPane.TabDragPolicy.FIXED;
|
import static javafx.scene.control.TabPane.TabDragPolicy.FIXED;
|
||||||
import static javafx.scene.control.TabPane.TabDragPolicy.REORDER;
|
import static javafx.scene.control.TabPane.TabDragPolicy.REORDER;
|
||||||
|
|
||||||
|
@Slf4j
|
||||||
public class CamrecApplication extends Application {
|
public class CamrecApplication extends Application {
|
||||||
|
|
||||||
static final Logger LOG = LoggerFactory.getLogger(CamrecApplication.class);
|
|
||||||
|
|
||||||
private Config config;
|
private Config config;
|
||||||
private Recorder recorder;
|
private Recorder recorder;
|
||||||
private OnlineMonitor onlineMonitor;
|
private OnlineMonitor onlineMonitor;
|
||||||
|
@ -148,18 +146,18 @@ public class CamrecApplication extends Application {
|
||||||
@Subscribe
|
@Subscribe
|
||||||
public void trayActionRequest(Map<String, Object> evt) {
|
public void trayActionRequest(Map<String, Object> evt) {
|
||||||
if (Objects.equals("shutdown", evt.get("event"))) {
|
if (Objects.equals("shutdown", evt.get("event"))) {
|
||||||
LOG.debug("Shutdown request from tray icon");
|
log.debug("Shutdown request from tray icon");
|
||||||
try {
|
try {
|
||||||
Platform.runLater(() -> {
|
Platform.runLater(() -> {
|
||||||
primaryStage.show();
|
primaryStage.show();
|
||||||
shutdown();
|
shutdown();
|
||||||
});
|
});
|
||||||
} catch (Exception ex) {
|
} catch (Exception ex) {
|
||||||
LOG.error(ex.getMessage(), ex);
|
log.error(ex.getMessage(), ex);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (Objects.equals("stage_restored", evt.get("event"))) {
|
if (Objects.equals("stage_restored", evt.get("event"))) {
|
||||||
LOG.debug("Main stage restored");
|
log.debug("Main stage restored");
|
||||||
Platform.runLater(() -> {
|
Platform.runLater(() -> {
|
||||||
if (tabPane.getSelectionModel().getSelectedItem() instanceof TabSelectionListener listener) {
|
if (tabPane.getSelectionModel().getSelectedItem() instanceof TabSelectionListener listener) {
|
||||||
listener.selected();
|
listener.selected();
|
||||||
|
@ -203,7 +201,7 @@ public class CamrecApplication extends Application {
|
||||||
site.init();
|
site.init();
|
||||||
}
|
}
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
LOG.error("Error while initializing site {}", site.getName(), e);
|
log.error("Error while initializing site {}", site.getName(), e);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
@ -214,13 +212,13 @@ public class CamrecApplication extends Application {
|
||||||
}
|
}
|
||||||
|
|
||||||
private void logEnvironment() {
|
private void logEnvironment() {
|
||||||
LOG.debug("OS:\t{} {}", System.getProperty("os.name"), System.getProperty("os.version"));
|
log.debug("OS:\t{} {}", System.getProperty("os.name"), System.getProperty("os.version"));
|
||||||
LOG.debug("Java:\t{} {} {}", System.getProperty("java.vendor"), System.getProperty("java.vm.name"), System.getProperty("java.version"));
|
log.debug("Java:\t{} {} {}", System.getProperty("java.vendor"), System.getProperty("java.vm.name"), System.getProperty("java.version"));
|
||||||
LOG.debug("JavaFX:\t{} ({})", System.getProperty("javafx.version"), System.getProperty("javafx.runtime.version"));
|
log.debug("JavaFX:\t{} ({})", System.getProperty("javafx.version"), System.getProperty("javafx.runtime.version"));
|
||||||
}
|
}
|
||||||
|
|
||||||
private void createGui(Stage primaryStage) throws IOException {
|
private void createGui(Stage primaryStage) throws IOException {
|
||||||
LOG.debug("Creating GUI");
|
log.debug("Creating GUI");
|
||||||
DesktopIntegration.setRecorder(recorder);
|
DesktopIntegration.setRecorder(recorder);
|
||||||
DesktopIntegration.setPrimaryStage(primaryStage);
|
DesktopIntegration.setPrimaryStage(primaryStage);
|
||||||
CamrecApplication.title = "CTB Recorder " + Version.getVersion().toDisplayString();
|
CamrecApplication.title = "CTB Recorder " + Version.getVersion().toDisplayString();
|
||||||
|
@ -288,10 +286,10 @@ public class CamrecApplication extends Application {
|
||||||
});
|
});
|
||||||
|
|
||||||
if (config.getSettings().startMinimized) {
|
if (config.getSettings().startMinimized) {
|
||||||
LOG.info("Minimize to tray on start");
|
log.info("Minimize to tray on start");
|
||||||
DesktopIntegration.minimizeToTray(primaryStage);
|
DesktopIntegration.minimizeToTray(primaryStage);
|
||||||
} else {
|
} else {
|
||||||
LOG.info("Showing primary stage");
|
log.info("Showing primary stage");
|
||||||
primaryStage.show();
|
primaryStage.show();
|
||||||
}
|
}
|
||||||
primaryStage.setOnCloseRequest(createShutdownHandler());
|
primaryStage.setOnCloseRequest(createShutdownHandler());
|
||||||
|
@ -326,7 +324,7 @@ public class CamrecApplication extends Application {
|
||||||
l.selected();
|
l.selected();
|
||||||
}
|
}
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
LOG.error("Error switching tabs", e);
|
log.error("Error switching tabs", e);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -365,7 +363,7 @@ public class CamrecApplication extends Application {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} catch (InvalidKeyException | NoSuchAlgorithmException | IOException ex) {
|
} catch (InvalidKeyException | NoSuchAlgorithmException | IOException ex) {
|
||||||
LOG.warn("Couldn't check, if recordings are running");
|
log.warn("Couldn't check, if recordings are running");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -394,7 +392,7 @@ public class CamrecApplication extends Application {
|
||||||
try {
|
try {
|
||||||
Config.getInstance().save();
|
Config.getInstance().save();
|
||||||
clearHttpCache();
|
clearHttpCache();
|
||||||
LOG.info("Shutdown complete. Goodbye!");
|
log.info("Shutdown complete. Goodbye!");
|
||||||
Platform.runLater(() -> {
|
Platform.runLater(() -> {
|
||||||
primaryStage.close();
|
primaryStage.close();
|
||||||
shutdownInfo.close();
|
shutdownInfo.close();
|
||||||
|
@ -423,13 +421,13 @@ public class CamrecApplication extends Application {
|
||||||
private void clearHttpCache() throws IOException {
|
private void clearHttpCache() throws IOException {
|
||||||
try {
|
try {
|
||||||
File httpCacheDir = new File(config.getConfigDir(), "cache");
|
File httpCacheDir = new File(config.getConfigDir(), "cache");
|
||||||
LOG.debug("Deleting http cache {}", httpCacheDir);
|
log.debug("Deleting http cache {}", httpCacheDir);
|
||||||
HttpClientCacheProvider.getCache(config).evictAll();
|
HttpClientCacheProvider.getCache(config).evictAll();
|
||||||
HttpClientCacheProvider.getCache(config).close();
|
HttpClientCacheProvider.getCache(config).close();
|
||||||
IoUtils.deleteDirectory(httpCacheDir);
|
IoUtils.deleteDirectory(httpCacheDir);
|
||||||
LOG.debug("Cache has been deleted");
|
log.debug("Cache has been deleted");
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
LOG.info("The HTTP cache was not completely deleted: {}", e.getLocalizedMessage());
|
log.info("The HTTP cache was not completely deleted: {}", e.getLocalizedMessage());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -437,9 +435,9 @@ public class CamrecApplication extends Application {
|
||||||
for (EventHandlerConfiguration eventHandlerConfig : Config.getInstance().getSettings().eventHandlers) {
|
for (EventHandlerConfiguration eventHandlerConfig : Config.getInstance().getSettings().eventHandlers) {
|
||||||
var handler = new EventHandler(eventHandlerConfig);
|
var handler = new EventHandler(eventHandlerConfig);
|
||||||
EventBusHolder.register(handler);
|
EventBusHolder.register(handler);
|
||||||
LOG.debug("Registered event handler for {} {}", eventHandlerConfig.getEvent(), eventHandlerConfig.getName());
|
log.debug("Registered event handler for {} {}", eventHandlerConfig.getEvent(), eventHandlerConfig.getName());
|
||||||
}
|
}
|
||||||
LOG.debug("Alert System registered");
|
log.debug("Alert System registered");
|
||||||
}
|
}
|
||||||
|
|
||||||
private void registerActiveRecordingsCounter() {
|
private void registerActiveRecordingsCounter() {
|
||||||
|
@ -456,7 +454,7 @@ public class CamrecApplication extends Application {
|
||||||
Platform.runLater(() -> primaryStage.setTitle(windowTitle));
|
Platform.runLater(() -> primaryStage.setTitle(windowTitle));
|
||||||
updateStatus();
|
updateStatus();
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
LOG.warn("Couldn't update window title", e);
|
log.warn("Couldn't update window title", e);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -502,7 +500,7 @@ public class CamrecApplication extends Application {
|
||||||
+ " -fx-control-inner-background-alt: derive(-fx-base, 95%);\n" + "}";
|
+ " -fx-control-inner-background-alt: derive(-fx-base, 95%);\n" + "}";
|
||||||
fos.write(content.getBytes(StandardCharsets.UTF_8));
|
fos.write(content.getBytes(StandardCharsets.UTF_8));
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
LOG.error("Couldn't write stylesheet for user defined color theme");
|
log.error("Couldn't write stylesheet for user defined color theme");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -550,7 +548,7 @@ public class CamrecApplication extends Application {
|
||||||
try {
|
try {
|
||||||
recorder = new SimplifiedLocalRecorder(config, sites);
|
recorder = new SimplifiedLocalRecorder(config, sites);
|
||||||
} catch (IOException e) {
|
} catch (IOException e) {
|
||||||
LOG.error("Couldn't initialize recorder", e);
|
log.error("Couldn't initialize recorder", e);
|
||||||
Alert alert = new AutosizeAlert(Alert.AlertType.ERROR, primaryStage.getScene());
|
Alert alert = new AutosizeAlert(Alert.AlertType.ERROR, primaryStage.getScene());
|
||||||
alert.setTitle("Whoopsie");
|
alert.setTitle("Whoopsie");
|
||||||
alert.setContentText("Couldn't initialize recorder: " + e.getLocalizedMessage());
|
alert.setContentText("Couldn't initialize recorder: " + e.getLocalizedMessage());
|
||||||
|
@ -565,7 +563,7 @@ public class CamrecApplication extends Application {
|
||||||
try {
|
try {
|
||||||
Config.init(sites);
|
Config.init(sites);
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
LOG.error("Couldn't load settings", e);
|
log.error("Couldn't load settings", e);
|
||||||
Alert alert = new AutosizeAlert(Alert.AlertType.ERROR, primaryStage.getScene());
|
Alert alert = new AutosizeAlert(Alert.AlertType.ERROR, primaryStage.getScene());
|
||||||
alert.setTitle("Whoopsie");
|
alert.setTitle("Whoopsie");
|
||||||
alert.setContentText("Couldn't load settings. Falling back to defaults. A backup of your settings has been created.");
|
alert.setContentText("Couldn't load settings. Falling back to defaults. A backup of your settings has been created.");
|
||||||
|
|
|
@ -1,22 +1,19 @@
|
||||||
package ctbrec.ui;
|
package ctbrec.ui;
|
||||||
|
|
||||||
|
|
||||||
|
import lombok.extern.slf4j.Slf4j;
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.security.InvalidKeyException;
|
import java.security.InvalidKeyException;
|
||||||
import java.security.NoSuchAlgorithmException;
|
import java.security.NoSuchAlgorithmException;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Objects;
|
import java.util.Objects;
|
||||||
|
|
||||||
import org.slf4j.Logger;
|
|
||||||
import org.slf4j.LoggerFactory;
|
|
||||||
|
|
||||||
import ctbrec.recorder.Recorder;
|
import ctbrec.recorder.Recorder;
|
||||||
import ctbrec.sites.Site;
|
import ctbrec.sites.Site;
|
||||||
import javafx.application.Platform;
|
import javafx.application.Platform;
|
||||||
import javafx.scene.input.Clipboard;
|
import javafx.scene.input.Clipboard;
|
||||||
|
|
||||||
|
@Slf4j
|
||||||
public class ClipboardListener implements Runnable {
|
public class ClipboardListener implements Runnable {
|
||||||
|
|
||||||
private static final Logger LOG = LoggerFactory.getLogger(ClipboardListener.class);
|
|
||||||
private Recorder recorder;
|
private Recorder recorder;
|
||||||
private List<Site> sites;
|
private List<Site> sites;
|
||||||
private Clipboard systemClipboard;
|
private Clipboard systemClipboard;
|
||||||
|
@ -43,7 +40,7 @@ public class ClipboardListener implements Runnable {
|
||||||
addModelIfUrlMatches(url);
|
addModelIfUrlMatches(url);
|
||||||
}
|
}
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
LOG.error("Error in clipboard polling loop", e);
|
log.error("Error in clipboard polling loop", e);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,5 +1,7 @@
|
||||||
package ctbrec.ui;
|
package ctbrec.ui;
|
||||||
|
|
||||||
|
|
||||||
|
import lombok.extern.slf4j.Slf4j;
|
||||||
import ctbrec.Config;
|
import ctbrec.Config;
|
||||||
import ctbrec.OS;
|
import ctbrec.OS;
|
||||||
import ctbrec.StringUtil;
|
import ctbrec.StringUtil;
|
||||||
|
@ -12,22 +14,17 @@ import javafx.scene.control.Label;
|
||||||
import javafx.scene.control.TextField;
|
import javafx.scene.control.TextField;
|
||||||
import javafx.scene.layout.BorderPane;
|
import javafx.scene.layout.BorderPane;
|
||||||
import javafx.stage.Stage;
|
import javafx.stage.Stage;
|
||||||
import org.slf4j.Logger;
|
|
||||||
import org.slf4j.LoggerFactory;
|
|
||||||
|
|
||||||
import java.awt.*;
|
import java.awt.*;
|
||||||
import java.awt.TrayIcon.MessageType;
|
import java.awt.TrayIcon.MessageType;
|
||||||
import java.io.File;
|
import java.io.File;
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.net.URI;
|
import java.net.URI;
|
||||||
|
|
||||||
|
@Slf4j
|
||||||
public class DesktopIntegration {
|
public class DesktopIntegration {
|
||||||
|
|
||||||
private DesktopIntegration() {
|
private DesktopIntegration() {
|
||||||
}
|
}
|
||||||
|
|
||||||
private static final Logger LOG = LoggerFactory.getLogger(DesktopIntegration.class);
|
|
||||||
|
|
||||||
private static Recorder recorder;
|
private static Recorder recorder;
|
||||||
private static Stage primaryStage;
|
private static Stage primaryStage;
|
||||||
private static TrayIcon trayIcon;
|
private static TrayIcon trayIcon;
|
||||||
|
@ -42,7 +39,7 @@ public class DesktopIntegration {
|
||||||
rt.exec(cmdline);
|
rt.exec(cmdline);
|
||||||
return;
|
return;
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
LOG.debug("Couldn't open URL with user-defined {} {}", cmdline, uri);
|
log.debug("Couldn't open URL with user-defined {} {}", cmdline, uri);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -51,7 +48,7 @@ public class DesktopIntegration {
|
||||||
CamrecApplication.hostServices.showDocument(uri);
|
CamrecApplication.hostServices.showDocument(uri);
|
||||||
return;
|
return;
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
LOG.debug("Couldn't open URL with host services {}", uri);
|
log.debug("Couldn't open URL with host services {}", uri);
|
||||||
}
|
}
|
||||||
|
|
||||||
// opening with HostServices failed, now try Desktop
|
// opening with HostServices failed, now try Desktop
|
||||||
|
@ -59,7 +56,7 @@ public class DesktopIntegration {
|
||||||
Desktop.getDesktop().browse(new URI(uri));
|
Desktop.getDesktop().browse(new URI(uri));
|
||||||
return;
|
return;
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
LOG.debug("Couldn't open URL with Desktop {}", uri);
|
log.debug("Couldn't open URL with Desktop {}", uri);
|
||||||
}
|
}
|
||||||
|
|
||||||
// try external helpers
|
// try external helpers
|
||||||
|
@ -70,7 +67,7 @@ public class DesktopIntegration {
|
||||||
pb.start();
|
pb.start();
|
||||||
return;
|
return;
|
||||||
} catch (IOException e) {
|
} catch (IOException e) {
|
||||||
LOG.debug("Couldn't open URL with {} {}", helper, uri);
|
log.debug("Couldn't open URL with {} {}", helper, uri);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -112,7 +109,7 @@ public class DesktopIntegration {
|
||||||
Desktop.getDesktop().open(f);
|
Desktop.getDesktop().open(f);
|
||||||
return;
|
return;
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
LOG.debug("Couldn't open file with Desktop {}", f);
|
log.debug("Couldn't open file with Desktop {}", f);
|
||||||
}
|
}
|
||||||
|
|
||||||
// try external helpers
|
// try external helpers
|
||||||
|
@ -123,7 +120,7 @@ public class DesktopIntegration {
|
||||||
pb.start();
|
pb.start();
|
||||||
return;
|
return;
|
||||||
} catch (IOException e) {
|
} catch (IOException e) {
|
||||||
LOG.debug("Couldn't open file with {} {}", helper, f);
|
log.debug("Couldn't open file with {} {}", helper, f);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -171,7 +168,7 @@ public class DesktopIntegration {
|
||||||
} catch (NullPointerException e) {
|
} catch (NullPointerException e) {
|
||||||
// can happen at start, ignore
|
// can happen at start, ignore
|
||||||
} catch (IOException e1) {
|
} catch (IOException e1) {
|
||||||
LOG.error("Notification failed", e1);
|
log.error("Notification failed", e1);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -188,7 +185,7 @@ public class DesktopIntegration {
|
||||||
createTrayIcon(primaryStage);
|
createTrayIcon(primaryStage);
|
||||||
trayIcon.displayMessage(header, msg, MessageType.INFO);
|
trayIcon.displayMessage(header, msg, MessageType.INFO);
|
||||||
} else {
|
} else {
|
||||||
LOG.error("SystemTray notifications not supported by this OS");
|
log.error("SystemTray notifications not supported by this OS");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -209,7 +206,7 @@ public class DesktopIntegration {
|
||||||
}
|
}
|
||||||
return created;
|
return created;
|
||||||
} else {
|
} else {
|
||||||
LOG.error("SystemTray notifications not supported by this OS");
|
log.error("SystemTray notifications not supported by this OS");
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,22 +1,18 @@
|
||||||
package ctbrec.ui;
|
package ctbrec.ui;
|
||||||
|
|
||||||
|
|
||||||
|
import lombok.extern.slf4j.Slf4j;
|
||||||
import java.io.File;
|
import java.io.File;
|
||||||
import java.io.FileOutputStream;
|
import java.io.FileOutputStream;
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.io.InputStream;
|
import java.io.InputStream;
|
||||||
import java.net.URL;
|
import java.net.URL;
|
||||||
|
|
||||||
import org.slf4j.Logger;
|
|
||||||
import org.slf4j.LoggerFactory;
|
|
||||||
|
|
||||||
import ctbrec.io.HttpClient;
|
import ctbrec.io.HttpClient;
|
||||||
import ctbrec.recorder.ProgressListener;
|
import ctbrec.recorder.ProgressListener;
|
||||||
import okhttp3.Request;
|
import okhttp3.Request;
|
||||||
|
|
||||||
|
@Slf4j
|
||||||
public class FileDownload {
|
public class FileDownload {
|
||||||
|
|
||||||
private static final Logger LOG = LoggerFactory.getLogger(FileDownload.class);
|
|
||||||
|
|
||||||
private HttpClient httpClient;
|
private HttpClient httpClient;
|
||||||
private ProgressListener downloadListener;
|
private ProgressListener downloadListener;
|
||||||
|
|
||||||
|
@ -26,7 +22,7 @@ public class FileDownload {
|
||||||
}
|
}
|
||||||
|
|
||||||
public void start(URL url, File target) throws IOException {
|
public void start(URL url, File target) throws IOException {
|
||||||
LOG.trace("Downloading file {} to {}", url, target);
|
log.trace("Downloading file {} to {}", url, target);
|
||||||
var request = new Request.Builder().url(url).addHeader("connection", "keep-alive").build();
|
var request = new Request.Builder().url(url).addHeader("connection", "keep-alive").build();
|
||||||
var response = httpClient.execute(request);
|
var response = httpClient.execute(request);
|
||||||
var fileSize = Long.parseLong(response.header("Content-Length", String.valueOf(Long.MAX_VALUE)));
|
var fileSize = Long.parseLong(response.header("Content-Length", String.valueOf(Long.MAX_VALUE)));
|
||||||
|
|
|
@ -1,20 +1,16 @@
|
||||||
package ctbrec.ui;
|
package ctbrec.ui;
|
||||||
|
|
||||||
import org.slf4j.Logger;
|
import lombok.extern.slf4j.Slf4j;
|
||||||
import org.slf4j.LoggerFactory;
|
|
||||||
|
|
||||||
import ctbrec.Java;
|
import ctbrec.Java;
|
||||||
|
|
||||||
|
@Slf4j
|
||||||
public class Launcher {
|
public class Launcher {
|
||||||
|
|
||||||
private static final Logger LOG = LoggerFactory.getLogger(Launcher.class);
|
|
||||||
|
|
||||||
public static void main(String[] args) {
|
public static void main(String[] args) {
|
||||||
int javaVersion = Java.version();
|
int javaVersion = Java.version();
|
||||||
if(javaVersion == 0) {
|
if(javaVersion == 0) {
|
||||||
LOG.warn("Unknown Java version {}. App might not work as expected", javaVersion);
|
log.warn("Unknown Java version {}. App might not work as expected", javaVersion);
|
||||||
} else if (javaVersion < 10) {
|
} else if (javaVersion < 10) {
|
||||||
LOG.error("Your Java version ({}) is too old. Please update to Java 10 or newer", javaVersion);
|
log.error("Your Java version ({}) is too old. Please update to Java 10 or newer", javaVersion);
|
||||||
System.exit(1);
|
System.exit(1);
|
||||||
}
|
}
|
||||||
System.setProperty("awt.useSystemAAFontSettings","lcd");
|
System.setProperty("awt.useSystemAAFontSettings","lcd");
|
||||||
|
|
|
@ -1,5 +1,7 @@
|
||||||
package ctbrec.ui;
|
package ctbrec.ui;
|
||||||
|
|
||||||
|
|
||||||
|
import lombok.extern.slf4j.Slf4j;
|
||||||
import static ctbrec.SubsequentAction.*;
|
import static ctbrec.SubsequentAction.*;
|
||||||
|
|
||||||
import java.time.Instant;
|
import java.time.Instant;
|
||||||
|
@ -7,9 +9,6 @@ import java.time.LocalDateTime;
|
||||||
import java.time.ZoneId;
|
import java.time.ZoneId;
|
||||||
|
|
||||||
import ctbrec.Config;
|
import ctbrec.Config;
|
||||||
import org.slf4j.Logger;
|
|
||||||
import org.slf4j.LoggerFactory;
|
|
||||||
|
|
||||||
import ctbrec.Model;
|
import ctbrec.Model;
|
||||||
import ctbrec.SubsequentAction;
|
import ctbrec.SubsequentAction;
|
||||||
import ctbrec.ui.controls.DateTimePicker;
|
import ctbrec.ui.controls.DateTimePicker;
|
||||||
|
@ -24,10 +23,8 @@ import javafx.scene.control.ToggleGroup;
|
||||||
import javafx.scene.layout.GridPane;
|
import javafx.scene.layout.GridPane;
|
||||||
import javafx.scene.layout.VBox;
|
import javafx.scene.layout.VBox;
|
||||||
|
|
||||||
|
@Slf4j
|
||||||
public class RecordUntilDialog {
|
public class RecordUntilDialog {
|
||||||
|
|
||||||
private static final Logger LOG = LoggerFactory.getLogger(RecordUntilDialog.class);
|
|
||||||
|
|
||||||
private final Node source;
|
private final Node source;
|
||||||
private final Model model;
|
private final Model model;
|
||||||
private final GridPane gridPane = new GridPane();
|
private final GridPane gridPane = new GridPane();
|
||||||
|
@ -85,7 +82,7 @@ public class RecordUntilDialog {
|
||||||
boolean confirmed = Dialogs.showCustomInput(source.getScene(), "Stop Recording of " + model.getDisplayName() + " at", gridPane);
|
boolean confirmed = Dialogs.showCustomInput(source.getScene(), "Stop Recording of " + model.getDisplayName() + " at", gridPane);
|
||||||
if (confirmed) {
|
if (confirmed) {
|
||||||
SubsequentAction action = getSubsequentAction();
|
SubsequentAction action = getSubsequentAction();
|
||||||
LOG.info("Stop at {} and {}", datePicker.getDateTimeValue(), action);
|
log.info("Stop at {} and {}", datePicker.getDateTimeValue(), action);
|
||||||
var stopAt = Instant.from(datePicker.getDateTimeValue().atZone(ZoneId.systemDefault()));
|
var stopAt = Instant.from(datePicker.getDateTimeValue().atZone(ZoneId.systemDefault()));
|
||||||
model.setRecordUntil(stopAt);
|
model.setRecordUntil(stopAt);
|
||||||
model.setRecordUntilSubsequentAction(action);
|
model.setRecordUntilSubsequentAction(action);
|
||||||
|
|
|
@ -1,12 +1,10 @@
|
||||||
package ctbrec.ui;
|
package ctbrec.ui;
|
||||||
|
|
||||||
|
|
||||||
|
import lombok.extern.slf4j.Slf4j;
|
||||||
import java.util.Collections;
|
import java.util.Collections;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.concurrent.ExecutionException;
|
import java.util.concurrent.ExecutionException;
|
||||||
|
|
||||||
import org.slf4j.Logger;
|
|
||||||
import org.slf4j.LoggerFactory;
|
|
||||||
|
|
||||||
import ctbrec.GlobalThreadPool;
|
import ctbrec.GlobalThreadPool;
|
||||||
import ctbrec.Model;
|
import ctbrec.Model;
|
||||||
import ctbrec.recorder.download.StreamSource;
|
import ctbrec.recorder.download.StreamSource;
|
||||||
|
@ -20,10 +18,8 @@ import javafx.scene.control.ChoiceDialog;
|
||||||
import javafx.scene.image.Image;
|
import javafx.scene.image.Image;
|
||||||
import javafx.stage.Stage;
|
import javafx.stage.Stage;
|
||||||
|
|
||||||
|
@Slf4j
|
||||||
public class StreamSourceSelectionDialog extends ChoiceDialog<StreamSource> {
|
public class StreamSourceSelectionDialog extends ChoiceDialog<StreamSource> {
|
||||||
|
|
||||||
private static final Logger LOG = LoggerFactory.getLogger(StreamSourceSelectionDialog.class);
|
|
||||||
|
|
||||||
public static final StreamSource BEST = new BestStreamSource();
|
public static final StreamSource BEST = new BestStreamSource();
|
||||||
public static final StreamSource LOADING = new LoadingStreamSource();
|
public static final StreamSource LOADING = new LoadingStreamSource();
|
||||||
private Scene parent;
|
private Scene parent;
|
||||||
|
@ -66,9 +62,9 @@ public class StreamSourceSelectionDialog extends ChoiceDialog<StreamSource> {
|
||||||
loadStreamSources.get();
|
loadStreamSources.get();
|
||||||
} catch (InterruptedException e) {
|
} catch (InterruptedException e) {
|
||||||
Thread.currentThread().interrupt();
|
Thread.currentThread().interrupt();
|
||||||
LOG.error("Couldn't fetch available stream sources", e);
|
log.error("Couldn't fetch available stream sources", e);
|
||||||
} catch (ExecutionException e) {
|
} catch (ExecutionException e) {
|
||||||
LOG.error("Couldn't fetch available stream sources", e);
|
log.error("Couldn't fetch available stream sources", e);
|
||||||
}
|
}
|
||||||
|
|
||||||
boolean confirmed = Dialogs.showConfirmDialog("Error loading stream resolutions", "Do you want to add the model anyway?", "Stream resolutions unknown", parent);
|
boolean confirmed = Dialogs.showConfirmDialog("Error loading stream resolutions", "Do you want to add the model anyway?", "Stream resolutions unknown", parent);
|
||||||
|
|
|
@ -1,12 +1,10 @@
|
||||||
package ctbrec.ui;
|
package ctbrec.ui;
|
||||||
|
|
||||||
|
|
||||||
|
import lombok.extern.slf4j.Slf4j;
|
||||||
import java.text.DecimalFormat;
|
import java.text.DecimalFormat;
|
||||||
import java.util.Objects;
|
import java.util.Objects;
|
||||||
import java.util.concurrent.ExecutionException;
|
import java.util.concurrent.ExecutionException;
|
||||||
|
|
||||||
import org.slf4j.Logger;
|
|
||||||
import org.slf4j.LoggerFactory;
|
|
||||||
|
|
||||||
import ctbrec.GlobalThreadPool;
|
import ctbrec.GlobalThreadPool;
|
||||||
import ctbrec.sites.Site;
|
import ctbrec.sites.Site;
|
||||||
import javafx.application.Platform;
|
import javafx.application.Platform;
|
||||||
|
@ -17,9 +15,8 @@ import javafx.scene.control.ButtonType;
|
||||||
import javafx.scene.control.TextInputDialog;
|
import javafx.scene.control.TextInputDialog;
|
||||||
import javafx.stage.Stage;
|
import javafx.stage.Stage;
|
||||||
|
|
||||||
|
@Slf4j
|
||||||
public class TipDialog extends TextInputDialog {
|
public class TipDialog extends TextInputDialog {
|
||||||
|
|
||||||
private static final Logger LOG = LoggerFactory.getLogger(TipDialog.class);
|
|
||||||
private Site site;
|
private Site site;
|
||||||
private Scene parent;
|
private Scene parent;
|
||||||
|
|
||||||
|
@ -84,7 +81,7 @@ public class TipDialog extends TextInputDialog {
|
||||||
}
|
}
|
||||||
|
|
||||||
private void handleExcetion(Exception e) {
|
private void handleExcetion(Exception e) {
|
||||||
LOG.error("Couldn't retrieve account balance", e);
|
log.error("Couldn't retrieve account balance", e);
|
||||||
showErrorDialog(e);
|
showErrorDialog(e);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1,5 +1,7 @@
|
||||||
package ctbrec.ui;
|
package ctbrec.ui;
|
||||||
|
|
||||||
|
|
||||||
|
import lombok.extern.slf4j.Slf4j;
|
||||||
import com.google.common.eventbus.Subscribe;
|
import com.google.common.eventbus.Subscribe;
|
||||||
import ctbrec.GlobalThreadPool;
|
import ctbrec.GlobalThreadPool;
|
||||||
import ctbrec.event.EventBusHolder;
|
import ctbrec.event.EventBusHolder;
|
||||||
|
@ -8,17 +10,13 @@ import javafx.application.Platform;
|
||||||
import javafx.concurrent.Task;
|
import javafx.concurrent.Task;
|
||||||
import javafx.scene.control.Label;
|
import javafx.scene.control.Label;
|
||||||
import javafx.scene.control.Tooltip;
|
import javafx.scene.control.Tooltip;
|
||||||
import org.slf4j.Logger;
|
|
||||||
import org.slf4j.LoggerFactory;
|
|
||||||
|
|
||||||
import java.text.DecimalFormat;
|
import java.text.DecimalFormat;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
import java.util.Objects;
|
import java.util.Objects;
|
||||||
import java.util.concurrent.ExecutionException;
|
import java.util.concurrent.ExecutionException;
|
||||||
|
|
||||||
|
@Slf4j
|
||||||
public class TokenLabel extends Label {
|
public class TokenLabel extends Label {
|
||||||
|
|
||||||
private static final Logger LOG = LoggerFactory.getLogger(TokenLabel.class);
|
|
||||||
private double tokens = -1;
|
private double tokens = -1;
|
||||||
private final Site site;
|
private final Site site;
|
||||||
|
|
||||||
|
@ -85,7 +83,7 @@ public class TokenLabel extends Label {
|
||||||
}
|
}
|
||||||
|
|
||||||
private void handleException(Exception 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()));
|
||||||
|
|
|
@ -1,14 +1,13 @@
|
||||||
package ctbrec.ui;
|
package ctbrec.ui;
|
||||||
|
|
||||||
|
|
||||||
|
import lombok.extern.slf4j.Slf4j;
|
||||||
import ctbrec.Config;
|
import ctbrec.Config;
|
||||||
import ctbrec.event.EventBusHolder;
|
import ctbrec.event.EventBusHolder;
|
||||||
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;
|
||||||
import javafx.stage.Stage;
|
import javafx.stage.Stage;
|
||||||
import org.slf4j.Logger;
|
|
||||||
import org.slf4j.LoggerFactory;
|
|
||||||
|
|
||||||
import javax.imageio.ImageIO;
|
import javax.imageio.ImageIO;
|
||||||
import javax.swing.*;
|
import javax.swing.*;
|
||||||
import java.awt.*;
|
import java.awt.*;
|
||||||
|
@ -26,10 +25,8 @@ import static java.awt.Font.BOLD;
|
||||||
import static java.awt.RenderingHints.KEY_ANTIALIASING;
|
import static java.awt.RenderingHints.KEY_ANTIALIASING;
|
||||||
import static java.awt.RenderingHints.VALUE_ANTIALIAS_ON;
|
import static java.awt.RenderingHints.VALUE_ANTIALIAS_ON;
|
||||||
|
|
||||||
|
@Slf4j
|
||||||
public class TrayIcon {
|
public class TrayIcon {
|
||||||
|
|
||||||
private static final Logger LOG = LoggerFactory.getLogger(TrayIcon.class);
|
|
||||||
|
|
||||||
private final Stage stage;
|
private final Stage stage;
|
||||||
private final Recorder recorder;
|
private final Recorder recorder;
|
||||||
private SystemTray tray;
|
private SystemTray tray;
|
||||||
|
@ -60,7 +57,7 @@ public class TrayIcon {
|
||||||
try {
|
try {
|
||||||
tray.add(awtTrayIcon);
|
tray.add(awtTrayIcon);
|
||||||
} catch (AWTException e) {
|
} catch (AWTException e) {
|
||||||
LOG.error("Couldn't add tray icon", e);
|
log.error("Couldn't add tray icon", e);
|
||||||
}
|
}
|
||||||
awtTrayIcon.addMouseListener(new MouseAdapter() {
|
awtTrayIcon.addMouseListener(new MouseAdapter() {
|
||||||
@Override
|
@Override
|
||||||
|
@ -73,7 +70,7 @@ public class TrayIcon {
|
||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
} else {
|
} else {
|
||||||
LOG.error("SystemTray notifications not supported by this OS");
|
log.error("SystemTray notifications not supported by this OS");
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -113,7 +110,7 @@ public class TrayIcon {
|
||||||
Platform.runLater(() -> {
|
Platform.runLater(() -> {
|
||||||
stage.setX(Config.getInstance().getSettings().windowX);
|
stage.setX(Config.getInstance().getSettings().windowX);
|
||||||
stage.setY(Config.getInstance().getSettings().windowY);
|
stage.setY(Config.getInstance().getSettings().windowY);
|
||||||
LOG.debug("Restoring window location {},{}", stage.getX(), stage.getY());
|
log.debug("Restoring window location {},{}", stage.getX(), stage.getY());
|
||||||
stage.setIconified(false);
|
stage.setIconified(false);
|
||||||
stage.show();
|
stage.show();
|
||||||
stage.toFront();
|
stage.toFront();
|
||||||
|
@ -146,7 +143,7 @@ public class TrayIcon {
|
||||||
awtTrayIcon.setImage(createImage(activeRecordings));
|
awtTrayIcon.setImage(createImage(activeRecordings));
|
||||||
}
|
}
|
||||||
} catch (IOException e) {
|
} catch (IOException e) {
|
||||||
LOG.error("Couldn't update tray icon image", e);
|
log.error("Couldn't update tray icon image", e);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1,14 +1,12 @@
|
||||||
package ctbrec.ui.action;
|
package ctbrec.ui.action;
|
||||||
|
|
||||||
|
|
||||||
|
import lombok.extern.slf4j.Slf4j;
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.function.Predicate;
|
import java.util.function.Predicate;
|
||||||
import java.util.stream.Collectors;
|
import java.util.stream.Collectors;
|
||||||
|
|
||||||
import org.slf4j.Logger;
|
|
||||||
import org.slf4j.LoggerFactory;
|
|
||||||
|
|
||||||
import ctbrec.GlobalThreadPool;
|
import ctbrec.GlobalThreadPool;
|
||||||
import ctbrec.Model;
|
import ctbrec.Model;
|
||||||
import ctbrec.recorder.Recorder;
|
import ctbrec.recorder.Recorder;
|
||||||
|
@ -16,9 +14,8 @@ import ctbrec.ui.controls.Dialogs;
|
||||||
import javafx.application.Platform;
|
import javafx.application.Platform;
|
||||||
import javafx.scene.control.Button;
|
import javafx.scene.control.Button;
|
||||||
|
|
||||||
|
@Slf4j
|
||||||
public class CheckModelAccountAction {
|
public class CheckModelAccountAction {
|
||||||
private static final Logger LOG = LoggerFactory.getLogger(CheckModelAccountAction.class);
|
|
||||||
|
|
||||||
private Button b;
|
private Button b;
|
||||||
|
|
||||||
private Recorder recorder;
|
private Recorder recorder;
|
||||||
|
@ -78,7 +75,7 @@ public class CheckModelAccountAction {
|
||||||
deletedAccounts.add(modelToCheck);
|
deletedAccounts.add(modelToCheck);
|
||||||
}
|
}
|
||||||
} catch (IOException e) {
|
} catch (IOException e) {
|
||||||
LOG.warn("Couldn't check, if model account still exists", e);
|
log.warn("Couldn't check, if model account still exists", e);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,20 +1,18 @@
|
||||||
package ctbrec.ui.action;
|
package ctbrec.ui.action;
|
||||||
|
|
||||||
|
|
||||||
|
import lombok.extern.slf4j.Slf4j;
|
||||||
import ctbrec.Model;
|
import ctbrec.Model;
|
||||||
import ctbrec.notes.ModelNotesService;
|
import ctbrec.notes.ModelNotesService;
|
||||||
import ctbrec.ui.CamrecApplication;
|
import ctbrec.ui.CamrecApplication;
|
||||||
import ctbrec.ui.controls.Dialogs;
|
import ctbrec.ui.controls.Dialogs;
|
||||||
import javafx.scene.Cursor;
|
import javafx.scene.Cursor;
|
||||||
import javafx.scene.Node;
|
import javafx.scene.Node;
|
||||||
import org.slf4j.Logger;
|
|
||||||
import org.slf4j.LoggerFactory;
|
|
||||||
|
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.util.Optional;
|
import java.util.Optional;
|
||||||
|
|
||||||
|
@Slf4j
|
||||||
public class EditNotesAction {
|
public class EditNotesAction {
|
||||||
private static final Logger LOG = LoggerFactory.getLogger(EditNotesAction.class);
|
|
||||||
|
|
||||||
private final Node source;
|
private final Node source;
|
||||||
private final Model model;
|
private final Model model;
|
||||||
private final Runnable callback;
|
private final Runnable callback;
|
||||||
|
@ -39,14 +37,14 @@ public class EditNotesAction {
|
||||||
notesService.removeModelNotes(model.getUrl());
|
notesService.removeModelNotes(model.getUrl());
|
||||||
}
|
}
|
||||||
} catch (IOException e) {
|
} catch (IOException e) {
|
||||||
LOG.warn("Couldn't save config", e);
|
log.warn("Couldn't save config", e);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
if (callback != null) {
|
if (callback != null) {
|
||||||
try {
|
try {
|
||||||
callback.run();
|
callback.run();
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
LOG.error("Error while executing callback", e);
|
log.error("Error while executing callback", e);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
|
|
|
@ -1,15 +1,13 @@
|
||||||
package ctbrec.ui.action;
|
package ctbrec.ui.action;
|
||||||
|
|
||||||
|
|
||||||
|
import lombok.extern.slf4j.Slf4j;
|
||||||
import java.util.LinkedList;
|
import java.util.LinkedList;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Objects;
|
import java.util.Objects;
|
||||||
import java.util.concurrent.ExecutionException;
|
import java.util.concurrent.ExecutionException;
|
||||||
import java.util.concurrent.Future;
|
import java.util.concurrent.Future;
|
||||||
import java.util.function.Consumer;
|
import java.util.function.Consumer;
|
||||||
|
|
||||||
import org.slf4j.Logger;
|
|
||||||
import org.slf4j.LoggerFactory;
|
|
||||||
|
|
||||||
import ctbrec.GlobalThreadPool;
|
import ctbrec.GlobalThreadPool;
|
||||||
import ctbrec.Model;
|
import ctbrec.Model;
|
||||||
import ctbrec.ui.controls.Dialogs;
|
import ctbrec.ui.controls.Dialogs;
|
||||||
|
@ -17,10 +15,8 @@ import javafx.application.Platform;
|
||||||
import javafx.scene.Cursor;
|
import javafx.scene.Cursor;
|
||||||
import javafx.scene.Node;
|
import javafx.scene.Node;
|
||||||
|
|
||||||
|
@Slf4j
|
||||||
public class ModelMassEditAction {
|
public class ModelMassEditAction {
|
||||||
|
|
||||||
private static final Logger LOG = LoggerFactory.getLogger(ModelMassEditAction.class);
|
|
||||||
|
|
||||||
protected List<? extends Model> models;
|
protected List<? extends Model> models;
|
||||||
protected Consumer<Model> action;
|
protected Consumer<Model> action;
|
||||||
protected Node source;
|
protected Node source;
|
||||||
|
@ -64,7 +60,7 @@ public class ModelMassEditAction {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (ex != null) {
|
if (ex != null) {
|
||||||
LOG.error("Error while executing model mass edit", ex);
|
log.error("Error while executing model mass edit", ex);
|
||||||
Dialogs.showError(source.getScene(), "Error", "Error while execution action", ex);
|
Dialogs.showError(source.getScene(), "Error", "Error while execution action", ex);
|
||||||
}
|
}
|
||||||
Platform.runLater(() -> source.setCursor(Cursor.DEFAULT));
|
Platform.runLater(() -> source.setCursor(Cursor.DEFAULT));
|
||||||
|
|
|
@ -1,5 +1,7 @@
|
||||||
package ctbrec.ui.action;
|
package ctbrec.ui.action;
|
||||||
|
|
||||||
|
|
||||||
|
import lombok.extern.slf4j.Slf4j;
|
||||||
import ctbrec.Model;
|
import ctbrec.Model;
|
||||||
import ctbrec.StringUtil;
|
import ctbrec.StringUtil;
|
||||||
import ctbrec.ui.CamrecApplication;
|
import ctbrec.ui.CamrecApplication;
|
||||||
|
@ -10,9 +12,6 @@ import javafx.scene.Cursor;
|
||||||
import javafx.scene.Node;
|
import javafx.scene.Node;
|
||||||
import javafx.scene.control.Label;
|
import javafx.scene.control.Label;
|
||||||
import javafx.scene.layout.GridPane;
|
import javafx.scene.layout.GridPane;
|
||||||
import org.slf4j.Logger;
|
|
||||||
import org.slf4j.LoggerFactory;
|
|
||||||
|
|
||||||
import javax.imageio.ImageIO;
|
import javax.imageio.ImageIO;
|
||||||
import java.awt.image.BufferedImage;
|
import java.awt.image.BufferedImage;
|
||||||
import java.io.File;
|
import java.io.File;
|
||||||
|
@ -20,9 +19,8 @@ import java.io.IOException;
|
||||||
import java.util.Arrays;
|
import java.util.Arrays;
|
||||||
import java.util.function.Consumer;
|
import java.util.function.Consumer;
|
||||||
|
|
||||||
|
@Slf4j
|
||||||
public class SetPortraitAction extends AbstractPortraitAction {
|
public class SetPortraitAction extends AbstractPortraitAction {
|
||||||
private static final Logger LOG = LoggerFactory.getLogger(SetPortraitAction.class);
|
|
||||||
|
|
||||||
private final Consumer<Model> callback;
|
private final Consumer<Model> callback;
|
||||||
|
|
||||||
public SetPortraitAction(Node source, Model selectedModel, Consumer<Model> callback) {
|
public SetPortraitAction(Node source, Model selectedModel, Consumer<Model> callback) {
|
||||||
|
@ -50,7 +48,7 @@ public class SetPortraitAction extends AbstractPortraitAction {
|
||||||
if (StringUtil.isBlank(selectedFile)) {
|
if (StringUtil.isBlank(selectedFile)) {
|
||||||
removePortrait(model.getUrl());
|
removePortrait(model.getUrl());
|
||||||
} else {
|
} else {
|
||||||
LOG.debug("User selected {}", selectedFile);
|
log.debug("User selected {}", selectedFile);
|
||||||
boolean success = processImageFile(selectedFile);
|
boolean success = processImageFile(selectedFile);
|
||||||
if (success) {
|
if (success) {
|
||||||
try {
|
try {
|
||||||
|
@ -79,7 +77,7 @@ public class SetPortraitAction extends AbstractPortraitAction {
|
||||||
try {
|
try {
|
||||||
callback.accept(model);
|
callback.accept(model);
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
LOG.error("Error while executing callback", e);
|
log.error("Error while executing callback", e);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -91,12 +89,12 @@ public class SetPortraitAction extends AbstractPortraitAction {
|
||||||
BufferedImage portrait = convertToScaledJpg(croppedImage);
|
BufferedImage portrait = convertToScaledJpg(croppedImage);
|
||||||
boolean success = store(model.getUrl(), portrait);
|
boolean success = store(model.getUrl(), portrait);
|
||||||
if (!success) {
|
if (!success) {
|
||||||
LOG.debug("Available formats: {}", Arrays.toString(ImageIO.getWriterFormatNames()));
|
log.debug("Available formats: {}", Arrays.toString(ImageIO.getWriterFormatNames()));
|
||||||
throw new IOException("No suitable writer found for image format " + FORMAT);
|
throw new IOException("No suitable writer found for image format " + FORMAT);
|
||||||
}
|
}
|
||||||
return success;
|
return success;
|
||||||
} catch (IOException e) {
|
} catch (IOException e) {
|
||||||
LOG.error("Error while changing portrait image", e);
|
log.error("Error while changing portrait image", e);
|
||||||
Dialogs.showError("Set Portrait", "Couldn't change portrait image: ", e);
|
Dialogs.showError("Set Portrait", "Couldn't change portrait image: ", e);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,13 +1,11 @@
|
||||||
package ctbrec.ui.action;
|
package ctbrec.ui.action;
|
||||||
|
|
||||||
|
|
||||||
|
import lombok.extern.slf4j.Slf4j;
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.security.InvalidKeyException;
|
import java.security.InvalidKeyException;
|
||||||
import java.security.NoSuchAlgorithmException;
|
import java.security.NoSuchAlgorithmException;
|
||||||
import java.util.concurrent.CompletableFuture;
|
import java.util.concurrent.CompletableFuture;
|
||||||
|
|
||||||
import org.slf4j.Logger;
|
|
||||||
import org.slf4j.LoggerFactory;
|
|
||||||
|
|
||||||
import ctbrec.GlobalThreadPool;
|
import ctbrec.GlobalThreadPool;
|
||||||
import ctbrec.Model;
|
import ctbrec.Model;
|
||||||
import ctbrec.recorder.Recorder;
|
import ctbrec.recorder.Recorder;
|
||||||
|
@ -18,10 +16,8 @@ import javafx.application.Platform;
|
||||||
import javafx.scene.Cursor;
|
import javafx.scene.Cursor;
|
||||||
import javafx.scene.Node;
|
import javafx.scene.Node;
|
||||||
|
|
||||||
|
@Slf4j
|
||||||
public class SetStopDateAction {
|
public class SetStopDateAction {
|
||||||
|
|
||||||
private static final Logger LOG = LoggerFactory.getLogger(SetStopDateAction.class);
|
|
||||||
|
|
||||||
private Node source;
|
private Node source;
|
||||||
private Model model;
|
private Model model;
|
||||||
private Recorder recorder;
|
private Recorder recorder;
|
||||||
|
@ -48,7 +44,7 @@ public class SetStopDateAction {
|
||||||
}, GlobalThreadPool.get()).whenComplete((r, e) -> {
|
}, GlobalThreadPool.get()).whenComplete((r, e) -> {
|
||||||
Platform.runLater(() -> source.setCursor(Cursor.DEFAULT));
|
Platform.runLater(() -> source.setCursor(Cursor.DEFAULT));
|
||||||
if (e != null) {
|
if (e != null) {
|
||||||
LOG.error("Error", e);
|
log.error("Error", e);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,5 +1,7 @@
|
||||||
package ctbrec.ui.action;
|
package ctbrec.ui.action;
|
||||||
|
|
||||||
|
|
||||||
|
import lombok.extern.slf4j.Slf4j;
|
||||||
import ctbrec.GlobalThreadPool;
|
import ctbrec.GlobalThreadPool;
|
||||||
import ctbrec.Model;
|
import ctbrec.Model;
|
||||||
import ctbrec.ui.controls.Dialogs;
|
import ctbrec.ui.controls.Dialogs;
|
||||||
|
@ -8,15 +10,10 @@ import javafx.embed.swing.SwingFXUtils;
|
||||||
import javafx.scene.Cursor;
|
import javafx.scene.Cursor;
|
||||||
import javafx.scene.Node;
|
import javafx.scene.Node;
|
||||||
import javafx.scene.image.Image;
|
import javafx.scene.image.Image;
|
||||||
import org.slf4j.Logger;
|
|
||||||
import org.slf4j.LoggerFactory;
|
|
||||||
|
|
||||||
import java.awt.image.BufferedImage;
|
import java.awt.image.BufferedImage;
|
||||||
|
|
||||||
|
@Slf4j
|
||||||
public class SetThumbAsPortraitAction extends AbstractPortraitAction {
|
public class SetThumbAsPortraitAction extends AbstractPortraitAction {
|
||||||
|
|
||||||
private static final Logger LOG = LoggerFactory.getLogger(SetThumbAsPortraitAction.class);
|
|
||||||
|
|
||||||
private final Image image;
|
private final Image image;
|
||||||
|
|
||||||
public SetThumbAsPortraitAction(Node source, Model model, Image image) {
|
public SetThumbAsPortraitAction(Node source, Model model, Image image) {
|
||||||
|
@ -35,7 +32,7 @@ public class SetThumbAsPortraitAction extends AbstractPortraitAction {
|
||||||
store(model.getUrl(), portrait);
|
store(model.getUrl(), portrait);
|
||||||
firePortraitChanged();
|
firePortraitChanged();
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
LOG.error("Error while changing portrait image", e);
|
log.error("Error while changing portrait image", e);
|
||||||
Platform.runLater(() -> Dialogs.showError("Set Portrait", "Couldn't change portrait image: ", e));
|
Platform.runLater(() -> Dialogs.showError("Set Portrait", "Couldn't change portrait image: ", e));
|
||||||
} finally {
|
} finally {
|
||||||
Platform.runLater(() -> source.setCursor(Cursor.DEFAULT));
|
Platform.runLater(() -> source.setCursor(Cursor.DEFAULT));
|
||||||
|
|
|
@ -1,5 +1,7 @@
|
||||||
package ctbrec.ui.action;
|
package ctbrec.ui.action;
|
||||||
|
|
||||||
|
|
||||||
|
import lombok.extern.slf4j.Slf4j;
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.security.InvalidKeyException;
|
import java.security.InvalidKeyException;
|
||||||
import java.security.NoSuchAlgorithmException;
|
import java.security.NoSuchAlgorithmException;
|
||||||
|
@ -8,9 +10,6 @@ import java.util.concurrent.CompletableFuture;
|
||||||
import java.util.concurrent.ExecutionException;
|
import java.util.concurrent.ExecutionException;
|
||||||
|
|
||||||
import org.eclipse.jetty.io.RuntimeIOException;
|
import org.eclipse.jetty.io.RuntimeIOException;
|
||||||
import org.slf4j.Logger;
|
|
||||||
import org.slf4j.LoggerFactory;
|
|
||||||
|
|
||||||
import ctbrec.GlobalThreadPool;
|
import ctbrec.GlobalThreadPool;
|
||||||
import ctbrec.Model;
|
import ctbrec.Model;
|
||||||
import ctbrec.recorder.Recorder;
|
import ctbrec.recorder.Recorder;
|
||||||
|
@ -22,9 +21,8 @@ import javafx.application.Platform;
|
||||||
import javafx.scene.Cursor;
|
import javafx.scene.Cursor;
|
||||||
import javafx.scene.Node;
|
import javafx.scene.Node;
|
||||||
|
|
||||||
|
@Slf4j
|
||||||
public class SwitchStreamResolutionAction {
|
public class SwitchStreamResolutionAction {
|
||||||
private static final Logger LOG = LoggerFactory.getLogger(SwitchStreamResolutionAction.class);
|
|
||||||
|
|
||||||
private Node source;
|
private Node source;
|
||||||
private Model selectedModel;
|
private Model selectedModel;
|
||||||
private Recorder recorder;
|
private Recorder recorder;
|
||||||
|
@ -54,7 +52,7 @@ public class SwitchStreamResolutionAction {
|
||||||
try {
|
try {
|
||||||
recorder.switchStreamSource(selectedModel);
|
recorder.switchStreamSource(selectedModel);
|
||||||
} catch (InvalidKeyException | NoSuchAlgorithmException | IllegalStateException | IOException e) {
|
} catch (InvalidKeyException | NoSuchAlgorithmException | IllegalStateException | IOException e) {
|
||||||
LOG.error(couldntSwitchHeaderText, e);
|
log.error(couldntSwitchHeaderText, e);
|
||||||
Dialogs.showError(source.getScene(), "Couldn't switch stream resolution", "Error while switching stream resolution", e);
|
Dialogs.showError(source.getScene(), "Couldn't switch stream resolution", "Error while switching stream resolution", e);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,15 +1,13 @@
|
||||||
package ctbrec.ui.action;
|
package ctbrec.ui.action;
|
||||||
|
|
||||||
|
|
||||||
|
import lombok.extern.slf4j.Slf4j;
|
||||||
import static ctbrec.ui.controls.Dialogs.*;
|
import static ctbrec.ui.controls.Dialogs.*;
|
||||||
|
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.text.DecimalFormat;
|
import java.text.DecimalFormat;
|
||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
|
|
||||||
import org.slf4j.Logger;
|
|
||||||
import org.slf4j.LoggerFactory;
|
|
||||||
|
|
||||||
import ctbrec.Model;
|
import ctbrec.Model;
|
||||||
import ctbrec.event.EventBusHolder;
|
import ctbrec.event.EventBusHolder;
|
||||||
import ctbrec.ui.SiteUiFactory;
|
import ctbrec.ui.SiteUiFactory;
|
||||||
|
@ -17,10 +15,8 @@ import ctbrec.ui.TipDialog;
|
||||||
import javafx.scene.Cursor;
|
import javafx.scene.Cursor;
|
||||||
import javafx.scene.Node;
|
import javafx.scene.Node;
|
||||||
|
|
||||||
|
@Slf4j
|
||||||
public class TipAction {
|
public class TipAction {
|
||||||
|
|
||||||
private static final Logger LOG = LoggerFactory.getLogger(TipAction.class);
|
|
||||||
|
|
||||||
private Model model;
|
private Model model;
|
||||||
private Node source;
|
private Node source;
|
||||||
|
|
||||||
|
@ -47,7 +43,7 @@ public class TipAction {
|
||||||
event.put("amount", tokens.doubleValue());
|
event.put("amount", tokens.doubleValue());
|
||||||
EventBusHolder.BUS.post(event);
|
EventBusHolder.BUS.post(event);
|
||||||
} catch (IOException ex) {
|
} catch (IOException ex) {
|
||||||
LOG.error("An error occurred while sending tip", ex);
|
log.error("An error occurred while sending tip", ex);
|
||||||
showError(source.getScene(), "Couldn't send tip", "An error occurred while sending tip:", ex);
|
showError(source.getScene(), "Couldn't send tip", "An error occurred while sending tip:", ex);
|
||||||
} catch (Exception ex) {
|
} catch (Exception ex) {
|
||||||
showError(source.getScene(), "Couldn't send tip", "You entered an invalid amount of tokens", ex);
|
showError(source.getScene(), "Couldn't send tip", "You entered an invalid amount of tokens", ex);
|
||||||
|
|
|
@ -1,12 +1,10 @@
|
||||||
package ctbrec.ui.controls;
|
package ctbrec.ui.controls;
|
||||||
|
|
||||||
|
|
||||||
|
import lombok.extern.slf4j.Slf4j;
|
||||||
import java.io.File;
|
import java.io.File;
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.util.Objects;
|
import java.util.Objects;
|
||||||
|
|
||||||
import org.slf4j.Logger;
|
|
||||||
import org.slf4j.LoggerFactory;
|
|
||||||
|
|
||||||
import ctbrec.StringUtil;
|
import ctbrec.StringUtil;
|
||||||
import ctbrec.ui.AutosizeAlert;
|
import ctbrec.ui.AutosizeAlert;
|
||||||
import javafx.beans.property.SimpleStringProperty;
|
import javafx.beans.property.SimpleStringProperty;
|
||||||
|
@ -26,10 +24,8 @@ import javafx.scene.layout.Priority;
|
||||||
import javafx.scene.paint.Color;
|
import javafx.scene.paint.Color;
|
||||||
import javafx.stage.FileChooser;
|
import javafx.stage.FileChooser;
|
||||||
|
|
||||||
|
@Slf4j
|
||||||
public abstract class AbstractFileSelectionBox extends HBox {
|
public abstract class AbstractFileSelectionBox extends HBox {
|
||||||
|
|
||||||
private static final Logger LOG = LoggerFactory.getLogger(AbstractFileSelectionBox.class);
|
|
||||||
|
|
||||||
private final StringProperty fileProperty = new SimpleStringProperty();
|
private final StringProperty fileProperty = new SimpleStringProperty();
|
||||||
private final Tooltip validationError = new Tooltip();
|
private final Tooltip validationError = new Tooltip();
|
||||||
protected TextField fileInput;
|
protected TextField fileInput;
|
||||||
|
@ -151,7 +147,7 @@ public abstract class AbstractFileSelectionBox extends HBox {
|
||||||
try {
|
try {
|
||||||
fileInput.setText(program.getCanonicalPath());
|
fileInput.setText(program.getCanonicalPath());
|
||||||
} catch (IOException e1) {
|
} catch (IOException e1) {
|
||||||
LOG.error("Couldn't determine path", e1);
|
log.error("Couldn't determine path", e1);
|
||||||
var alert = new AutosizeAlert(Alert.AlertType.ERROR, getScene());
|
var alert = new AutosizeAlert(Alert.AlertType.ERROR, getScene());
|
||||||
alert.setTitle("Whoopsie");
|
alert.setTitle("Whoopsie");
|
||||||
alert.setContentText("Couldn't determine path");
|
alert.setContentText("Couldn't determine path");
|
||||||
|
|
|
@ -1,14 +1,12 @@
|
||||||
|
|
||||||
package ctbrec.ui.controls;
|
package ctbrec.ui.controls;
|
||||||
|
|
||||||
|
|
||||||
|
import lombok.extern.slf4j.Slf4j;
|
||||||
import java.time.LocalDate;
|
import java.time.LocalDate;
|
||||||
import java.time.LocalDateTime;
|
import java.time.LocalDateTime;
|
||||||
import java.time.LocalTime;
|
import java.time.LocalTime;
|
||||||
import java.time.format.DateTimeFormatter;
|
import java.time.format.DateTimeFormatter;
|
||||||
|
|
||||||
import org.slf4j.Logger;
|
|
||||||
import org.slf4j.LoggerFactory;
|
|
||||||
|
|
||||||
import javafx.beans.property.ObjectProperty;
|
import javafx.beans.property.ObjectProperty;
|
||||||
import javafx.beans.property.SimpleObjectProperty;
|
import javafx.beans.property.SimpleObjectProperty;
|
||||||
import javafx.scene.control.DatePicker;
|
import javafx.scene.control.DatePicker;
|
||||||
|
@ -25,8 +23,8 @@ import javafx.util.StringConverter;
|
||||||
* license Apache 2.0
|
* license Apache 2.0
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
|
@Slf4j
|
||||||
public class DateTimePicker extends DatePicker {
|
public class DateTimePicker extends DatePicker {
|
||||||
private static final Logger LOG = LoggerFactory.getLogger(DateTimePicker.class);
|
|
||||||
public static final String DefaultFormat = "yyyy-MM-dd HH:mm";
|
public static final String DefaultFormat = "yyyy-MM-dd HH:mm";
|
||||||
|
|
||||||
private DateTimeFormatter formatter;
|
private DateTimeFormatter formatter;
|
||||||
|
@ -56,7 +54,7 @@ public class DateTimePicker extends DatePicker {
|
||||||
dateTimeValue.set(LocalDateTime.of(newValue, time));
|
dateTimeValue.set(LocalDateTime.of(newValue, time));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
LOG.debug("{} {}", newValue, dateTimeValue);
|
log.debug("{} {}", newValue, dateTimeValue);
|
||||||
});
|
});
|
||||||
|
|
||||||
editorProperty().get().textProperty().addListener((obs, ov, nv) -> {
|
editorProperty().get().textProperty().addListener((obs, ov, nv) -> {
|
||||||
|
|
|
@ -31,6 +31,8 @@
|
||||||
*/
|
*/
|
||||||
package ctbrec.ui.controls;
|
package ctbrec.ui.controls;
|
||||||
|
|
||||||
|
|
||||||
|
import lombok.extern.slf4j.Slf4j;
|
||||||
import ctbrec.Config;
|
import ctbrec.Config;
|
||||||
import ctbrec.GlobalThreadPool;
|
import ctbrec.GlobalThreadPool;
|
||||||
import ctbrec.Model;
|
import ctbrec.Model;
|
||||||
|
@ -52,9 +54,6 @@ import javafx.scene.input.ContextMenuEvent;
|
||||||
import javafx.scene.input.MouseButton;
|
import javafx.scene.input.MouseButton;
|
||||||
import javafx.scene.input.MouseEvent;
|
import javafx.scene.input.MouseEvent;
|
||||||
import javafx.scene.shape.Rectangle;
|
import javafx.scene.shape.Rectangle;
|
||||||
import org.slf4j.Logger;
|
|
||||||
import org.slf4j.LoggerFactory;
|
|
||||||
|
|
||||||
import java.net.URL;
|
import java.net.URL;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Objects;
|
import java.util.Objects;
|
||||||
|
@ -63,9 +62,8 @@ import java.util.Optional;
|
||||||
/**
|
/**
|
||||||
* Popover page that displays a list of samples and sample categories for a given SampleCategory.
|
* Popover page that displays a list of samples and sample categories for a given SampleCategory.
|
||||||
*/
|
*/
|
||||||
|
@Slf4j
|
||||||
public class SearchPopoverTreeList extends PopoverTreeList<Model> implements Popover.Page {
|
public class SearchPopoverTreeList extends PopoverTreeList<Model> implements Popover.Page {
|
||||||
private static final Logger LOG = LoggerFactory.getLogger(SearchPopoverTreeList.class);
|
|
||||||
|
|
||||||
private Popover popover;
|
private Popover popover;
|
||||||
|
|
||||||
private Recorder recorder;
|
private Recorder recorder;
|
||||||
|
@ -195,9 +193,9 @@ public class SearchPopoverTreeList extends PopoverTreeList<Model> implements Pop
|
||||||
get();
|
get();
|
||||||
} catch (InterruptedException e) {
|
} catch (InterruptedException e) {
|
||||||
Thread.currentThread().interrupt();
|
Thread.currentThread().interrupt();
|
||||||
LOG.warn("Search failed: {}", e.getMessage());
|
log.warn("Search failed: {}", e.getMessage());
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
LOG.warn("Search failed: {}", e.getMessage());
|
log.warn("Search failed: {}", e.getMessage());
|
||||||
}
|
}
|
||||||
Platform.runLater(() -> setCursor(Cursor.DEFAULT));
|
Platform.runLater(() -> setCursor(Cursor.DEFAULT));
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,5 +1,7 @@
|
||||||
package ctbrec.ui.controls;
|
package ctbrec.ui.controls;
|
||||||
|
|
||||||
|
|
||||||
|
import lombok.extern.slf4j.Slf4j;
|
||||||
import java.io.InterruptedIOException;
|
import java.io.InterruptedIOException;
|
||||||
import java.util.Collections;
|
import java.util.Collections;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
@ -7,10 +9,6 @@ import java.util.concurrent.ExecutionException;
|
||||||
import java.util.concurrent.ExecutorService;
|
import java.util.concurrent.ExecutorService;
|
||||||
import java.util.concurrent.Executors;
|
import java.util.concurrent.Executors;
|
||||||
import java.util.concurrent.Future;
|
import java.util.concurrent.Future;
|
||||||
|
|
||||||
import org.slf4j.Logger;
|
|
||||||
import org.slf4j.LoggerFactory;
|
|
||||||
|
|
||||||
import ctbrec.Config;
|
import ctbrec.Config;
|
||||||
import ctbrec.GlobalThreadPool;
|
import ctbrec.GlobalThreadPool;
|
||||||
import ctbrec.Model;
|
import ctbrec.Model;
|
||||||
|
@ -27,9 +25,8 @@ import javafx.scene.media.Media;
|
||||||
import javafx.scene.media.MediaPlayer;
|
import javafx.scene.media.MediaPlayer;
|
||||||
import javafx.scene.media.MediaView;
|
import javafx.scene.media.MediaView;
|
||||||
|
|
||||||
|
@Slf4j
|
||||||
public class StreamPreview extends StackPane {
|
public class StreamPreview extends StackPane {
|
||||||
private static final Logger LOG = LoggerFactory.getLogger(StreamPreview.class);
|
|
||||||
|
|
||||||
private ImageView preview = new ImageView();
|
private ImageView preview = new ImageView();
|
||||||
private MediaView videoPreview;
|
private MediaView videoPreview;
|
||||||
private MediaPlayer videoPlayer;
|
private MediaPlayer videoPlayer;
|
||||||
|
@ -69,7 +66,7 @@ public class StreamPreview extends StackPane {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
running = true;
|
running = true;
|
||||||
LOG.debug("Starting preview stream for model {}", model);
|
log.debug("Starting preview stream for model {}", model);
|
||||||
progressIndicator.setVisible(true);
|
progressIndicator.setVisible(true);
|
||||||
if(model.getPreview() != null) {
|
if(model.getPreview() != null) {
|
||||||
try {
|
try {
|
||||||
|
@ -91,9 +88,9 @@ public class StreamPreview extends StackPane {
|
||||||
List<StreamSource> sources = model.getStreamSources();
|
List<StreamSource> sources = model.getStreamSources();
|
||||||
Collections.sort(sources);
|
Collections.sort(sources);
|
||||||
StreamSource best = sources.get(0);
|
StreamSource best = sources.get(0);
|
||||||
LOG.debug("StreamSource {}", best);
|
log.debug("StreamSource {}", best);
|
||||||
checkInterrupt();
|
checkInterrupt();
|
||||||
LOG.debug("Preview url for {} is {}", model.getName(), best.getMediaPlaylistUrl());
|
log.debug("Preview url for {} is {}", model.getName(), best.getMediaPlaylistUrl());
|
||||||
video = new Media(best.getMediaPlaylistUrl());
|
video = new Media(best.getMediaPlaylistUrl());
|
||||||
video.setOnError(() -> onError(videoPlayer));
|
video.setOnError(() -> onError(videoPlayer));
|
||||||
if(videoPlayer != null) {
|
if(videoPlayer != null) {
|
||||||
|
@ -121,12 +118,12 @@ public class StreamPreview extends StackPane {
|
||||||
if(e.getMessage().equals("Stream url unknown")) {
|
if(e.getMessage().equals("Stream url unknown")) {
|
||||||
// fine hls url for mfc not known yet
|
// fine hls url for mfc not known yet
|
||||||
} else {
|
} else {
|
||||||
LOG.warn("Couldn't start preview video: {}", e.getMessage());
|
log.warn("Couldn't start preview video: {}", e.getMessage());
|
||||||
}
|
}
|
||||||
showTestImage();
|
showTestImage();
|
||||||
} catch (HttpException e) {
|
} catch (HttpException e) {
|
||||||
if(e.getResponseCode() != 404) {
|
if(e.getResponseCode() != 404) {
|
||||||
LOG.warn("Couldn't start preview video: {}", e.getMessage());
|
log.warn("Couldn't start preview video: {}", e.getMessage());
|
||||||
}
|
}
|
||||||
showTestImage();
|
showTestImage();
|
||||||
} catch (InterruptedException | InterruptedIOException e) {
|
} catch (InterruptedException | InterruptedIOException e) {
|
||||||
|
@ -136,11 +133,11 @@ public class StreamPreview extends StackPane {
|
||||||
if(e.getCause() instanceof InterruptedException || e.getCause() instanceof InterruptedIOException) {
|
if(e.getCause() instanceof InterruptedException || e.getCause() instanceof InterruptedIOException) {
|
||||||
// future has been canceled, that's fine
|
// future has been canceled, that's fine
|
||||||
} else {
|
} else {
|
||||||
LOG.warn("Couldn't start preview video: {}", e.getMessage());
|
log.warn("Couldn't start preview video: {}", e.getMessage());
|
||||||
}
|
}
|
||||||
showTestImage();
|
showTestImage();
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
LOG.warn("Couldn't start preview video: {}", e.getMessage());
|
log.warn("Couldn't start preview video: {}", e.getMessage());
|
||||||
showTestImage();
|
showTestImage();
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
@ -169,7 +166,7 @@ public class StreamPreview extends StackPane {
|
||||||
}
|
}
|
||||||
|
|
||||||
private void onError(MediaPlayer videoPlayer) {
|
private void onError(MediaPlayer videoPlayer) {
|
||||||
LOG.error("Error while starting preview stream", videoPlayer.getError());
|
log.error("Error while starting preview stream", videoPlayer.getError());
|
||||||
showTestImage();
|
showTestImage();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1,8 +1,6 @@
|
||||||
package ctbrec.ui.controls;
|
package ctbrec.ui.controls;
|
||||||
|
|
||||||
import org.slf4j.Logger;
|
import lombok.extern.slf4j.Slf4j;
|
||||||
import org.slf4j.LoggerFactory;
|
|
||||||
|
|
||||||
import javafx.geometry.Insets;
|
import javafx.geometry.Insets;
|
||||||
import javafx.geometry.Pos;
|
import javafx.geometry.Pos;
|
||||||
import javafx.scene.control.Button;
|
import javafx.scene.control.Button;
|
||||||
|
@ -12,9 +10,9 @@ import javafx.scene.layout.Pane;
|
||||||
import javafx.scene.layout.StackPane;
|
import javafx.scene.layout.StackPane;
|
||||||
import javafx.stage.Stage;
|
import javafx.stage.Stage;
|
||||||
|
|
||||||
|
@Slf4j
|
||||||
public class Wizard extends BorderPane {
|
public class Wizard extends BorderPane {
|
||||||
|
|
||||||
private static final transient Logger LOG = LoggerFactory.getLogger(Wizard.class);
|
|
||||||
private Pane[] pages;
|
private Pane[] pages;
|
||||||
private StackPane stack;
|
private StackPane stack;
|
||||||
private Stage stage;
|
private Stage stage;
|
||||||
|
@ -90,7 +88,7 @@ public class Wizard extends BorderPane {
|
||||||
prev.setDisable(page == 0);
|
prev.setDisable(page == 0);
|
||||||
next.setDisable(page == pages.length - 1);
|
next.setDisable(page == pages.length - 1);
|
||||||
finish.setDisable(page != pages.length - 1);
|
finish.setDisable(page != pages.length - 1);
|
||||||
LOG.debug("Setting border");
|
log.debug("Setting border");
|
||||||
pages[page].setStyle(
|
pages[page].setStyle(
|
||||||
"-fx-background-color: -fx-inner-border, -fx-background;"+
|
"-fx-background-color: -fx-inner-border, -fx-background;"+
|
||||||
"-fx-background-insets: 0 0 -1 0, 0, 1, 2;");
|
"-fx-background-insets: 0 0 -1 0, 0, 1, 2;");
|
||||||
|
|
|
@ -1,25 +1,21 @@
|
||||||
package ctbrec.ui.controls.table;
|
package ctbrec.ui.controls.table;
|
||||||
|
|
||||||
|
|
||||||
|
import lombok.extern.slf4j.Slf4j;
|
||||||
import java.time.Duration;
|
import java.time.Duration;
|
||||||
import java.time.Instant;
|
import java.time.Instant;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
import java.util.Objects;
|
import java.util.Objects;
|
||||||
import java.util.stream.Collectors;
|
import java.util.stream.Collectors;
|
||||||
|
|
||||||
import org.slf4j.Logger;
|
|
||||||
import org.slf4j.LoggerFactory;
|
|
||||||
|
|
||||||
import ctbrec.StringUtil;
|
import ctbrec.StringUtil;
|
||||||
import javafx.collections.ListChangeListener;
|
import javafx.collections.ListChangeListener;
|
||||||
import javafx.collections.ObservableList;
|
import javafx.collections.ObservableList;
|
||||||
import javafx.scene.control.TableColumn;
|
import javafx.scene.control.TableColumn;
|
||||||
import javafx.scene.control.TableView;
|
import javafx.scene.control.TableView;
|
||||||
|
|
||||||
|
@Slf4j
|
||||||
public class StatePersistingTableView<T> extends TableView<T> {
|
public class StatePersistingTableView<T> extends TableView<T> {
|
||||||
|
|
||||||
private static final Logger LOG = LoggerFactory.getLogger(StatePersistingTableView.class);
|
|
||||||
|
|
||||||
private Instant initialized;
|
private Instant initialized;
|
||||||
private TableViewStateStore stateStore;
|
private TableViewStateStore stateStore;
|
||||||
|
|
||||||
|
@ -135,7 +131,7 @@ public class StatePersistingTableView<T> extends TableView<T> {
|
||||||
try {
|
try {
|
||||||
r.run();
|
r.run();
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
LOG.error("Couldn't safe table view state with prefix {}", stateStore.getName(), e);
|
log.error("Couldn't safe table view state with prefix {}", stateStore.getName(), e);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,10 +1,8 @@
|
||||||
package ctbrec.ui.menu;
|
package ctbrec.ui.menu;
|
||||||
|
|
||||||
|
|
||||||
|
import lombok.extern.slf4j.Slf4j;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
import org.slf4j.Logger;
|
|
||||||
import org.slf4j.LoggerFactory;
|
|
||||||
|
|
||||||
import ctbrec.Model;
|
import ctbrec.Model;
|
||||||
import ctbrec.recorder.Recorder;
|
import ctbrec.recorder.Recorder;
|
||||||
import ctbrec.ui.action.AbstractModelAction.Result;
|
import ctbrec.ui.action.AbstractModelAction.Result;
|
||||||
|
@ -13,10 +11,8 @@ import ctbrec.ui.action.TriConsumer;
|
||||||
import ctbrec.ui.action.UnfollowAction;
|
import ctbrec.ui.action.UnfollowAction;
|
||||||
import javafx.scene.Node;
|
import javafx.scene.Node;
|
||||||
|
|
||||||
|
@Slf4j
|
||||||
public class FollowUnfollowHandler {
|
public class FollowUnfollowHandler {
|
||||||
|
|
||||||
private static final Logger LOG = LoggerFactory.getLogger(FollowUnfollowHandler.class);
|
|
||||||
|
|
||||||
private Node source;
|
private Node source;
|
||||||
private Recorder recorder;
|
private Recorder recorder;
|
||||||
private TriConsumer<Model, Boolean, Boolean> callback;
|
private TriConsumer<Model, Boolean, Boolean> callback;
|
||||||
|
@ -32,7 +28,7 @@ public class FollowUnfollowHandler {
|
||||||
r.stream().filter(rs -> rs.getThrowable() == null).map(Result::getModel).forEach(m -> callback.accept(m, true, true));
|
r.stream().filter(rs -> rs.getThrowable() == null).map(Result::getModel).forEach(m -> callback.accept(m, true, true));
|
||||||
r.stream().filter(rs -> rs.getThrowable() != null).map(Result::getModel).forEach(m -> callback.accept(m, true, false));
|
r.stream().filter(rs -> rs.getThrowable() != null).map(Result::getModel).forEach(m -> callback.accept(m, true, false));
|
||||||
}).exceptionally(ex -> {
|
}).exceptionally(ex -> {
|
||||||
LOG.error("Couldn't follow model", ex);
|
log.error("Couldn't follow model", ex);
|
||||||
return null;
|
return null;
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
@ -42,7 +38,7 @@ public class FollowUnfollowHandler {
|
||||||
r.stream().filter(rs -> rs.getThrowable() == null).map(Result::getModel).forEach(m -> callback.accept(m, false, true));
|
r.stream().filter(rs -> rs.getThrowable() == null).map(Result::getModel).forEach(m -> callback.accept(m, false, true));
|
||||||
r.stream().filter(rs -> rs.getThrowable() != null).map(Result::getModel).forEach(m -> callback.accept(m, false, false));
|
r.stream().filter(rs -> rs.getThrowable() != null).map(Result::getModel).forEach(m -> callback.accept(m, false, false));
|
||||||
}).exceptionally(ex -> {
|
}).exceptionally(ex -> {
|
||||||
LOG.error("Couldn't unfollow model", ex);
|
log.error("Couldn't unfollow model", ex);
|
||||||
return null;
|
return null;
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,20 +1,16 @@
|
||||||
package ctbrec.ui.menu;
|
package ctbrec.ui.menu;
|
||||||
|
|
||||||
|
|
||||||
|
import lombok.extern.slf4j.Slf4j;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
import org.slf4j.Logger;
|
|
||||||
import org.slf4j.LoggerFactory;
|
|
||||||
|
|
||||||
import ctbrec.Model;
|
import ctbrec.Model;
|
||||||
import ctbrec.recorder.Recorder;
|
import ctbrec.recorder.Recorder;
|
||||||
import ctbrec.ui.action.ForcePriorityAction;
|
import ctbrec.ui.action.ForcePriorityAction;
|
||||||
import ctbrec.ui.action.ResumePriorityAction;
|
import ctbrec.ui.action.ResumePriorityAction;
|
||||||
import javafx.scene.Node;
|
import javafx.scene.Node;
|
||||||
|
|
||||||
|
@Slf4j
|
||||||
public class ForcePriorityHandler {
|
public class ForcePriorityHandler {
|
||||||
|
|
||||||
private static final Logger LOG = LoggerFactory.getLogger(ForcePriorityHandler.class);
|
|
||||||
|
|
||||||
private Node source;
|
private Node source;
|
||||||
private Recorder recorder;
|
private Recorder recorder;
|
||||||
private Runnable callback;
|
private Runnable callback;
|
||||||
|
@ -28,7 +24,7 @@ public class ForcePriorityHandler {
|
||||||
protected void forcePriority(List<Model> selectedModels) {
|
protected void forcePriority(List<Model> selectedModels) {
|
||||||
new ForcePriorityAction(source, selectedModels, recorder).execute()
|
new ForcePriorityAction(source, selectedModels, recorder).execute()
|
||||||
.exceptionally(ex -> {
|
.exceptionally(ex -> {
|
||||||
LOG.error("Error while forcing ignore priority", ex);
|
log.error("Error while forcing ignore priority", ex);
|
||||||
return null;
|
return null;
|
||||||
}).whenComplete((r, ex) -> executeCallback());
|
}).whenComplete((r, ex) -> executeCallback());
|
||||||
}
|
}
|
||||||
|
@ -36,7 +32,7 @@ public class ForcePriorityHandler {
|
||||||
protected void resumePriority(List<Model> selectedModels) {
|
protected void resumePriority(List<Model> selectedModels) {
|
||||||
new ResumePriorityAction(source, selectedModels, recorder).execute()
|
new ResumePriorityAction(source, selectedModels, recorder).execute()
|
||||||
.exceptionally(ex -> {
|
.exceptionally(ex -> {
|
||||||
LOG.error("Error while resuming respecting priority", ex);
|
log.error("Error while resuming respecting priority", ex);
|
||||||
return null;
|
return null;
|
||||||
}).whenComplete((r, ex) -> executeCallback());
|
}).whenComplete((r, ex) -> executeCallback());
|
||||||
}
|
}
|
||||||
|
@ -45,7 +41,7 @@ public class ForcePriorityHandler {
|
||||||
try {
|
try {
|
||||||
callback.run();
|
callback.run();
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
LOG.error("Error while executing menu callback", e);
|
log.error("Error while executing menu callback", e);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,5 +1,7 @@
|
||||||
package ctbrec.ui.menu;
|
package ctbrec.ui.menu;
|
||||||
|
|
||||||
|
|
||||||
|
import lombok.extern.slf4j.Slf4j;
|
||||||
import ctbrec.Config;
|
import ctbrec.Config;
|
||||||
import ctbrec.Model;
|
import ctbrec.Model;
|
||||||
import ctbrec.ModelGroup;
|
import ctbrec.ModelGroup;
|
||||||
|
@ -18,9 +20,6 @@ import javafx.scene.control.SeparatorMenuItem;
|
||||||
import javafx.scene.control.TabPane;
|
import javafx.scene.control.TabPane;
|
||||||
import javafx.scene.input.Clipboard;
|
import javafx.scene.input.Clipboard;
|
||||||
import javafx.scene.input.ClipboardContent;
|
import javafx.scene.input.ClipboardContent;
|
||||||
import org.slf4j.Logger;
|
|
||||||
import org.slf4j.LoggerFactory;
|
|
||||||
|
|
||||||
import java.net.URLEncoder;
|
import java.net.URLEncoder;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Optional;
|
import java.util.Optional;
|
||||||
|
@ -28,10 +27,8 @@ import java.util.function.Consumer;
|
||||||
|
|
||||||
import static java.nio.charset.StandardCharsets.UTF_8;
|
import static java.nio.charset.StandardCharsets.UTF_8;
|
||||||
|
|
||||||
|
@Slf4j
|
||||||
public class ModelMenuContributor {
|
public class ModelMenuContributor {
|
||||||
|
|
||||||
private static final Logger LOG = LoggerFactory.getLogger(ModelMenuContributor.class);
|
|
||||||
|
|
||||||
private final Config config;
|
private final Config config;
|
||||||
private final Recorder recorder;
|
private final Recorder recorder;
|
||||||
private final Node source;
|
private final Node source;
|
||||||
|
@ -431,7 +428,7 @@ public class ModelMenuContributor {
|
||||||
new StartRecordingAction(source, models, recorder).execute()
|
new StartRecordingAction(source, models, recorder).execute()
|
||||||
.whenComplete((r, ex) -> {
|
.whenComplete((r, ex) -> {
|
||||||
if (ex != null) {
|
if (ex != null) {
|
||||||
LOG.error("Error while starting recordings", ex);
|
log.error("Error while starting recordings", ex);
|
||||||
}
|
}
|
||||||
r.stream().map(Result::getModel).forEach(startStopCallback);
|
r.stream().map(Result::getModel).forEach(startStopCallback);
|
||||||
});
|
});
|
||||||
|
@ -443,7 +440,7 @@ public class ModelMenuContributor {
|
||||||
new StopRecordingAction(source, models, recorder).execute()
|
new StopRecordingAction(source, models, recorder).execute()
|
||||||
.whenComplete((r, ex) -> {
|
.whenComplete((r, ex) -> {
|
||||||
if (ex != null) {
|
if (ex != null) {
|
||||||
LOG.error("Error while stopping recordings", ex);
|
log.error("Error while stopping recordings", ex);
|
||||||
}
|
}
|
||||||
r.stream().map(Result::getModel).forEach(startStopCallback);
|
r.stream().map(Result::getModel).forEach(startStopCallback);
|
||||||
});
|
});
|
||||||
|
@ -465,7 +462,7 @@ public class ModelMenuContributor {
|
||||||
try {
|
try {
|
||||||
callback.run();
|
callback.run();
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
LOG.error("Error while executing menu callback", e);
|
log.error("Error while executing menu callback", e);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,20 +1,16 @@
|
||||||
package ctbrec.ui.menu;
|
package ctbrec.ui.menu;
|
||||||
|
|
||||||
|
|
||||||
|
import lombok.extern.slf4j.Slf4j;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
import org.slf4j.Logger;
|
|
||||||
import org.slf4j.LoggerFactory;
|
|
||||||
|
|
||||||
import ctbrec.Model;
|
import ctbrec.Model;
|
||||||
import ctbrec.recorder.Recorder;
|
import ctbrec.recorder.Recorder;
|
||||||
import ctbrec.ui.action.PauseAction;
|
import ctbrec.ui.action.PauseAction;
|
||||||
import ctbrec.ui.action.ResumeAction;
|
import ctbrec.ui.action.ResumeAction;
|
||||||
import javafx.scene.Node;
|
import javafx.scene.Node;
|
||||||
|
|
||||||
|
@Slf4j
|
||||||
public class PauseResumeHandler {
|
public class PauseResumeHandler {
|
||||||
|
|
||||||
private static final Logger LOG = LoggerFactory.getLogger(PauseResumeHandler.class);
|
|
||||||
|
|
||||||
private Node source;
|
private Node source;
|
||||||
private Recorder recorder;
|
private Recorder recorder;
|
||||||
private Runnable callback;
|
private Runnable callback;
|
||||||
|
@ -28,7 +24,7 @@ public class PauseResumeHandler {
|
||||||
protected void pause(List<Model> selectedModels) {
|
protected void pause(List<Model> selectedModels) {
|
||||||
new PauseAction(source, selectedModels, recorder).execute()
|
new PauseAction(source, selectedModels, recorder).execute()
|
||||||
.exceptionally(ex -> {
|
.exceptionally(ex -> {
|
||||||
LOG.error("Error while pausing recordings", ex);
|
log.error("Error while pausing recordings", ex);
|
||||||
return null;
|
return null;
|
||||||
}).whenComplete((r, ex) -> executeCallback());
|
}).whenComplete((r, ex) -> executeCallback());
|
||||||
}
|
}
|
||||||
|
@ -36,7 +32,7 @@ public class PauseResumeHandler {
|
||||||
protected void resume(List<Model> selectedModels) {
|
protected void resume(List<Model> selectedModels) {
|
||||||
new ResumeAction(source, selectedModels, recorder).execute()
|
new ResumeAction(source, selectedModels, recorder).execute()
|
||||||
.exceptionally(ex -> {
|
.exceptionally(ex -> {
|
||||||
LOG.error("Error while resuming recordings", ex);
|
log.error("Error while resuming recordings", ex);
|
||||||
return null;
|
return null;
|
||||||
}).whenComplete((r, ex) -> executeCallback());
|
}).whenComplete((r, ex) -> executeCallback());
|
||||||
}
|
}
|
||||||
|
@ -45,7 +41,7 @@ public class PauseResumeHandler {
|
||||||
try {
|
try {
|
||||||
callback.run();
|
callback.run();
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
LOG.error("Error while executing menu callback", e);
|
log.error("Error while executing menu callback", e);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,5 +1,7 @@
|
||||||
package ctbrec.ui.settings;
|
package ctbrec.ui.settings;
|
||||||
|
|
||||||
|
|
||||||
|
import lombok.extern.slf4j.Slf4j;
|
||||||
import ctbrec.recorder.postprocessing.PostProcessor;
|
import ctbrec.recorder.postprocessing.PostProcessor;
|
||||||
import ctbrec.ui.controls.DirectorySelectionBox;
|
import ctbrec.ui.controls.DirectorySelectionBox;
|
||||||
import ctbrec.ui.controls.ProgramSelectionBox;
|
import ctbrec.ui.controls.ProgramSelectionBox;
|
||||||
|
@ -10,16 +12,12 @@ import javafx.scene.Node;
|
||||||
import javafx.scene.control.*;
|
import javafx.scene.control.*;
|
||||||
import javafx.scene.layout.HBox;
|
import javafx.scene.layout.HBox;
|
||||||
import javafx.util.converter.NumberStringConverter;
|
import javafx.util.converter.NumberStringConverter;
|
||||||
import org.slf4j.Logger;
|
|
||||||
import org.slf4j.LoggerFactory;
|
|
||||||
|
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.util.HashSet;
|
import java.util.HashSet;
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
|
|
||||||
|
@Slf4j
|
||||||
public abstract class AbstractPostProcessingPaneFactory {
|
public abstract class AbstractPostProcessingPaneFactory {
|
||||||
|
|
||||||
private static final Logger LOG = LoggerFactory.getLogger(AbstractPostProcessingPaneFactory.class);
|
|
||||||
private PostProcessor pp;
|
private PostProcessor pp;
|
||||||
Set<Property<?>> properties = new HashSet<>();
|
Set<Property<?>> properties = new HashSet<>();
|
||||||
|
|
||||||
|
@ -36,7 +34,7 @@ public abstract class AbstractPostProcessingPaneFactory {
|
||||||
for (Property<?> property : properties) {
|
for (Property<?> property : properties) {
|
||||||
String key = property.getName();
|
String key = property.getName();
|
||||||
Object value = preferences.getSetting(key).get().getProperty().getValue();
|
Object value = preferences.getSetting(key).get().getProperty().getValue();
|
||||||
LOG.debug("{}={}", key, value);
|
log.debug("{}={}", key, value);
|
||||||
pp.getConfig().put(key, value.toString());
|
pp.getConfig().put(key, value.toString());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,5 +1,7 @@
|
||||||
package ctbrec.ui.settings;
|
package ctbrec.ui.settings;
|
||||||
|
|
||||||
|
|
||||||
|
import lombok.extern.slf4j.Slf4j;
|
||||||
import ctbrec.Config;
|
import ctbrec.Config;
|
||||||
import ctbrec.Model;
|
import ctbrec.Model;
|
||||||
import ctbrec.Recording;
|
import ctbrec.Recording;
|
||||||
|
@ -35,9 +37,6 @@ import javafx.stage.Modality;
|
||||||
import javafx.stage.Stage;
|
import javafx.stage.Stage;
|
||||||
import javafx.stage.Window;
|
import javafx.stage.Window;
|
||||||
import org.mapstruct.factory.Mappers;
|
import org.mapstruct.factory.Mappers;
|
||||||
import org.slf4j.Logger;
|
|
||||||
import org.slf4j.LoggerFactory;
|
|
||||||
|
|
||||||
import java.io.File;
|
import java.io.File;
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.io.InputStream;
|
import java.io.InputStream;
|
||||||
|
@ -52,8 +51,8 @@ import java.util.List;
|
||||||
import java.util.Objects;
|
import java.util.Objects;
|
||||||
import java.util.stream.Collectors;
|
import java.util.stream.Collectors;
|
||||||
|
|
||||||
|
@Slf4j
|
||||||
public class ActionSettingsPanel extends GridPane {
|
public class ActionSettingsPanel extends GridPane {
|
||||||
private static final Logger LOG = LoggerFactory.getLogger(ActionSettingsPanel.class);
|
|
||||||
private ListView<EventHandlerConfiguration> actionTable;
|
private ListView<EventHandlerConfiguration> actionTable;
|
||||||
|
|
||||||
private final TextField name = new TextField();
|
private final TextField name = new TextField();
|
||||||
|
@ -123,7 +122,7 @@ public class ActionSettingsPanel extends GridPane {
|
||||||
try {
|
try {
|
||||||
Config.getInstance().save();
|
Config.getInstance().save();
|
||||||
} catch (IOException e) {
|
} catch (IOException e) {
|
||||||
LOG.error("Couldn't save config", e);
|
log.error("Couldn't save config", e);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -203,7 +202,7 @@ public class ActionSettingsPanel extends GridPane {
|
||||||
EventBusHolder.register(handler);
|
EventBusHolder.register(handler);
|
||||||
Config.getInstance().getSettings().eventHandlers.add(config);
|
Config.getInstance().getSettings().eventHandlers.add(config);
|
||||||
actionTable.getItems().add(config);
|
actionTable.getItems().add(config);
|
||||||
LOG.debug("Registered event handler for {} {}", config.getEvent(), config.getName());
|
log.debug("Registered event handler for {} {}", config.getEvent(), config.getName());
|
||||||
}
|
}
|
||||||
|
|
||||||
private void validateSettings() {
|
private void validateSettings() {
|
||||||
|
|
|
@ -1,5 +1,7 @@
|
||||||
package ctbrec.ui.settings;
|
package ctbrec.ui.settings;
|
||||||
|
|
||||||
|
|
||||||
|
import lombok.extern.slf4j.Slf4j;
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.lang.reflect.InvocationTargetException;
|
import java.lang.reflect.InvocationTargetException;
|
||||||
import java.time.LocalTime;
|
import java.time.LocalTime;
|
||||||
|
@ -7,10 +9,6 @@ import java.time.LocalTime;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Objects;
|
import java.util.Objects;
|
||||||
import java.util.Optional;
|
import java.util.Optional;
|
||||||
|
|
||||||
import org.slf4j.Logger;
|
|
||||||
import org.slf4j.LoggerFactory;
|
|
||||||
|
|
||||||
import ctbrec.Config;
|
import ctbrec.Config;
|
||||||
import ctbrec.Settings;
|
import ctbrec.Settings;
|
||||||
import ctbrec.StringUtil;
|
import ctbrec.StringUtil;
|
||||||
|
@ -48,9 +46,8 @@ import javafx.scene.control.ToggleGroup;
|
||||||
import javafx.scene.layout.HBox;
|
import javafx.scene.layout.HBox;
|
||||||
import javafx.util.converter.NumberStringConverter;
|
import javafx.util.converter.NumberStringConverter;
|
||||||
|
|
||||||
|
@Slf4j
|
||||||
public class CtbrecPreferencesStorage implements PreferencesStorage {
|
public class CtbrecPreferencesStorage implements PreferencesStorage {
|
||||||
|
|
||||||
private static final Logger LOG = LoggerFactory.getLogger(CtbrecPreferencesStorage.class);
|
|
||||||
public static final String PATTERN_NOT_A_DIGIT = "[^\\d]";
|
public static final String PATTERN_NOT_A_DIGIT = "[^\\d]";
|
||||||
public static final String COULDNT_SAVE_MSG = "Couldn't save config setting";
|
public static final String COULDNT_SAVE_MSG = "Couldn't save config setting";
|
||||||
|
|
||||||
|
@ -142,7 +139,7 @@ public class CtbrecPreferencesStorage implements PreferencesStorage {
|
||||||
try {
|
try {
|
||||||
r.run();
|
r.run();
|
||||||
} catch (RuntimeException e) {
|
} catch (RuntimeException e) {
|
||||||
LOG.warn("Error while calling \"restart required\" callback", e);
|
log.warn("Error while calling \"restart required\" callback", e);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
@ -331,7 +328,7 @@ public class CtbrecPreferencesStorage implements PreferencesStorage {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
comboBox.valueProperty().addListener((obs, oldV, newV) -> saveValue(() -> {
|
comboBox.valueProperty().addListener((obs, oldV, newV) -> saveValue(() -> {
|
||||||
LOG.debug("Saving setting {}", setting.getKey());
|
log.debug("Saving setting {}", setting.getKey());
|
||||||
if (setIfChanged(setting.getKey(), setting.getConverter() != null ? setting.getConverter().convertFrom(newV) : newV)) {
|
if (setIfChanged(setting.getKey(), setting.getConverter() != null ? setting.getConverter().convertFrom(newV) : newV)) {
|
||||||
if (setting.doesNeedRestart()) {
|
if (setting.doesNeedRestart()) {
|
||||||
runRestartRequiredCallback();
|
runRestartRequiredCallback();
|
||||||
|
@ -379,7 +376,7 @@ public class CtbrecPreferencesStorage implements PreferencesStorage {
|
||||||
try {
|
try {
|
||||||
exe.run();
|
exe.run();
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
LOG.error(COULDNT_SAVE_MSG, e);
|
log.error(COULDNT_SAVE_MSG, e);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1,13 +1,11 @@
|
||||||
package ctbrec.ui.settings;
|
package ctbrec.ui.settings;
|
||||||
|
|
||||||
|
|
||||||
|
import lombok.extern.slf4j.Slf4j;
|
||||||
import java.io.File;
|
import java.io.File;
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.nio.file.Files;
|
import java.nio.file.Files;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
import org.slf4j.Logger;
|
|
||||||
import org.slf4j.LoggerFactory;
|
|
||||||
|
|
||||||
import ctbrec.Config;
|
import ctbrec.Config;
|
||||||
import ctbrec.ui.controls.Dialogs;
|
import ctbrec.ui.controls.Dialogs;
|
||||||
import javafx.collections.FXCollections;
|
import javafx.collections.FXCollections;
|
||||||
|
@ -18,10 +16,8 @@ import javafx.scene.control.ListCell;
|
||||||
import javafx.scene.layout.HBox;
|
import javafx.scene.layout.HBox;
|
||||||
import javafx.scene.text.Font;
|
import javafx.scene.text.Font;
|
||||||
|
|
||||||
|
@Slf4j
|
||||||
public class FontSettingsPane extends HBox {
|
public class FontSettingsPane extends HBox {
|
||||||
|
|
||||||
private static final Logger LOG = LoggerFactory.getLogger(FontSettingsPane.class);
|
|
||||||
|
|
||||||
private ComboBox<String> fontFaceCombo;
|
private ComboBox<String> fontFaceCombo;
|
||||||
private ComboBox<Integer> fontSizeCombo;
|
private ComboBox<Integer> fontSizeCombo;
|
||||||
|
|
||||||
|
@ -78,7 +74,7 @@ public class FontSettingsPane extends HBox {
|
||||||
Files.writeString(getFontCssFile().toPath(), css);
|
Files.writeString(getFontCssFile().toPath(), css);
|
||||||
settingsTab.showRestartRequired();
|
settingsTab.showRestartRequired();
|
||||||
} catch (IOException e) {
|
} catch (IOException e) {
|
||||||
LOG.error("Couldn't write font file", e);
|
log.error("Couldn't write font file", e);
|
||||||
Dialogs.showError(getScene(), "Error saving configuration", "The font stylesheet file couldn't be written", e);
|
Dialogs.showError(getScene(), "Error saving configuration", "The font stylesheet file couldn't be written", e);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -94,7 +90,7 @@ public class FontSettingsPane extends HBox {
|
||||||
Files.delete(getFontCssFile().toPath());
|
Files.delete(getFontCssFile().toPath());
|
||||||
settingsTab.showRestartRequired();
|
settingsTab.showRestartRequired();
|
||||||
} catch (IOException e) {
|
} catch (IOException e) {
|
||||||
LOG.error("Couldn't delete font file", e);
|
log.error("Couldn't delete font file", e);
|
||||||
Dialogs.showError(getScene(), "Error resetting font configuration", "The font stylesheet file couldn't be deleted", e);
|
Dialogs.showError(getScene(), "Error resetting font configuration", "The font stylesheet file couldn't be deleted", e);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
|
@ -1,5 +1,7 @@
|
||||||
package ctbrec.ui.settings;
|
package ctbrec.ui.settings;
|
||||||
|
|
||||||
|
|
||||||
|
import lombok.extern.slf4j.Slf4j;
|
||||||
import ctbrec.Config;
|
import ctbrec.Config;
|
||||||
import ctbrec.GlobalThreadPool;
|
import ctbrec.GlobalThreadPool;
|
||||||
import ctbrec.Hmac;
|
import ctbrec.Hmac;
|
||||||
|
@ -36,9 +38,6 @@ import javafx.scene.layout.*;
|
||||||
import javafx.scene.paint.Color;
|
import javafx.scene.paint.Color;
|
||||||
import javafx.util.Duration;
|
import javafx.util.Duration;
|
||||||
import lombok.Getter;
|
import lombok.Getter;
|
||||||
import org.slf4j.Logger;
|
|
||||||
import org.slf4j.LoggerFactory;
|
|
||||||
|
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.Arrays;
|
import java.util.Arrays;
|
||||||
|
@ -49,9 +48,8 @@ import static ctbrec.Settings.ProxyType.*;
|
||||||
import static ctbrec.Settings.SplitStrategy.*;
|
import static ctbrec.Settings.SplitStrategy.*;
|
||||||
import static java.util.Optional.ofNullable;
|
import static java.util.Optional.ofNullable;
|
||||||
|
|
||||||
|
@Slf4j
|
||||||
public class SettingsTab extends Tab implements TabSelectionListener {
|
public class SettingsTab extends Tab implements TabSelectionListener {
|
||||||
|
|
||||||
private static final Logger LOG = LoggerFactory.getLogger(SettingsTab.class);
|
|
||||||
public static final int CHECKBOX_MARGIN = 6;
|
public static final int CHECKBOX_MARGIN = 6;
|
||||||
private static final long MiB = 1024 * 1024L; // NOSONAR
|
private static final long MiB = 1024 * 1024L; // NOSONAR
|
||||||
private static final long GiB = 1024 * MiB; // NOSONAR
|
private static final long GiB = 1024 * MiB; // NOSONAR
|
||||||
|
@ -438,7 +436,7 @@ public class SettingsTab extends Tab implements TabSelectionListener {
|
||||||
try {
|
try {
|
||||||
DocServer.start();
|
DocServer.start();
|
||||||
} catch (Exception ex) {
|
} catch (Exception ex) {
|
||||||
LOG.error("Couldn't start documentation server", ex);
|
log.error("Couldn't start documentation server", ex);
|
||||||
}
|
}
|
||||||
}).start();
|
}).start();
|
||||||
DesktopIntegration.open(url);
|
DesktopIntegration.open(url);
|
||||||
|
@ -456,7 +454,7 @@ public class SettingsTab extends Tab implements TabSelectionListener {
|
||||||
try {
|
try {
|
||||||
s.getGui().disableProperty().bind(bindTo);
|
s.getGui().disableProperty().bind(bindTo);
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
LOG.error("Couldn't bind disableProperty of {}", s.getName(), e);
|
log.error("Couldn't bind disableProperty of {}", s.getName(), e);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -537,7 +535,7 @@ public class SettingsTab extends Tab implements TabSelectionListener {
|
||||||
try {
|
try {
|
||||||
Config.getInstance().save();
|
Config.getInstance().save();
|
||||||
} catch (IOException e) {
|
} catch (IOException e) {
|
||||||
LOG.error("Couldn't save config", e);
|
log.error("Couldn't save config", e);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,21 +1,17 @@
|
||||||
package ctbrec.ui.sites;
|
package ctbrec.ui.sites;
|
||||||
|
|
||||||
|
|
||||||
|
import lombok.extern.slf4j.Slf4j;
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
|
|
||||||
import org.slf4j.Logger;
|
|
||||||
import org.slf4j.LoggerFactory;
|
|
||||||
|
|
||||||
import ctbrec.Config;
|
import ctbrec.Config;
|
||||||
|
|
||||||
|
@Slf4j
|
||||||
public abstract class AbstractConfigUI implements ConfigUI {
|
public abstract class AbstractConfigUI implements ConfigUI {
|
||||||
|
|
||||||
private static final Logger LOG = LoggerFactory.getLogger(AbstractConfigUI.class);
|
|
||||||
|
|
||||||
protected void save() {
|
protected void save() {
|
||||||
try {
|
try {
|
||||||
Config.getInstance().save();
|
Config.getInstance().save();
|
||||||
} catch (IOException e) {
|
} catch (IOException e) {
|
||||||
LOG.error("Couldn't save config");
|
log.error("Couldn't save config");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,5 +1,7 @@
|
||||||
package ctbrec.ui.sites.bonga;
|
package ctbrec.ui.sites.bonga;
|
||||||
|
|
||||||
|
|
||||||
|
import lombok.extern.slf4j.Slf4j;
|
||||||
import ctbrec.Config;
|
import ctbrec.Config;
|
||||||
import ctbrec.sites.bonga.BongaCams;
|
import ctbrec.sites.bonga.BongaCams;
|
||||||
import ctbrec.ui.ExternalBrowser;
|
import ctbrec.ui.ExternalBrowser;
|
||||||
|
@ -8,9 +10,6 @@ import okhttp3.Cookie.Builder;
|
||||||
import okhttp3.CookieJar;
|
import okhttp3.CookieJar;
|
||||||
import okhttp3.HttpUrl;
|
import okhttp3.HttpUrl;
|
||||||
import org.json.JSONObject;
|
import org.json.JSONObject;
|
||||||
import org.slf4j.Logger;
|
|
||||||
import org.slf4j.LoggerFactory;
|
|
||||||
|
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.net.MalformedURLException;
|
import java.net.MalformedURLException;
|
||||||
// import java.net.URL;
|
// import java.net.URL;
|
||||||
|
@ -20,9 +19,8 @@ import java.util.Collections;
|
||||||
import java.util.Objects;
|
import java.util.Objects;
|
||||||
import java.util.function.Consumer;
|
import java.util.function.Consumer;
|
||||||
|
|
||||||
|
@Slf4j
|
||||||
public class BongaCamsElectronLoginDialog {
|
public class BongaCamsElectronLoginDialog {
|
||||||
|
|
||||||
private static final Logger LOG = LoggerFactory.getLogger(BongaCamsElectronLoginDialog.class);
|
|
||||||
public static final String DOMAIN = "bongacams.com";
|
public static final String DOMAIN = "bongacams.com";
|
||||||
private BongaCams site;
|
private BongaCams site;
|
||||||
private CookieJar cookieJar;
|
private CookieJar cookieJar;
|
||||||
|
@ -50,7 +48,7 @@ public class BongaCamsElectronLoginDialog {
|
||||||
|
|
||||||
private final Consumer<String> msgHandler = line -> {
|
private final Consumer<String> msgHandler = line -> {
|
||||||
if (!line.startsWith("{")) {
|
if (!line.startsWith("{")) {
|
||||||
LOG.error("Didn't received a JSON object {}", line);
|
log.error("Didn't received a JSON object {}", line);
|
||||||
} else {
|
} else {
|
||||||
var json = new JSONObject(line);
|
var json = new JSONObject(line);
|
||||||
if (json.has("url")) {
|
if (json.has("url")) {
|
||||||
|
@ -79,9 +77,9 @@ public class BongaCamsElectronLoginDialog {
|
||||||
}
|
}
|
||||||
} catch (InterruptedException e) {
|
} catch (InterruptedException e) {
|
||||||
Thread.currentThread().interrupt();
|
Thread.currentThread().interrupt();
|
||||||
LOG.warn("Couldn't auto fill username and password for BongaCams", e);
|
log.warn("Couldn't auto fill username and password for BongaCams", e);
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
LOG.warn("Couldn't auto fill username and password for BongaCams", e);
|
log.warn("Couldn't auto fill username and password for BongaCams", e);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -118,11 +116,11 @@ public class BongaCamsElectronLoginDialog {
|
||||||
browser.close();
|
browser.close();
|
||||||
}
|
}
|
||||||
} catch (MalformedURLException e) {
|
} catch (MalformedURLException e) {
|
||||||
LOG.error("Couldn't parse new url {}", url, e);
|
log.error("Couldn't parse new url {}", url, e);
|
||||||
} catch (IOException e) {
|
} catch (IOException e) {
|
||||||
LOG.error("Couldn't send shutdown request to external browser", e);
|
log.error("Couldn't send shutdown request to external browser", e);
|
||||||
} catch (URISyntaxException e) {
|
} catch (URISyntaxException e) {
|
||||||
LOG.error("Invalid URL: " + url);
|
log.error("Invalid URL: " + url);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,19 +1,17 @@
|
||||||
package ctbrec.ui.sites.bonga;
|
package ctbrec.ui.sites.bonga;
|
||||||
|
|
||||||
|
|
||||||
|
import lombok.extern.slf4j.Slf4j;
|
||||||
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.io.IOException;
|
||||||
|
|
||||||
|
@Slf4j
|
||||||
public class BongaCamsSiteUi extends AbstractSiteUi {
|
public class BongaCamsSiteUi extends AbstractSiteUi {
|
||||||
|
|
||||||
private static final Logger LOG = LoggerFactory.getLogger(BongaCamsSiteUi.class);
|
|
||||||
private final BongaCams bongaCams;
|
private final BongaCams bongaCams;
|
||||||
private BongaCamsTabProvider tabProvider;
|
private BongaCamsTabProvider tabProvider;
|
||||||
private BongaCamsConfigUI configUi;
|
private BongaCamsConfigUI configUi;
|
||||||
|
@ -48,16 +46,16 @@ public class BongaCamsSiteUi extends AbstractSiteUi {
|
||||||
try {
|
try {
|
||||||
new BongaCamsElectronLoginDialog(bongaCams, bongaCams.getHttpClient().getCookieJar());
|
new BongaCamsElectronLoginDialog(bongaCams, bongaCams.getHttpClient().getCookieJar());
|
||||||
} catch (Exception e1) {
|
} catch (Exception e1) {
|
||||||
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 " + bongaCams.getName(), e1);
|
Dialogs.showError("Login error", "Couldn't login to " + bongaCams.getName(), e1);
|
||||||
}
|
}
|
||||||
|
|
||||||
BongaCamsHttpClient httpClient = (BongaCamsHttpClient) bongaCams.getHttpClient();
|
BongaCamsHttpClient httpClient = (BongaCamsHttpClient) bongaCams.getHttpClient();
|
||||||
boolean loggedIn = httpClient.checkLoginSuccess();
|
boolean loggedIn = httpClient.checkLoginSuccess();
|
||||||
if (loggedIn) {
|
if (loggedIn) {
|
||||||
LOG.info("Logged in. User ID is {}", httpClient.getUserId());
|
log.info("Logged in. User ID is {}", httpClient.getUserId());
|
||||||
} else {
|
} else {
|
||||||
LOG.info("Login failed");
|
log.info("Login failed");
|
||||||
}
|
}
|
||||||
return loggedIn;
|
return loggedIn;
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,5 +1,7 @@
|
||||||
package ctbrec.ui.sites.bonga;
|
package ctbrec.ui.sites.bonga;
|
||||||
|
|
||||||
|
|
||||||
|
import lombok.extern.slf4j.Slf4j;
|
||||||
import ctbrec.Config;
|
import ctbrec.Config;
|
||||||
import ctbrec.Model;
|
import ctbrec.Model;
|
||||||
import ctbrec.StringUtil;
|
import ctbrec.StringUtil;
|
||||||
|
@ -11,9 +13,6 @@ import javafx.concurrent.Task;
|
||||||
import okhttp3.Request;
|
import okhttp3.Request;
|
||||||
import org.json.JSONArray;
|
import org.json.JSONArray;
|
||||||
import org.json.JSONObject;
|
import org.json.JSONObject;
|
||||||
import org.slf4j.Logger;
|
|
||||||
import org.slf4j.LoggerFactory;
|
|
||||||
|
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
@ -21,10 +20,8 @@ import java.util.Locale;
|
||||||
|
|
||||||
import static ctbrec.io.HttpConstants.*;
|
import static ctbrec.io.HttpConstants.*;
|
||||||
|
|
||||||
|
@Slf4j
|
||||||
public class BongaCamsUpdateService extends PaginatedScheduledService {
|
public class BongaCamsUpdateService extends PaginatedScheduledService {
|
||||||
|
|
||||||
private static final Logger LOG = LoggerFactory.getLogger(BongaCamsUpdateService.class);
|
|
||||||
|
|
||||||
private final BongaCams bongaCams;
|
private final BongaCams bongaCams;
|
||||||
private final String url;
|
private final String url;
|
||||||
private final boolean requiresLogin;
|
private final boolean requiresLogin;
|
||||||
|
@ -55,7 +52,7 @@ public class BongaCamsUpdateService extends PaginatedScheduledService {
|
||||||
|
|
||||||
private List<Model> loadModelList() throws IOException {
|
private List<Model> loadModelList() throws IOException {
|
||||||
String pageUrl = url + ((page - 1) * 72);
|
String pageUrl = url + ((page - 1) * 72);
|
||||||
LOG.debug("Fetching page {}", pageUrl);
|
log.debug("Fetching page {}", pageUrl);
|
||||||
var request = new Request.Builder()
|
var request = new Request.Builder()
|
||||||
.url(pageUrl)
|
.url(pageUrl)
|
||||||
.header(USER_AGENT, Config.getInstance().getSettings().httpUserAgent)
|
.header(USER_AGENT, Config.getInstance().getSettings().httpUserAgent)
|
||||||
|
|
|
@ -1,14 +1,13 @@
|
||||||
package ctbrec.ui.sites.cam4;
|
package ctbrec.ui.sites.cam4;
|
||||||
|
|
||||||
|
|
||||||
|
import lombok.extern.slf4j.Slf4j;
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.util.Collections;
|
import java.util.Collections;
|
||||||
import java.util.Optional;
|
import java.util.Optional;
|
||||||
import java.util.function.Consumer;
|
import java.util.function.Consumer;
|
||||||
|
|
||||||
import org.json.JSONObject;
|
import org.json.JSONObject;
|
||||||
import org.slf4j.Logger;
|
|
||||||
import org.slf4j.LoggerFactory;
|
|
||||||
|
|
||||||
import ctbrec.Config;
|
import ctbrec.Config;
|
||||||
import ctbrec.sites.cam4.Cam4;
|
import ctbrec.sites.cam4.Cam4;
|
||||||
import ctbrec.ui.ExternalBrowser;
|
import ctbrec.ui.ExternalBrowser;
|
||||||
|
@ -17,9 +16,8 @@ import okhttp3.Cookie.Builder;
|
||||||
import okhttp3.CookieJar;
|
import okhttp3.CookieJar;
|
||||||
import okhttp3.HttpUrl;
|
import okhttp3.HttpUrl;
|
||||||
|
|
||||||
|
@Slf4j
|
||||||
public class Cam4ElectronLoginDialog {
|
public class Cam4ElectronLoginDialog {
|
||||||
|
|
||||||
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;
|
public static final String URL = Cam4.BASE_URI;
|
||||||
private CookieJar cookieJar;
|
private CookieJar cookieJar;
|
||||||
|
@ -50,7 +48,7 @@ public class Cam4ElectronLoginDialog {
|
||||||
|
|
||||||
private Consumer<String> msgHandler = line -> {
|
private Consumer<String> msgHandler = line -> {
|
||||||
if(!line.startsWith("{")) {
|
if(!line.startsWith("{")) {
|
||||||
LOG.error("Didn't received a JSON object {}", line);
|
log.error("Didn't received a JSON object {}", line);
|
||||||
} else {
|
} else {
|
||||||
var json = new JSONObject(line);
|
var json = new JSONObject(line);
|
||||||
safeCookies(json);
|
safeCookies(json);
|
||||||
|
@ -81,12 +79,12 @@ public class Cam4ElectronLoginDialog {
|
||||||
private void checkIfLoggedIn() {
|
private void checkIfLoggedIn() {
|
||||||
try {
|
try {
|
||||||
browser.executeJavaScript("document.querySelector('a[id*=\"mainHeader_userMenuContent-logout\"]').text").thenAccept(r -> {
|
browser.executeJavaScript("document.querySelector('a[id*=\"mainHeader_userMenuContent-logout\"]').text").thenAccept(r -> {
|
||||||
LOG.debug("Result from browser is {}", r);
|
log.debug("Result from browser is {}", r);
|
||||||
// found the logout button, we can close the browser, the login was successful
|
// found the logout button, we can close the browser, the login was successful
|
||||||
closeBrowser();
|
closeBrowser();
|
||||||
}).exceptionally(ex -> null);
|
}).exceptionally(ex -> null);
|
||||||
} catch (IOException e) {
|
} catch (IOException e) {
|
||||||
LOG.error("Check, if logged in failed", e);
|
log.error("Check, if logged in failed", e);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -99,7 +97,7 @@ public class Cam4ElectronLoginDialog {
|
||||||
+ "if (cookieButton) { cookieButton.click(); }");
|
+ "if (cookieButton) { cookieButton.click(); }");
|
||||||
dialogsClicked = true;
|
dialogsClicked = true;
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
LOG.warn("Couldn't click on cookie and age acknowlegde buttons for Cam4", e);
|
log.warn("Couldn't click on cookie and age acknowlegde buttons for Cam4", e);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -132,7 +130,7 @@ public class Cam4ElectronLoginDialog {
|
||||||
+ "if (loginButton) { loginButton.click(); }");
|
+ "if (loginButton) { loginButton.click(); }");
|
||||||
loginDialogOpened = true;
|
loginDialogOpened = true;
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
LOG.warn("Couldn't open login dialog for Cam4", e);
|
log.warn("Couldn't open login dialog for Cam4", e);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -150,7 +148,7 @@ public class Cam4ElectronLoginDialog {
|
||||||
browser.executeJavaScript("document.querySelector('input[id*=\"loginFrom_passwordInput\"]').value = '" + password + "');");
|
browser.executeJavaScript("document.querySelector('input[id*=\"loginFrom_passwordInput\"]').value = '" + password + "');");
|
||||||
}
|
}
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
LOG.warn("Couldn't auto fill username and password for Cam4", e);
|
log.warn("Couldn't auto fill username and password for Cam4", e);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -159,7 +157,7 @@ public class Cam4ElectronLoginDialog {
|
||||||
try {
|
try {
|
||||||
browser.executeJavaScript("document.querySelector('button[id*=\"loginFrom_submitButton\"]').click();");
|
browser.executeJavaScript("document.querySelector('button[id*=\"loginFrom_submitButton\"]').click();");
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
LOG.warn("Couldn't click on login button for Cam4", e);
|
log.warn("Couldn't click on login button for Cam4", e);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -187,7 +185,7 @@ public class Cam4ElectronLoginDialog {
|
||||||
Optional.ofNullable(loginChecker).ifPresent(Thread::interrupt);
|
Optional.ofNullable(loginChecker).ifPresent(Thread::interrupt);
|
||||||
browser.close();
|
browser.close();
|
||||||
} catch(IOException e) {
|
} catch(IOException e) {
|
||||||
LOG.error("Couldn't send close request to browser", e);
|
log.error("Couldn't send close request to browser", e);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,5 +1,7 @@
|
||||||
package ctbrec.ui.sites.cam4;
|
package ctbrec.ui.sites.cam4;
|
||||||
|
|
||||||
|
|
||||||
|
import lombok.extern.slf4j.Slf4j;
|
||||||
import ctbrec.Model;
|
import ctbrec.Model;
|
||||||
import ctbrec.io.HttpException;
|
import ctbrec.io.HttpException;
|
||||||
import ctbrec.sites.cam4.Cam4;
|
import ctbrec.sites.cam4.Cam4;
|
||||||
|
@ -9,9 +11,6 @@ import ctbrec.ui.tabs.PaginatedScheduledService;
|
||||||
import javafx.concurrent.Task;
|
import javafx.concurrent.Task;
|
||||||
import okhttp3.Request;
|
import okhttp3.Request;
|
||||||
import org.json.JSONObject;
|
import org.json.JSONObject;
|
||||||
import org.slf4j.Logger;
|
|
||||||
import org.slf4j.LoggerFactory;
|
|
||||||
|
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.Collections;
|
import java.util.Collections;
|
||||||
|
@ -19,10 +18,8 @@ import java.util.List;
|
||||||
import java.util.concurrent.ExecutorService;
|
import java.util.concurrent.ExecutorService;
|
||||||
import java.util.concurrent.Executors;
|
import java.util.concurrent.Executors;
|
||||||
|
|
||||||
|
@Slf4j
|
||||||
public class Cam4FollowedUpdateService extends PaginatedScheduledService {
|
public class Cam4FollowedUpdateService extends PaginatedScheduledService {
|
||||||
|
|
||||||
private static final Logger LOG = LoggerFactory.getLogger(Cam4FollowedUpdateService.class);
|
|
||||||
|
|
||||||
private final Cam4 site;
|
private final Cam4 site;
|
||||||
private boolean showOnline = true;
|
private boolean showOnline = true;
|
||||||
|
|
||||||
|
@ -55,7 +52,7 @@ public class Cam4FollowedUpdateService extends PaginatedScheduledService {
|
||||||
// login first
|
// login first
|
||||||
SiteUiFactory.getUi(site).login();
|
SiteUiFactory.getUi(site).login();
|
||||||
String url = site.getBaseUrl() + "/directoryCams?directoryJson=true&online=" + showOnline + "&url=true&friends=true&favorites=true&resultsPerPage=90";
|
String url = site.getBaseUrl() + "/directoryCams?directoryJson=true&online=" + showOnline + "&url=true&friends=true&favorites=true&resultsPerPage=90";
|
||||||
LOG.debug("Fetching page {}", url);
|
log.debug("Fetching page {}", url);
|
||||||
Request req = new Request.Builder().url(url).build();
|
Request req = new Request.Builder().url(url).build();
|
||||||
try (var response = site.getHttpClient().execute(req)) {
|
try (var response = site.getHttpClient().execute(req)) {
|
||||||
if (response.isSuccessful()) {
|
if (response.isSuccessful()) {
|
||||||
|
|
|
@ -1,10 +1,8 @@
|
||||||
package ctbrec.ui.sites.cam4;
|
package ctbrec.ui.sites.cam4;
|
||||||
|
|
||||||
|
|
||||||
|
import lombok.extern.slf4j.Slf4j;
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
|
|
||||||
import org.slf4j.Logger;
|
|
||||||
import org.slf4j.LoggerFactory;
|
|
||||||
|
|
||||||
import ctbrec.sites.cam4.Cam4;
|
import ctbrec.sites.cam4.Cam4;
|
||||||
import ctbrec.sites.cam4.Cam4HttpClient;
|
import ctbrec.sites.cam4.Cam4HttpClient;
|
||||||
import ctbrec.ui.controls.Dialogs;
|
import ctbrec.ui.controls.Dialogs;
|
||||||
|
@ -12,9 +10,8 @@ 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;
|
||||||
|
|
||||||
|
@Slf4j
|
||||||
public class Cam4SiteUi extends AbstractSiteUi {
|
public class Cam4SiteUi extends AbstractSiteUi {
|
||||||
private static final Logger LOG = LoggerFactory.getLogger(Cam4SiteUi.class);
|
|
||||||
|
|
||||||
private final Cam4 cam4;
|
private final Cam4 cam4;
|
||||||
private Cam4TabProvider tabProvider;
|
private Cam4TabProvider tabProvider;
|
||||||
private Cam4ConfigUI configUi;
|
private Cam4ConfigUI configUi;
|
||||||
|
@ -49,7 +46,7 @@ public class Cam4SiteUi extends AbstractSiteUi {
|
||||||
try {
|
try {
|
||||||
new Cam4ElectronLoginDialog(cam4.getHttpClient().getCookieJar());
|
new Cam4ElectronLoginDialog(cam4.getHttpClient().getCookieJar());
|
||||||
} catch (Exception e1) {
|
} catch (Exception e1) {
|
||||||
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);
|
||||||
}
|
}
|
||||||
Cam4HttpClient httpClient = (Cam4HttpClient) cam4.getHttpClient();
|
Cam4HttpClient httpClient = (Cam4HttpClient) cam4.getHttpClient();
|
||||||
|
|
|
@ -1,5 +1,7 @@
|
||||||
package ctbrec.ui.sites.cam4;
|
package ctbrec.ui.sites.cam4;
|
||||||
|
|
||||||
|
|
||||||
|
import lombok.extern.slf4j.Slf4j;
|
||||||
import ctbrec.Config;
|
import ctbrec.Config;
|
||||||
import ctbrec.Model;
|
import ctbrec.Model;
|
||||||
import ctbrec.StringUtil;
|
import ctbrec.StringUtil;
|
||||||
|
@ -12,9 +14,6 @@ import javafx.concurrent.Task;
|
||||||
import okhttp3.Request;
|
import okhttp3.Request;
|
||||||
import org.json.JSONArray;
|
import org.json.JSONArray;
|
||||||
import org.json.JSONObject;
|
import org.json.JSONObject;
|
||||||
import org.slf4j.Logger;
|
|
||||||
import org.slf4j.LoggerFactory;
|
|
||||||
|
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.Collections;
|
import java.util.Collections;
|
||||||
|
@ -27,9 +26,8 @@ import static ctbrec.Model.State.ONLINE;
|
||||||
import static ctbrec.io.HttpConstants.ACCEPT_LANGUAGE;
|
import static ctbrec.io.HttpConstants.ACCEPT_LANGUAGE;
|
||||||
import static ctbrec.io.HttpConstants.USER_AGENT;
|
import static ctbrec.io.HttpConstants.USER_AGENT;
|
||||||
|
|
||||||
|
@Slf4j
|
||||||
public class Cam4UpdateService extends PaginatedScheduledService {
|
public class Cam4UpdateService extends PaginatedScheduledService {
|
||||||
|
|
||||||
private static final Logger LOG = LoggerFactory.getLogger(Cam4UpdateService.class);
|
|
||||||
private String url;
|
private String url;
|
||||||
private final Cam4 site;
|
private final Cam4 site;
|
||||||
private final boolean loginRequired;
|
private final boolean loginRequired;
|
||||||
|
@ -57,7 +55,7 @@ public class Cam4UpdateService extends PaginatedScheduledService {
|
||||||
return Collections.emptyList();
|
return Collections.emptyList();
|
||||||
} else {
|
} else {
|
||||||
String pageUrl = Cam4UpdateService.this.url + "&page=" + page;
|
String pageUrl = Cam4UpdateService.this.url + "&page=" + page;
|
||||||
LOG.debug("Fetching page {}", pageUrl);
|
log.debug("Fetching page {}", pageUrl);
|
||||||
if (loginRequired) {
|
if (loginRequired) {
|
||||||
SiteUiFactory.getUi(site).login();
|
SiteUiFactory.getUi(site).login();
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,5 +1,7 @@
|
||||||
package ctbrec.ui.sites.chaturbate;
|
package ctbrec.ui.sites.chaturbate;
|
||||||
|
|
||||||
|
|
||||||
|
import lombok.extern.slf4j.Slf4j;
|
||||||
import ctbrec.Config;
|
import ctbrec.Config;
|
||||||
import ctbrec.sites.chaturbate.Chaturbate;
|
import ctbrec.sites.chaturbate.Chaturbate;
|
||||||
import ctbrec.ui.ExternalBrowser;
|
import ctbrec.ui.ExternalBrowser;
|
||||||
|
@ -8,9 +10,6 @@ import okhttp3.Cookie.Builder;
|
||||||
import okhttp3.CookieJar;
|
import okhttp3.CookieJar;
|
||||||
import okhttp3.HttpUrl;
|
import okhttp3.HttpUrl;
|
||||||
import org.json.JSONObject;
|
import org.json.JSONObject;
|
||||||
import org.slf4j.Logger;
|
|
||||||
import org.slf4j.LoggerFactory;
|
|
||||||
|
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.net.MalformedURLException;
|
import java.net.MalformedURLException;
|
||||||
import java.net.URL;
|
import java.net.URL;
|
||||||
|
@ -18,9 +17,8 @@ import java.util.Collections;
|
||||||
import java.util.Objects;
|
import java.util.Objects;
|
||||||
import java.util.function.Consumer;
|
import java.util.function.Consumer;
|
||||||
|
|
||||||
|
@Slf4j
|
||||||
public class ChaturbateElectronLoginDialog {
|
public class ChaturbateElectronLoginDialog {
|
||||||
|
|
||||||
private static final Logger LOG = LoggerFactory.getLogger(ChaturbateElectronLoginDialog.class);
|
|
||||||
public static final String DOMAIN = "chaturbate.com";
|
public static final String DOMAIN = "chaturbate.com";
|
||||||
private Chaturbate site;
|
private Chaturbate site;
|
||||||
private CookieJar cookieJar;
|
private CookieJar cookieJar;
|
||||||
|
@ -49,7 +47,7 @@ public class ChaturbateElectronLoginDialog {
|
||||||
|
|
||||||
private final Consumer<String> msgHandler = line -> {
|
private final Consumer<String> msgHandler = line -> {
|
||||||
if (!line.startsWith("{")) {
|
if (!line.startsWith("{")) {
|
||||||
LOG.error("Didn't received a JSON object {}", line);
|
log.error("Didn't received a JSON object {}", line);
|
||||||
} else {
|
} else {
|
||||||
var json = new JSONObject(line);
|
var json = new JSONObject(line);
|
||||||
if (json.has("url")) {
|
if (json.has("url")) {
|
||||||
|
@ -76,9 +74,9 @@ public class ChaturbateElectronLoginDialog {
|
||||||
browser.executeJavaScript("document.querySelector('form[action*=login]').submit()");
|
browser.executeJavaScript("document.querySelector('form[action*=login]').submit()");
|
||||||
} catch (InterruptedException e) {
|
} catch (InterruptedException e) {
|
||||||
Thread.currentThread().interrupt();
|
Thread.currentThread().interrupt();
|
||||||
LOG.warn("Couldn't auto fill username and password for Chaturbate", e);
|
log.warn("Couldn't auto fill username and password for Chaturbate", e);
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
LOG.warn("Couldn't auto fill username and password for Chaturbate", e);
|
log.warn("Couldn't auto fill username and password for Chaturbate", e);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -113,9 +111,9 @@ public class ChaturbateElectronLoginDialog {
|
||||||
browser.close();
|
browser.close();
|
||||||
}
|
}
|
||||||
} catch (MalformedURLException e) {
|
} catch (MalformedURLException e) {
|
||||||
LOG.error("Couldn't parse new url {}", url, e);
|
log.error("Couldn't parse new url {}", url, e);
|
||||||
} catch (IOException e) {
|
} catch (IOException e) {
|
||||||
LOG.error("Couldn't send shutdown request to external browser", e);
|
log.error("Couldn't send shutdown request to external browser", e);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,20 +1,17 @@
|
||||||
package ctbrec.ui.sites.chaturbate;
|
package ctbrec.ui.sites.chaturbate;
|
||||||
|
|
||||||
|
|
||||||
|
import lombok.extern.slf4j.Slf4j;
|
||||||
import ctbrec.sites.chaturbate.Chaturbate;
|
import ctbrec.sites.chaturbate.Chaturbate;
|
||||||
import ctbrec.sites.chaturbate.ChaturbateHttpClient;
|
import ctbrec.sites.chaturbate.ChaturbateHttpClient;
|
||||||
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.io.IOException;
|
||||||
|
|
||||||
|
@Slf4j
|
||||||
public class ChaturbateSiteUi extends AbstractSiteUi {
|
public class ChaturbateSiteUi extends AbstractSiteUi {
|
||||||
|
|
||||||
private static final Logger LOG = LoggerFactory.getLogger(ChaturbateSiteUi.class);
|
|
||||||
|
|
||||||
private final Chaturbate chaturbate;
|
private final Chaturbate chaturbate;
|
||||||
private ChaturbateTabProvider tabProvider;
|
private ChaturbateTabProvider tabProvider;
|
||||||
private ChaturbateConfigUi configUi;
|
private ChaturbateConfigUi configUi;
|
||||||
|
@ -45,7 +42,7 @@ public class ChaturbateSiteUi extends AbstractSiteUi {
|
||||||
try {
|
try {
|
||||||
automaticLogin = chaturbate.login();
|
automaticLogin = chaturbate.login();
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
LOG.debug("Automatic login failed", e);
|
log.debug("Automatic login failed", e);
|
||||||
}
|
}
|
||||||
if (automaticLogin) {
|
if (automaticLogin) {
|
||||||
return true;
|
return true;
|
||||||
|
@ -54,7 +51,7 @@ public class ChaturbateSiteUi extends AbstractSiteUi {
|
||||||
try {
|
try {
|
||||||
new ChaturbateElectronLoginDialog(chaturbate, chaturbate.getHttpClient().getCookieJar());
|
new ChaturbateElectronLoginDialog(chaturbate, chaturbate.getHttpClient().getCookieJar());
|
||||||
} catch (Exception e1) {
|
} catch (Exception e1) {
|
||||||
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 " + chaturbate.getName(), e1);
|
Dialogs.showError("Login error", "Couldn't login to " + chaturbate.getName(), e1);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1,5 +1,7 @@
|
||||||
package ctbrec.ui.sites.dreamcam;
|
package ctbrec.ui.sites.dreamcam;
|
||||||
|
|
||||||
|
|
||||||
|
import lombok.extern.slf4j.Slf4j;
|
||||||
import static ctbrec.io.HttpConstants.*;
|
import static ctbrec.io.HttpConstants.*;
|
||||||
|
|
||||||
import ctbrec.Config;
|
import ctbrec.Config;
|
||||||
|
@ -17,11 +19,8 @@ import okhttp3.Request;
|
||||||
import okhttp3.Response;
|
import okhttp3.Response;
|
||||||
import org.json.JSONArray;
|
import org.json.JSONArray;
|
||||||
import org.json.JSONObject;
|
import org.json.JSONObject;
|
||||||
import org.slf4j.Logger;
|
@Slf4j
|
||||||
import org.slf4j.LoggerFactory;
|
|
||||||
|
|
||||||
public class DreamcamUpdateService extends PaginatedScheduledService {
|
public class DreamcamUpdateService extends PaginatedScheduledService {
|
||||||
private static final Logger LOG = LoggerFactory.getLogger(DreamcamUpdateService.class);
|
|
||||||
// private static final String API_URL = "https://api.dreamcam.co.kr/v1/live";
|
// private static final String API_URL = "https://api.dreamcam.co.kr/v1/live";
|
||||||
private static final int modelsPerPage = 64;
|
private static final int modelsPerPage = 64;
|
||||||
private Dreamcam site;
|
private Dreamcam site;
|
||||||
|
@ -46,7 +45,7 @@ public class DreamcamUpdateService extends PaginatedScheduledService {
|
||||||
int offset = (getPage() - 1) * modelsPerPage;
|
int offset = (getPage() - 1) * modelsPerPage;
|
||||||
int limit = modelsPerPage;
|
int limit = modelsPerPage;
|
||||||
String paginatedUrl = url + "&offset=" + offset + "&limit=" + limit;
|
String paginatedUrl = url + "&offset=" + offset + "&limit=" + limit;
|
||||||
LOG.debug("Fetching page {}", paginatedUrl);
|
log.debug("Fetching page {}", paginatedUrl);
|
||||||
Request req = new Request.Builder()
|
Request req = new Request.Builder()
|
||||||
.url(paginatedUrl)
|
.url(paginatedUrl)
|
||||||
.header(USER_AGENT, Config.getInstance().getSettings().httpUserAgent)
|
.header(USER_AGENT, Config.getInstance().getSettings().httpUserAgent)
|
||||||
|
|
|
@ -1,10 +1,8 @@
|
||||||
package ctbrec.ui.sites.fc2live;
|
package ctbrec.ui.sites.fc2live;
|
||||||
|
|
||||||
|
|
||||||
|
import lombok.extern.slf4j.Slf4j;
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
|
|
||||||
import org.slf4j.Logger;
|
|
||||||
import org.slf4j.LoggerFactory;
|
|
||||||
|
|
||||||
import ctbrec.GlobalThreadPool;
|
import ctbrec.GlobalThreadPool;
|
||||||
import ctbrec.Model;
|
import ctbrec.Model;
|
||||||
import ctbrec.sites.fc2live.Fc2Live;
|
import ctbrec.sites.fc2live.Fc2Live;
|
||||||
|
@ -16,8 +14,8 @@ 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;
|
||||||
|
|
||||||
|
@Slf4j
|
||||||
public class Fc2LiveSiteUi extends AbstractSiteUi {
|
public class Fc2LiveSiteUi extends AbstractSiteUi {
|
||||||
private static final Logger LOG = LoggerFactory.getLogger(Fc2LiveSiteUi.class);
|
|
||||||
private final Fc2Live fc2live;
|
private final Fc2Live fc2live;
|
||||||
private Fc2TabProvider tabProvider;
|
private Fc2TabProvider tabProvider;
|
||||||
private Fc2LiveConfigUI configUi;
|
private Fc2LiveConfigUI configUi;
|
||||||
|
@ -58,7 +56,7 @@ public class Fc2LiveSiteUi extends AbstractSiteUi {
|
||||||
}
|
}
|
||||||
try {
|
try {
|
||||||
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) {
|
} catch (InterruptedException e) {
|
||||||
Thread.currentThread().interrupt();
|
Thread.currentThread().interrupt();
|
||||||
|
@ -73,7 +71,7 @@ public class Fc2LiveSiteUi extends AbstractSiteUi {
|
||||||
}
|
}
|
||||||
|
|
||||||
private void handleException(Exception e) {
|
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);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,5 +1,7 @@
|
||||||
package ctbrec.ui.sites.fc2live;
|
package ctbrec.ui.sites.fc2live;
|
||||||
|
|
||||||
|
|
||||||
|
import lombok.extern.slf4j.Slf4j;
|
||||||
import static ctbrec.io.HttpConstants.*;
|
import static ctbrec.io.HttpConstants.*;
|
||||||
|
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
|
@ -9,9 +11,6 @@ import java.util.Locale;
|
||||||
import java.util.stream.Collectors;
|
import java.util.stream.Collectors;
|
||||||
|
|
||||||
import org.json.JSONObject;
|
import org.json.JSONObject;
|
||||||
import org.slf4j.Logger;
|
|
||||||
import org.slf4j.LoggerFactory;
|
|
||||||
|
|
||||||
import ctbrec.Config;
|
import ctbrec.Config;
|
||||||
import ctbrec.Model;
|
import ctbrec.Model;
|
||||||
import ctbrec.io.HttpException;
|
import ctbrec.io.HttpException;
|
||||||
|
@ -22,9 +21,8 @@ import javafx.concurrent.Task;
|
||||||
import okhttp3.Request;
|
import okhttp3.Request;
|
||||||
import okhttp3.RequestBody;
|
import okhttp3.RequestBody;
|
||||||
|
|
||||||
|
@Slf4j
|
||||||
public class Fc2UpdateService extends PaginatedScheduledService {
|
public class Fc2UpdateService extends PaginatedScheduledService {
|
||||||
private static final Logger LOG = LoggerFactory.getLogger(Fc2UpdateService.class);
|
|
||||||
|
|
||||||
private String url;
|
private String url;
|
||||||
private Fc2Live fc2live;
|
private Fc2Live fc2live;
|
||||||
private int modelsPerPage = 30;
|
private int modelsPerPage = 30;
|
||||||
|
@ -49,7 +47,7 @@ public class Fc2UpdateService extends PaginatedScheduledService {
|
||||||
.header(USER_AGENT, Config.getInstance().getSettings().httpUserAgent)
|
.header(USER_AGENT, Config.getInstance().getSettings().httpUserAgent)
|
||||||
.header(X_REQUESTED_WITH, XML_HTTP_REQUEST)
|
.header(X_REQUESTED_WITH, XML_HTTP_REQUEST)
|
||||||
.build();
|
.build();
|
||||||
LOG.debug("Fetching page {}", url);
|
log.debug("Fetching page {}", url);
|
||||||
try (var resp = fc2live.getHttpClient().execute(req)) {
|
try (var resp = fc2live.getHttpClient().execute(req)) {
|
||||||
if (resp.isSuccessful()) {
|
if (resp.isSuccessful()) {
|
||||||
List<Fc2Model> models = new ArrayList<>();
|
List<Fc2Model> models = new ArrayList<>();
|
||||||
|
|
|
@ -1,5 +1,7 @@
|
||||||
package ctbrec.ui.sites.flirt4free;
|
package ctbrec.ui.sites.flirt4free;
|
||||||
|
|
||||||
|
|
||||||
|
import lombok.extern.slf4j.Slf4j;
|
||||||
import ctbrec.Config;
|
import ctbrec.Config;
|
||||||
import ctbrec.Model;
|
import ctbrec.Model;
|
||||||
import ctbrec.io.HttpException;
|
import ctbrec.io.HttpException;
|
||||||
|
@ -10,9 +12,6 @@ import javafx.concurrent.Task;
|
||||||
import okhttp3.Request;
|
import okhttp3.Request;
|
||||||
import org.json.JSONObject;
|
import org.json.JSONObject;
|
||||||
import org.jsoup.nodes.Entities;
|
import org.jsoup.nodes.Entities;
|
||||||
import org.slf4j.Logger;
|
|
||||||
import org.slf4j.LoggerFactory;
|
|
||||||
|
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
@ -22,9 +21,8 @@ import java.util.regex.Pattern;
|
||||||
import static ctbrec.io.HttpClient.gunzipBody;
|
import static ctbrec.io.HttpClient.gunzipBody;
|
||||||
import static ctbrec.io.HttpConstants.*;
|
import static ctbrec.io.HttpConstants.*;
|
||||||
|
|
||||||
|
@Slf4j
|
||||||
public class Flirt4FreeUpdateService extends PaginatedScheduledService {
|
public class Flirt4FreeUpdateService extends PaginatedScheduledService {
|
||||||
|
|
||||||
private static final Logger LOG = LoggerFactory.getLogger(Flirt4FreeUpdateService.class);
|
|
||||||
private static final int MODELS_PER_PAGE = 50;
|
private static final int MODELS_PER_PAGE = 50;
|
||||||
private final String url;
|
private final String url;
|
||||||
private final Flirt4Free flirt4Free;
|
private final Flirt4Free flirt4Free;
|
||||||
|
@ -41,7 +39,7 @@ public class Flirt4FreeUpdateService extends PaginatedScheduledService {
|
||||||
return new Task<>() {
|
return new Task<>() {
|
||||||
@Override
|
@Override
|
||||||
public List<Model> call() throws IOException {
|
public List<Model> call() throws IOException {
|
||||||
LOG.debug("Fetching page {}", url);
|
log.debug("Fetching page {}", url);
|
||||||
var request = new Request.Builder()
|
var request = new Request.Builder()
|
||||||
.url(url)
|
.url(url)
|
||||||
.header(USER_AGENT, Config.getInstance().getSettings().httpUserAgent)
|
.header(USER_AGENT, Config.getInstance().getSettings().httpUserAgent)
|
||||||
|
@ -65,14 +63,14 @@ public class Flirt4FreeUpdateService extends PaginatedScheduledService {
|
||||||
if (m.find()) {
|
if (m.find()) {
|
||||||
var data = new JSONObject(m.group(1));
|
var data = new JSONObject(m.group(1));
|
||||||
var modelData = data.getJSONArray("models");
|
var modelData = data.getJSONArray("models");
|
||||||
LOG.debug("Found {} models", modelData.length());
|
log.debug("Found {} models", modelData.length());
|
||||||
for (var i = 0; i < modelData.length(); i++) {
|
for (var i = 0; i < modelData.length(); i++) {
|
||||||
var modelJson = modelData.getJSONObject(i);
|
var modelJson = modelData.getJSONObject(i);
|
||||||
try {
|
try {
|
||||||
Flirt4FreeModel model = parseModel(modelJson);
|
Flirt4FreeModel model = parseModel(modelJson);
|
||||||
models.add(model);
|
models.add(model);
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
LOG.warn("Couldn't parse model {}", modelJson);
|
log.warn("Couldn't parse model {}", modelJson);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return models.stream()
|
return models.stream()
|
||||||
|
|
|
@ -1,5 +1,7 @@
|
||||||
package ctbrec.ui.sites.myfreecams;
|
package ctbrec.ui.sites.myfreecams;
|
||||||
|
|
||||||
|
|
||||||
|
import lombok.extern.slf4j.Slf4j;
|
||||||
import ctbrec.Config;
|
import ctbrec.Config;
|
||||||
import ctbrec.Model;
|
import ctbrec.Model;
|
||||||
import ctbrec.StringUtil;
|
import ctbrec.StringUtil;
|
||||||
|
@ -10,9 +12,6 @@ import javafx.concurrent.Task;
|
||||||
import okhttp3.Request;
|
import okhttp3.Request;
|
||||||
import okhttp3.Response;
|
import okhttp3.Response;
|
||||||
import org.json.JSONObject;
|
import org.json.JSONObject;
|
||||||
import org.slf4j.Logger;
|
|
||||||
import org.slf4j.LoggerFactory;
|
|
||||||
|
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.Collections;
|
import java.util.Collections;
|
||||||
|
@ -21,9 +20,8 @@ import java.util.List;
|
||||||
import static ctbrec.io.HttpConstants.REFERER;
|
import static ctbrec.io.HttpConstants.REFERER;
|
||||||
import static ctbrec.io.HttpConstants.USER_AGENT;
|
import static ctbrec.io.HttpConstants.USER_AGENT;
|
||||||
|
|
||||||
|
@Slf4j
|
||||||
public class FriendsUpdateService extends PaginatedScheduledService {
|
public class FriendsUpdateService extends PaginatedScheduledService {
|
||||||
|
|
||||||
private static final Logger LOG = LoggerFactory.getLogger(FriendsUpdateService.class);
|
|
||||||
private final MyFreeCams myFreeCams;
|
private final MyFreeCams myFreeCams;
|
||||||
private Mode mode = Mode.ONLINE;
|
private Mode mode = Mode.ONLINE;
|
||||||
|
|
||||||
|
@ -55,7 +53,7 @@ public class FriendsUpdateService extends PaginatedScheduledService {
|
||||||
var body = resp.body().string().substring(4);
|
var body = resp.body().string().substring(4);
|
||||||
parseModels(body, models);
|
parseModels(body, models);
|
||||||
} else {
|
} else {
|
||||||
LOG.error("Couldn't load friends list {} {}", resp.code(), resp.message());
|
log.error("Couldn't load friends list {} {}", resp.code(), resp.message());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
boolean filterOnline = mode == Mode.ONLINE;
|
boolean filterOnline = mode == Mode.ONLINE;
|
||||||
|
@ -102,7 +100,7 @@ public class FriendsUpdateService extends PaginatedScheduledService {
|
||||||
models.add(model);
|
models.add(model);
|
||||||
}
|
}
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
LOG.info("Exception getting friends list. Response was: {}", body, e);
|
log.info("Exception getting friends list. Response was: {}", body, e);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1,13 +1,12 @@
|
||||||
package ctbrec.ui.sites.showup;
|
package ctbrec.ui.sites.showup;
|
||||||
|
|
||||||
|
|
||||||
|
import lombok.extern.slf4j.Slf4j;
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.util.Collections;
|
import java.util.Collections;
|
||||||
import java.util.function.Consumer;
|
import java.util.function.Consumer;
|
||||||
|
|
||||||
import org.json.JSONObject;
|
import org.json.JSONObject;
|
||||||
import org.slf4j.Logger;
|
|
||||||
import org.slf4j.LoggerFactory;
|
|
||||||
|
|
||||||
import ctbrec.Config;
|
import ctbrec.Config;
|
||||||
import ctbrec.sites.showup.Showup;
|
import ctbrec.sites.showup.Showup;
|
||||||
import ctbrec.ui.ExternalBrowser;
|
import ctbrec.ui.ExternalBrowser;
|
||||||
|
@ -16,9 +15,8 @@ import okhttp3.Cookie.Builder;
|
||||||
import okhttp3.CookieJar;
|
import okhttp3.CookieJar;
|
||||||
import okhttp3.HttpUrl;
|
import okhttp3.HttpUrl;
|
||||||
|
|
||||||
|
@Slf4j
|
||||||
public class ShowupElectronLoginDialog {
|
public class ShowupElectronLoginDialog {
|
||||||
|
|
||||||
private static final Logger LOG = LoggerFactory.getLogger(ShowupElectronLoginDialog.class);
|
|
||||||
public static final String DOMAIN = "showup.tv";
|
public static final String DOMAIN = "showup.tv";
|
||||||
public static final String URL = Showup.BASE_URL;
|
public static final String URL = Showup.BASE_URL;
|
||||||
private CookieJar cookieJar;
|
private CookieJar cookieJar;
|
||||||
|
@ -52,7 +50,7 @@ public class ShowupElectronLoginDialog {
|
||||||
var json = new JSONObject(line);
|
var json = new JSONObject(line);
|
||||||
if(json.has("url")) {
|
if(json.has("url")) {
|
||||||
var url = json.getString("url");
|
var url = json.getString("url");
|
||||||
LOG.debug(url);
|
log.debug(url);
|
||||||
if(url.contains("/site/accept_rules")) {
|
if(url.contains("/site/accept_rules")) {
|
||||||
try {
|
try {
|
||||||
Thread.sleep(500);
|
Thread.sleep(500);
|
||||||
|
@ -62,9 +60,9 @@ public class ShowupElectronLoginDialog {
|
||||||
}
|
}
|
||||||
} catch (InterruptedException e) {
|
} catch (InterruptedException e) {
|
||||||
Thread.currentThread().interrupt();
|
Thread.currentThread().interrupt();
|
||||||
LOG.warn("Couldn't auto fill username and password for Showup", e);
|
log.warn("Couldn't auto fill username and password for Showup", e);
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
LOG.warn("Couldn't auto fill username and password for Showup", e);
|
log.warn("Couldn't auto fill username and password for Showup", e);
|
||||||
}
|
}
|
||||||
} else if (url.equals(URL + '/') && firstCall) {
|
} else if (url.equals(URL + '/') && firstCall) {
|
||||||
firstCall = false;
|
firstCall = false;
|
||||||
|
@ -84,9 +82,9 @@ public class ShowupElectronLoginDialog {
|
||||||
return;
|
return;
|
||||||
} catch (InterruptedException e) {
|
} catch (InterruptedException e) {
|
||||||
Thread.currentThread().interrupt();
|
Thread.currentThread().interrupt();
|
||||||
LOG.warn("Couldn't auto fill username and password for Showup", e);
|
log.warn("Couldn't auto fill username and password for Showup", e);
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
LOG.warn("Couldn't auto fill username and password for Showup", e);
|
log.warn("Couldn't auto fill username and password for Showup", e);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -111,7 +109,7 @@ public class ShowupElectronLoginDialog {
|
||||||
b.secure();
|
b.secure();
|
||||||
}
|
}
|
||||||
Cookie c = b.build();
|
Cookie c = b.build();
|
||||||
LOG.debug("Adding cookie {}={}", c.name(), c.value());
|
log.debug("Adding cookie {}={}", c.name(), c.value());
|
||||||
cookieJar.saveFromResponse(HttpUrl.parse(Showup.BASE_URL), Collections.singletonList(c));
|
cookieJar.saveFromResponse(HttpUrl.parse(Showup.BASE_URL), Collections.singletonList(c));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,10 +1,8 @@
|
||||||
package ctbrec.ui.sites.showup;
|
package ctbrec.ui.sites.showup;
|
||||||
|
|
||||||
|
|
||||||
|
import lombok.extern.slf4j.Slf4j;
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
|
|
||||||
import org.slf4j.Logger;
|
|
||||||
import org.slf4j.LoggerFactory;
|
|
||||||
|
|
||||||
import ctbrec.sites.showup.Showup;
|
import ctbrec.sites.showup.Showup;
|
||||||
import ctbrec.sites.showup.ShowupHttpClient;
|
import ctbrec.sites.showup.ShowupHttpClient;
|
||||||
import ctbrec.ui.controls.Dialogs;
|
import ctbrec.ui.controls.Dialogs;
|
||||||
|
@ -12,10 +10,8 @@ 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;
|
||||||
|
|
||||||
|
@Slf4j
|
||||||
public class ShowupSiteUi extends AbstractSiteUi {
|
public class ShowupSiteUi extends AbstractSiteUi {
|
||||||
|
|
||||||
private static final Logger LOG = LoggerFactory.getLogger(ShowupSiteUi.class);
|
|
||||||
|
|
||||||
private final Showup site;
|
private final Showup site;
|
||||||
private ConfigUI configUi;
|
private ConfigUI configUi;
|
||||||
private TabProvider tabProvider;
|
private TabProvider tabProvider;
|
||||||
|
@ -50,16 +46,16 @@ public class ShowupSiteUi extends AbstractSiteUi {
|
||||||
try {
|
try {
|
||||||
new ShowupElectronLoginDialog(site.getHttpClient().getCookieJar());
|
new ShowupElectronLoginDialog(site.getHttpClient().getCookieJar());
|
||||||
} catch (Exception e1) {
|
} catch (Exception e1) {
|
||||||
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 " + site.getName(), e1);
|
Dialogs.showError("Login error", "Couldn't login to " + site.getName(), e1);
|
||||||
}
|
}
|
||||||
|
|
||||||
ShowupHttpClient httpClient = (ShowupHttpClient) site.getHttpClient();
|
ShowupHttpClient httpClient = (ShowupHttpClient) site.getHttpClient();
|
||||||
boolean loggedIn = httpClient.checkLoginSuccess();
|
boolean loggedIn = httpClient.checkLoginSuccess();
|
||||||
if (loggedIn) {
|
if (loggedIn) {
|
||||||
LOG.info("Logged in");
|
log.info("Logged in");
|
||||||
} else {
|
} else {
|
||||||
LOG.info("Login failed");
|
log.info("Login failed");
|
||||||
}
|
}
|
||||||
return loggedIn;
|
return loggedIn;
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,5 +1,7 @@
|
||||||
package ctbrec.ui.sites.streamate;
|
package ctbrec.ui.sites.streamate;
|
||||||
|
|
||||||
|
|
||||||
|
import lombok.extern.slf4j.Slf4j;
|
||||||
import ctbrec.Config;
|
import ctbrec.Config;
|
||||||
import ctbrec.Model;
|
import ctbrec.Model;
|
||||||
import ctbrec.io.HttpException;
|
import ctbrec.io.HttpException;
|
||||||
|
@ -10,9 +12,6 @@ import ctbrec.ui.tabs.PaginatedScheduledService;
|
||||||
import javafx.concurrent.Task;
|
import javafx.concurrent.Task;
|
||||||
import okhttp3.Request;
|
import okhttp3.Request;
|
||||||
import org.json.JSONObject;
|
import org.json.JSONObject;
|
||||||
import org.slf4j.Logger;
|
|
||||||
import org.slf4j.LoggerFactory;
|
|
||||||
|
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.util.*;
|
import java.util.*;
|
||||||
|
|
||||||
|
@ -22,10 +21,8 @@ import static ctbrec.Model.State.ONLINE;
|
||||||
import static ctbrec.io.HttpConstants.*;
|
import static ctbrec.io.HttpConstants.*;
|
||||||
import static ctbrec.sites.streamate.Streamate.NAIAD_URL;
|
import static ctbrec.sites.streamate.Streamate.NAIAD_URL;
|
||||||
|
|
||||||
|
@Slf4j
|
||||||
public class StreamateFollowedService extends PaginatedScheduledService {
|
public class StreamateFollowedService extends PaginatedScheduledService {
|
||||||
|
|
||||||
private static final Logger LOG = LoggerFactory.getLogger(StreamateFollowedService.class);
|
|
||||||
|
|
||||||
private static final int MODELS_PER_PAGE = 48;
|
private static final int MODELS_PER_PAGE = 48;
|
||||||
private final Streamate streamate;
|
private final Streamate streamate;
|
||||||
private final StreamateHttpClient httpClient;
|
private final StreamateHttpClient httpClient;
|
||||||
|
@ -46,12 +43,12 @@ public class StreamateFollowedService extends PaginatedScheduledService {
|
||||||
try {
|
try {
|
||||||
httpClient.login();
|
httpClient.login();
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
LOG.debug("Login was not successful");
|
log.debug("Login was not successful");
|
||||||
return Collections.emptyList();
|
return Collections.emptyList();
|
||||||
}
|
}
|
||||||
String saKey = httpClient.getSaKey();
|
String saKey = httpClient.getSaKey();
|
||||||
String pageUrl = url + "&from=" + ((page - 1) * MODELS_PER_PAGE) + "&size=" + MODELS_PER_PAGE;
|
String pageUrl = url + "&from=" + ((page - 1) * MODELS_PER_PAGE) + "&size=" + MODELS_PER_PAGE;
|
||||||
LOG.debug("Fetching page {}", pageUrl);
|
log.debug("Fetching page {}", pageUrl);
|
||||||
String smxxx = UUID.randomUUID() + "G0211569057409";
|
String smxxx = UUID.randomUUID() + "G0211569057409";
|
||||||
String smtid = Optional.ofNullable(httpClient.getCookieValue("smtid")).orElse(smxxx);
|
String smtid = Optional.ofNullable(httpClient.getCookieValue("smtid")).orElse(smxxx);
|
||||||
String smeid = Optional.ofNullable(httpClient.getCookieValue("smeid")).orElse(smxxx);
|
String smeid = Optional.ofNullable(httpClient.getCookieValue("smeid")).orElse(smxxx);
|
||||||
|
|
|
@ -1,5 +1,7 @@
|
||||||
package ctbrec.ui.sites.streamate;
|
package ctbrec.ui.sites.streamate;
|
||||||
|
|
||||||
|
|
||||||
|
import lombok.extern.slf4j.Slf4j;
|
||||||
import ctbrec.Model;
|
import ctbrec.Model;
|
||||||
import ctbrec.io.HttpException;
|
import ctbrec.io.HttpException;
|
||||||
import ctbrec.sites.streamate.Streamate;
|
import ctbrec.sites.streamate.Streamate;
|
||||||
|
@ -8,9 +10,6 @@ import ctbrec.sites.streamate.StreamateModel;
|
||||||
import ctbrec.ui.tabs.PaginatedScheduledService;
|
import ctbrec.ui.tabs.PaginatedScheduledService;
|
||||||
import javafx.concurrent.Task;
|
import javafx.concurrent.Task;
|
||||||
import org.json.JSONObject;
|
import org.json.JSONObject;
|
||||||
import org.slf4j.Logger;
|
|
||||||
import org.slf4j.LoggerFactory;
|
|
||||||
|
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.util.*;
|
import java.util.*;
|
||||||
|
|
||||||
|
@ -18,10 +17,8 @@ import static ctbrec.ErrorMessages.HTTP_RESPONSE_BODY_IS_NULL;
|
||||||
import static ctbrec.Model.State.*;
|
import static ctbrec.Model.State.*;
|
||||||
import static ctbrec.io.HttpConstants.ORIGIN;
|
import static ctbrec.io.HttpConstants.ORIGIN;
|
||||||
|
|
||||||
|
@Slf4j
|
||||||
public class StreamateUpdateService extends PaginatedScheduledService {
|
public class StreamateUpdateService extends PaginatedScheduledService {
|
||||||
|
|
||||||
private static final Logger LOG = LoggerFactory.getLogger(StreamateUpdateService.class);
|
|
||||||
|
|
||||||
private static final int MODELS_PER_PAGE = 48;
|
private static final int MODELS_PER_PAGE = 48;
|
||||||
private final Streamate streamate;
|
private final Streamate streamate;
|
||||||
private final StreamateHttpClient httpClient;
|
private final StreamateHttpClient httpClient;
|
||||||
|
@ -41,7 +38,7 @@ public class StreamateUpdateService extends PaginatedScheduledService {
|
||||||
int from = (page - 1) * MODELS_PER_PAGE;
|
int from = (page - 1) * MODELS_PER_PAGE;
|
||||||
String saKey = httpClient.getSaKey();
|
String saKey = httpClient.getSaKey();
|
||||||
String pageUrl = url + "&from=" + from + "&size=" + MODELS_PER_PAGE;
|
String pageUrl = url + "&from=" + from + "&size=" + MODELS_PER_PAGE;
|
||||||
LOG.debug("Fetching page {}", pageUrl);
|
log.debug("Fetching page {}", pageUrl);
|
||||||
String smxxx = UUID.randomUUID() + "G0211569057409";
|
String smxxx = UUID.randomUUID() + "G0211569057409";
|
||||||
String smtid = Optional.ofNullable(httpClient.getCookieValue("smtid")).orElse(smxxx);
|
String smtid = Optional.ofNullable(httpClient.getCookieValue("smtid")).orElse(smxxx);
|
||||||
String smeid = Optional.ofNullable(httpClient.getCookieValue("smeid")).orElse(smxxx);
|
String smeid = Optional.ofNullable(httpClient.getCookieValue("smeid")).orElse(smxxx);
|
||||||
|
|
|
@ -1,5 +1,7 @@
|
||||||
package ctbrec.ui.sites.stripchat;
|
package ctbrec.ui.sites.stripchat;
|
||||||
|
|
||||||
|
|
||||||
|
import lombok.extern.slf4j.Slf4j;
|
||||||
import ctbrec.Config;
|
import ctbrec.Config;
|
||||||
import ctbrec.sites.stripchat.Stripchat;
|
import ctbrec.sites.stripchat.Stripchat;
|
||||||
import ctbrec.ui.ExternalBrowser;
|
import ctbrec.ui.ExternalBrowser;
|
||||||
|
@ -8,16 +10,12 @@ import okhttp3.Cookie.Builder;
|
||||||
import okhttp3.CookieJar;
|
import okhttp3.CookieJar;
|
||||||
import okhttp3.HttpUrl;
|
import okhttp3.HttpUrl;
|
||||||
import org.json.JSONObject;
|
import org.json.JSONObject;
|
||||||
import org.slf4j.Logger;
|
|
||||||
import org.slf4j.LoggerFactory;
|
|
||||||
|
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.util.Collections;
|
import java.util.Collections;
|
||||||
import java.util.function.Consumer;
|
import java.util.function.Consumer;
|
||||||
|
|
||||||
|
@Slf4j
|
||||||
public class StripchatElectronLoginDialog {
|
public class StripchatElectronLoginDialog {
|
||||||
|
|
||||||
private static final Logger LOG = LoggerFactory.getLogger(StripchatElectronLoginDialog.class);
|
|
||||||
public static final String DOMAIN = Stripchat.getDomain();
|
public static final String DOMAIN = Stripchat.getDomain();
|
||||||
public static final String URL = Stripchat.getBaseUri();
|
public static final String URL = Stripchat.getBaseUri();
|
||||||
private CookieJar cookieJar;
|
private CookieJar cookieJar;
|
||||||
|
@ -67,7 +65,7 @@ public class StripchatElectronLoginDialog {
|
||||||
browser.executeJavaScript("document.querySelector('#recaptcha-checkbox-border').click();");
|
browser.executeJavaScript("document.querySelector('#recaptcha-checkbox-border').click();");
|
||||||
browser.executeJavaScript("document.querySelector('*[class~=btn-login]').addEventListener('click', function() {window.setTimeout(function() {location.reload()}, 2000)});");
|
browser.executeJavaScript("document.querySelector('*[class~=btn-login]').addEventListener('click', function() {window.setTimeout(function() {location.reload()}, 2000)});");
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
LOG.warn("Couldn't auto fill username and password for Stripchat", e);
|
log.warn("Couldn't auto fill username and password for Stripchat", e);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -95,7 +93,7 @@ public class StripchatElectronLoginDialog {
|
||||||
try {
|
try {
|
||||||
browser.close();
|
browser.close();
|
||||||
} catch (IOException e) {
|
} catch (IOException e) {
|
||||||
LOG.error("Couldn't send close request to browser", e);
|
log.error("Couldn't send close request to browser", e);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,10 +1,8 @@
|
||||||
package ctbrec.ui.sites.stripchat;
|
package ctbrec.ui.sites.stripchat;
|
||||||
|
|
||||||
|
|
||||||
|
import lombok.extern.slf4j.Slf4j;
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
|
|
||||||
import org.slf4j.Logger;
|
|
||||||
import org.slf4j.LoggerFactory;
|
|
||||||
|
|
||||||
import ctbrec.sites.stripchat.Stripchat;
|
import ctbrec.sites.stripchat.Stripchat;
|
||||||
import ctbrec.sites.stripchat.StripchatHttpClient;
|
import ctbrec.sites.stripchat.StripchatHttpClient;
|
||||||
import ctbrec.ui.controls.Dialogs;
|
import ctbrec.ui.controls.Dialogs;
|
||||||
|
@ -12,10 +10,8 @@ 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;
|
||||||
|
|
||||||
|
@Slf4j
|
||||||
public class StripchatSiteUi extends AbstractSiteUi {
|
public class StripchatSiteUi extends AbstractSiteUi {
|
||||||
|
|
||||||
private static final Logger LOG = LoggerFactory.getLogger(StripchatSiteUi.class);
|
|
||||||
|
|
||||||
private StripchatTabProvider tabProvider;
|
private StripchatTabProvider tabProvider;
|
||||||
private StripchatConfigUI configUi;
|
private StripchatConfigUI configUi;
|
||||||
private Stripchat site;
|
private Stripchat site;
|
||||||
|
@ -50,7 +46,7 @@ public class StripchatSiteUi extends AbstractSiteUi {
|
||||||
try {
|
try {
|
||||||
new StripchatElectronLoginDialog(site.getHttpClient().getCookieJar());
|
new StripchatElectronLoginDialog(site.getHttpClient().getCookieJar());
|
||||||
} catch (Exception e1) {
|
} catch (Exception e1) {
|
||||||
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 " + site.getName(), e1);
|
Dialogs.showError("Login error", "Couldn't login to " + site.getName(), e1);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1,5 +1,7 @@
|
||||||
package ctbrec.ui.sites.stripchat;
|
package ctbrec.ui.sites.stripchat;
|
||||||
|
|
||||||
|
|
||||||
|
import lombok.extern.slf4j.Slf4j;
|
||||||
import ctbrec.Config;
|
import ctbrec.Config;
|
||||||
import ctbrec.Model;
|
import ctbrec.Model;
|
||||||
import ctbrec.io.HttpException;
|
import ctbrec.io.HttpException;
|
||||||
|
@ -9,9 +11,6 @@ import ctbrec.ui.SiteUiFactory;
|
||||||
import javafx.concurrent.Task;
|
import javafx.concurrent.Task;
|
||||||
import okhttp3.Request;
|
import okhttp3.Request;
|
||||||
import org.json.JSONObject;
|
import org.json.JSONObject;
|
||||||
import org.slf4j.Logger;
|
|
||||||
import org.slf4j.LoggerFactory;
|
|
||||||
|
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.Collections;
|
import java.util.Collections;
|
||||||
|
@ -20,10 +19,8 @@ import java.util.Locale;
|
||||||
|
|
||||||
import static ctbrec.io.HttpConstants.*;
|
import static ctbrec.io.HttpConstants.*;
|
||||||
|
|
||||||
|
@Slf4j
|
||||||
public class StripchatUpdateService extends AbstractStripchatUpdateService {
|
public class StripchatUpdateService extends AbstractStripchatUpdateService {
|
||||||
|
|
||||||
private static final Logger LOG = LoggerFactory.getLogger(StripchatUpdateService.class);
|
|
||||||
|
|
||||||
private final String url;
|
private final String url;
|
||||||
private final boolean loginRequired;
|
private final boolean loginRequired;
|
||||||
private final Stripchat stripchat;
|
private final Stripchat stripchat;
|
||||||
|
@ -46,7 +43,7 @@ public class StripchatUpdateService extends AbstractStripchatUpdateService {
|
||||||
int offset = (getPage() - 1) * modelsPerPage;
|
int offset = (getPage() - 1) * modelsPerPage;
|
||||||
int limit = modelsPerPage;
|
int limit = modelsPerPage;
|
||||||
String paginatedUrl = url + "&offset=" + offset + "&limit=" + limit;
|
String paginatedUrl = url + "&offset=" + offset + "&limit=" + limit;
|
||||||
LOG.debug("Fetching page {}", paginatedUrl);
|
log.debug("Fetching page {}", paginatedUrl);
|
||||||
if (loginRequired) {
|
if (loginRequired) {
|
||||||
SiteUiFactory.getUi(stripchat).login();
|
SiteUiFactory.getUi(stripchat).login();
|
||||||
}
|
}
|
||||||
|
@ -90,12 +87,12 @@ public class StripchatUpdateService extends AbstractStripchatUpdateService {
|
||||||
model.setDescription(description.toString());
|
model.setDescription(description.toString());
|
||||||
models.add(model);
|
models.add(model);
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
LOG.warn("Couldn't parse one of the models: {}", jsonModel, e);
|
log.warn("Couldn't parse one of the models: {}", jsonModel, e);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return models;
|
return models;
|
||||||
} else {
|
} else {
|
||||||
LOG.debug("Response was not successful: {}", json);
|
log.debug("Response was not successful: {}", json);
|
||||||
return Collections.emptyList();
|
return Collections.emptyList();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,5 +1,7 @@
|
||||||
package ctbrec.ui.tabs;
|
package ctbrec.ui.tabs;
|
||||||
|
|
||||||
|
|
||||||
|
import lombok.extern.slf4j.Slf4j;
|
||||||
import ctbrec.*;
|
import ctbrec.*;
|
||||||
import ctbrec.Recording.State;
|
import ctbrec.Recording.State;
|
||||||
import ctbrec.event.EventBusHolder;
|
import ctbrec.event.EventBusHolder;
|
||||||
|
@ -43,9 +45,6 @@ import javafx.scene.layout.StackPane;
|
||||||
import javafx.scene.text.Font;
|
import javafx.scene.text.Font;
|
||||||
import javafx.stage.FileChooser;
|
import javafx.stage.FileChooser;
|
||||||
import javafx.util.Duration;
|
import javafx.util.Duration;
|
||||||
import org.slf4j.Logger;
|
|
||||||
import org.slf4j.LoggerFactory;
|
|
||||||
|
|
||||||
import java.io.File;
|
import java.io.File;
|
||||||
import java.io.FileNotFoundException;
|
import java.io.FileNotFoundException;
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
|
@ -67,11 +66,9 @@ import static ctbrec.Recording.State.*;
|
||||||
import static javafx.scene.control.ButtonType.NO;
|
import static javafx.scene.control.ButtonType.NO;
|
||||||
import static javafx.scene.control.ButtonType.YES;
|
import static javafx.scene.control.ButtonType.YES;
|
||||||
|
|
||||||
|
@Slf4j
|
||||||
public class RecordingsTab extends Tab implements TabSelectionListener, ShutdownListener {
|
public class RecordingsTab extends Tab implements TabSelectionListener, ShutdownListener {
|
||||||
private static final String ERROR_WHILE_DOWNLOADING_RECORDING = "Error while downloading recording";
|
private static final String ERROR_WHILE_DOWNLOADING_RECORDING = "Error while downloading recording";
|
||||||
|
|
||||||
private static final Logger LOG = LoggerFactory.getLogger(RecordingsTab.class);
|
|
||||||
|
|
||||||
private ScheduledService<List<JavaFxRecording>> updateService;
|
private ScheduledService<List<JavaFxRecording>> updateService;
|
||||||
private final Config config;
|
private final Config config;
|
||||||
private final ModelNotesService modelNotesService;
|
private final ModelNotesService modelNotesService;
|
||||||
|
@ -168,7 +165,7 @@ public class RecordingsTab extends Tab implements TabSelectionListener, Shutdown
|
||||||
try {
|
try {
|
||||||
modelNts = modelNotesService.loadModelNotes(cdf.getValue().getModel().getUrl()).orElse("");
|
modelNts = modelNotesService.loadModelNotes(cdf.getValue().getModel().getUrl()).orElse("");
|
||||||
} catch (IOException e) {
|
} catch (IOException e) {
|
||||||
LOG.warn("Could not load model notes", e);
|
log.warn("Could not load model notes", e);
|
||||||
modelNts = "";
|
modelNts = "";
|
||||||
}
|
}
|
||||||
return new SimpleStringProperty(modelNts);
|
return new SimpleStringProperty(modelNts);
|
||||||
|
@ -309,7 +306,7 @@ public class RecordingsTab extends Tab implements TabSelectionListener, Shutdown
|
||||||
updateUsedSpaceDisplay();
|
updateUsedSpaceDisplay();
|
||||||
});
|
});
|
||||||
updateService.setOnFailed(event -> {
|
updateService.setOnFailed(event -> {
|
||||||
LOG.info("Couldn't get list of recordings from recorder", event.getSource().getException());
|
log.info("Couldn't get list of recordings from recorder", event.getSource().getException());
|
||||||
var autosizeAlert = new AutosizeAlert(AlertType.ERROR, getTabPane().getScene());
|
var autosizeAlert = new AutosizeAlert(AlertType.ERROR, getTabPane().getScene());
|
||||||
autosizeAlert.setTitle("Whoopsie!");
|
autosizeAlert.setTitle("Whoopsie!");
|
||||||
autosizeAlert.setHeaderText("Recordings not available");
|
autosizeAlert.setHeaderText("Recordings not available");
|
||||||
|
@ -389,7 +386,7 @@ public class RecordingsTab extends Tab implements TabSelectionListener, Shutdown
|
||||||
// recordings dir does not exist
|
// recordings dir does not exist
|
||||||
Platform.runLater(() -> spaceLeft.setTooltip(new Tooltip("Recordings directory does not exist")));
|
Platform.runLater(() -> spaceLeft.setTooltip(new Tooltip("Recordings directory does not exist")));
|
||||||
} catch (IOException e) {
|
} catch (IOException e) {
|
||||||
LOG.error("Couldn't update free space", e);
|
log.error("Couldn't update free space", e);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
@ -687,7 +684,7 @@ public class RecordingsTab extends Tab implements TabSelectionListener, Shutdown
|
||||||
recorder.rerunPostProcessing(rec.getDelegate());
|
recorder.rerunPostProcessing(rec.getDelegate());
|
||||||
} catch (IOException | InvalidKeyException | NoSuchAlgorithmException | IllegalStateException e1) {
|
} catch (IOException | InvalidKeyException | NoSuchAlgorithmException | IllegalStateException e1) {
|
||||||
showErrorDialog("Error while starting post-processing", "The post-processing could not be started", e1);
|
showErrorDialog("Error while starting post-processing", "The post-processing could not be started", e1);
|
||||||
LOG.error("Error while starting post-processing", e1);
|
log.error("Error while starting post-processing", e1);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
@ -695,7 +692,7 @@ public class RecordingsTab extends Tab implements TabSelectionListener, Shutdown
|
||||||
|
|
||||||
private void download(Recording recording) {
|
private void download(Recording recording) {
|
||||||
try {
|
try {
|
||||||
LOG.debug("Path {}", recording.getAbsoluteFile());
|
log.debug("Path {}", recording.getAbsoluteFile());
|
||||||
String filename = proposeTargetFilename(recording);
|
String filename = proposeTargetFilename(recording);
|
||||||
var chooser = new FileChooser();
|
var chooser = new FileChooser();
|
||||||
chooser.setInitialFileName(filename);
|
chooser.setInitialFileName(filename);
|
||||||
|
@ -742,19 +739,19 @@ public class RecordingsTab extends Tab implements TabSelectionListener, Shutdown
|
||||||
var url = new URL(hlsBase + '/' + recording.getId() + "/playlist.m3u8");
|
var url = new URL(hlsBase + '/' + recording.getId() + "/playlist.m3u8");
|
||||||
var download = new RecordingDownload(CamrecApplication.httpClient);
|
var download = new RecordingDownload(CamrecApplication.httpClient);
|
||||||
download.init(config, recording.getModel(), Instant.now(), Executors.newSingleThreadExecutor());
|
download.init(config, recording.getModel(), Instant.now(), Executors.newSingleThreadExecutor());
|
||||||
LOG.info("Downloading {}", url);
|
log.info("Downloading {}", url);
|
||||||
download.downloadFinishedRecording(url.toString(), target, createDownloadListener(recording), recording.getSizeInByte());
|
download.downloadFinishedRecording(url.toString(), target, createDownloadListener(recording), recording.getSizeInByte());
|
||||||
}
|
}
|
||||||
} catch (FileNotFoundException e) {
|
} catch (FileNotFoundException e) {
|
||||||
showErrorDialog(ERROR_WHILE_DOWNLOADING_RECORDING, "The target file couldn't be created", e);
|
showErrorDialog(ERROR_WHILE_DOWNLOADING_RECORDING, "The target file couldn't be created", e);
|
||||||
LOG.error(ERROR_WHILE_DOWNLOADING_RECORDING, e);
|
log.error(ERROR_WHILE_DOWNLOADING_RECORDING, e);
|
||||||
} catch (InterruptedException e) {
|
} catch (InterruptedException e) {
|
||||||
Thread.currentThread().interrupt();
|
Thread.currentThread().interrupt();
|
||||||
showErrorDialog(ERROR_WHILE_DOWNLOADING_RECORDING, "The recording could not be downloaded", e);
|
showErrorDialog(ERROR_WHILE_DOWNLOADING_RECORDING, "The recording could not be downloaded", e);
|
||||||
LOG.error(ERROR_WHILE_DOWNLOADING_RECORDING, e);
|
log.error(ERROR_WHILE_DOWNLOADING_RECORDING, e);
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
showErrorDialog(ERROR_WHILE_DOWNLOADING_RECORDING, "The recording could not be downloaded", e);
|
showErrorDialog(ERROR_WHILE_DOWNLOADING_RECORDING, "The recording could not be downloaded", e);
|
||||||
LOG.error(ERROR_WHILE_DOWNLOADING_RECORDING, e);
|
log.error(ERROR_WHILE_DOWNLOADING_RECORDING, e);
|
||||||
} finally {
|
} finally {
|
||||||
Platform.runLater(() -> {
|
Platform.runLater(() -> {
|
||||||
recording.setStatus(FINISHED);
|
recording.setStatus(FINISHED);
|
||||||
|
@ -772,7 +769,7 @@ public class RecordingsTab extends Tab implements TabSelectionListener, Shutdown
|
||||||
return progress -> Platform.runLater(() -> {
|
return progress -> Platform.runLater(() -> {
|
||||||
if (progress == 100) {
|
if (progress == 100) {
|
||||||
recording.setStatus(FINISHED);
|
recording.setStatus(FINISHED);
|
||||||
LOG.debug("Download finished for recording {} - {}", recording.getId(), recording.getAbsoluteFile());
|
log.debug("Download finished for recording {} - {}", recording.getId(), recording.getAbsoluteFile());
|
||||||
} else {
|
} else {
|
||||||
recording.setStatus(DOWNLOADING);
|
recording.setStatus(DOWNLOADING);
|
||||||
}
|
}
|
||||||
|
@ -846,7 +843,7 @@ public class RecordingsTab extends Tab implements TabSelectionListener, Shutdown
|
||||||
deleted.add(r);
|
deleted.add(r);
|
||||||
} catch (Exception e1) {
|
} catch (Exception e1) {
|
||||||
exceptions.add(e1);
|
exceptions.add(e1);
|
||||||
LOG.error("Error while deleting recording", e1);
|
log.error("Error while deleting recording", e1);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (!exceptions.isEmpty()) {
|
if (!exceptions.isEmpty()) {
|
||||||
|
|
|
@ -1,5 +1,7 @@
|
||||||
package ctbrec.ui.tabs;
|
package ctbrec.ui.tabs;
|
||||||
|
|
||||||
|
|
||||||
|
import lombok.extern.slf4j.Slf4j;
|
||||||
import com.google.common.cache.CacheBuilder;
|
import com.google.common.cache.CacheBuilder;
|
||||||
import com.google.common.cache.CacheLoader;
|
import com.google.common.cache.CacheLoader;
|
||||||
import com.google.common.cache.LoadingCache;
|
import com.google.common.cache.LoadingCache;
|
||||||
|
@ -49,9 +51,6 @@ import javafx.scene.text.TextAlignment;
|
||||||
import javafx.util.Duration;
|
import javafx.util.Duration;
|
||||||
import okhttp3.Request;
|
import okhttp3.Request;
|
||||||
import okhttp3.Response;
|
import okhttp3.Response;
|
||||||
import org.slf4j.Logger;
|
|
||||||
import org.slf4j.LoggerFactory;
|
|
||||||
|
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.io.InputStream;
|
import java.io.InputStream;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
@ -68,10 +67,10 @@ import static ctbrec.Model.State.ONLINE;
|
||||||
import static ctbrec.io.HttpConstants.*;
|
import static ctbrec.io.HttpConstants.*;
|
||||||
import static ctbrec.ui.Icon.*;
|
import static ctbrec.ui.Icon.*;
|
||||||
|
|
||||||
|
@Slf4j
|
||||||
public class ThumbCell extends StackPane {
|
public class ThumbCell extends StackPane {
|
||||||
|
|
||||||
private static final String ERROR = "Error";
|
private static final String ERROR = "Error";
|
||||||
private static final Logger LOG = LoggerFactory.getLogger(ThumbCell.class);
|
|
||||||
private static final Duration ANIMATION_DURATION = new Duration(250);
|
private static final Duration ANIMATION_DURATION = new Duration(250);
|
||||||
|
|
||||||
private static final Image imgRecordIndicator = new Image(MEDIA_RECORD_16.url());
|
private static final Image imgRecordIndicator = new Image(MEDIA_RECORD_16.url());
|
||||||
|
@ -390,7 +389,7 @@ public class ThumbCell extends StackPane {
|
||||||
throw new HttpException(resp.code(), resp.message());
|
throw new HttpException(resp.code(), resp.message());
|
||||||
}
|
}
|
||||||
} catch (IOException e) {
|
} catch (IOException e) {
|
||||||
LOG.warn("Error loading thumbnail: {} {}", url, e.getLocalizedMessage());
|
log.warn("Error loading thumbnail: {} {}", url, e.getLocalizedMessage());
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
@ -469,7 +468,7 @@ public class ThumbCell extends StackPane {
|
||||||
}
|
}
|
||||||
setRecording(recording);
|
setRecording(recording);
|
||||||
} catch (Exception e1) {
|
} catch (Exception e1) {
|
||||||
LOG.error("Couldn't pause/resume recording", e1);
|
log.error("Couldn't pause/resume recording", e1);
|
||||||
Platform.runLater(() -> {
|
Platform.runLater(() -> {
|
||||||
Alert alert = new AutosizeAlert(Alert.AlertType.ERROR, getScene());
|
Alert alert = new AutosizeAlert(Alert.AlertType.ERROR, getScene());
|
||||||
alert.setTitle(ERROR);
|
alert.setTitle(ERROR);
|
||||||
|
@ -508,7 +507,7 @@ public class ThumbCell extends StackPane {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} catch (Exception e1) {
|
} catch (Exception e1) {
|
||||||
LOG.error("Couldn't follow/unfollow model {}", model.getName(), e1);
|
log.error("Couldn't follow/unfollow model {}", model.getName(), e1);
|
||||||
String msg = "I/O error while following/unfollowing model " + model.getName() + ": ";
|
String msg = "I/O error while following/unfollowing model " + model.getName() + ": ";
|
||||||
Dialogs.showError(getScene(), "Couldn't follow/unfollow model", msg, e1);
|
Dialogs.showError(getScene(), "Couldn't follow/unfollow model", msg, e1);
|
||||||
return false;
|
return false;
|
||||||
|
@ -627,7 +626,7 @@ public class ThumbCell extends StackPane {
|
||||||
try {
|
try {
|
||||||
return model.getStreamResolution(false);
|
return model.getStreamResolution(false);
|
||||||
} catch (ExecutionException e) {
|
} catch (ExecutionException e) {
|
||||||
LOG.trace("Error loading stream resolution for model {}: {}", model, e.getLocalizedMessage());
|
log.trace("Error loading stream resolution for model {}: {}", model, e.getLocalizedMessage());
|
||||||
return new int[2];
|
return new int[2];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,5 +1,7 @@
|
||||||
package ctbrec.ui.tabs;
|
package ctbrec.ui.tabs;
|
||||||
|
|
||||||
|
|
||||||
|
import lombok.extern.slf4j.Slf4j;
|
||||||
import ctbrec.Config;
|
import ctbrec.Config;
|
||||||
import ctbrec.GlobalThreadPool;
|
import ctbrec.GlobalThreadPool;
|
||||||
import ctbrec.Model;
|
import ctbrec.Model;
|
||||||
|
@ -36,9 +38,6 @@ import javafx.scene.image.ImageView;
|
||||||
import javafx.scene.input.*;
|
import javafx.scene.input.*;
|
||||||
import javafx.scene.layout.*;
|
import javafx.scene.layout.*;
|
||||||
import javafx.util.Duration;
|
import javafx.util.Duration;
|
||||||
import org.slf4j.Logger;
|
|
||||||
import org.slf4j.LoggerFactory;
|
|
||||||
|
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.net.SocketTimeoutException;
|
import java.net.SocketTimeoutException;
|
||||||
import java.util.*;
|
import java.util.*;
|
||||||
|
@ -46,9 +45,8 @@ import java.util.concurrent.*;
|
||||||
import java.util.concurrent.locks.ReentrantLock;
|
import java.util.concurrent.locks.ReentrantLock;
|
||||||
import java.util.stream.Collectors;
|
import java.util.stream.Collectors;
|
||||||
|
|
||||||
|
@Slf4j
|
||||||
public class ThumbOverviewTab extends Tab implements TabSelectionListener {
|
public class ThumbOverviewTab extends Tab implements TabSelectionListener {
|
||||||
private static final Logger LOG = LoggerFactory.getLogger(ThumbOverviewTab.class);
|
|
||||||
|
|
||||||
protected static BlockingQueue<Runnable> queue = new LinkedBlockingQueue<>();
|
protected static BlockingQueue<Runnable> queue = new LinkedBlockingQueue<>();
|
||||||
static ExecutorService threadPool = new ThreadPoolExecutor(2, 2, 10, TimeUnit.MINUTES, queue, createThreadFactory());
|
static ExecutorService threadPool = new ThreadPoolExecutor(2, 2, 10, TimeUnit.MINUTES, queue, createThreadFactory());
|
||||||
|
|
||||||
|
@ -617,14 +615,14 @@ public class ThumbOverviewTab extends Tab implements TabSelectionListener {
|
||||||
protected void onFail(WorkerStateEvent event) {
|
protected void onFail(WorkerStateEvent event) {
|
||||||
if (event.getSource().getException() != null) {
|
if (event.getSource().getException() != null) {
|
||||||
if (event.getSource().getException() instanceof SocketTimeoutException) {
|
if (event.getSource().getException() instanceof SocketTimeoutException) {
|
||||||
LOG.debug("Fetching model list timed out");
|
log.debug("Fetching model list timed out");
|
||||||
errorLabel.setText("Timeout while updating");
|
errorLabel.setText("Timeout while updating");
|
||||||
} else {
|
} else {
|
||||||
LOG.error("Couldn't update model list", event.getSource().getException());
|
log.error("Couldn't update model list", event.getSource().getException());
|
||||||
errorLabel.setText("Error while updating " + event.getSource().getException().getLocalizedMessage());
|
errorLabel.setText("Error while updating " + event.getSource().getException().getLocalizedMessage());
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
LOG.error("Couldn't update model list {}", event.getEventType());
|
log.error("Couldn't update model list {}", event.getEventType());
|
||||||
errorLabel.setText("Couldn't update model list " + event.getEventType());
|
errorLabel.setText("Couldn't update model list " + event.getEventType());
|
||||||
}
|
}
|
||||||
grid.getChildren().removeAll(progressIndicator, noResultsFound, errorLabel);
|
grid.getChildren().removeAll(progressIndicator, noResultsFound, errorLabel);
|
||||||
|
@ -718,7 +716,7 @@ public class ThumbOverviewTab extends Tab implements TabSelectionListener {
|
||||||
}
|
}
|
||||||
return !tokensMissing;
|
return !tokensMissing;
|
||||||
} catch (NumberFormatException | ExecutionException | IOException e) {
|
} catch (NumberFormatException | ExecutionException | IOException e) {
|
||||||
LOG.error("Error while filtering model list", e);
|
log.error("Error while filtering model list", e);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,13 +1,11 @@
|
||||||
package ctbrec.ui.tabs;
|
package ctbrec.ui.tabs;
|
||||||
|
|
||||||
|
|
||||||
|
import lombok.extern.slf4j.Slf4j;
|
||||||
import static ctbrec.ui.controls.Dialogs.*;
|
import static ctbrec.ui.controls.Dialogs.*;
|
||||||
|
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
import org.slf4j.Logger;
|
|
||||||
import org.slf4j.LoggerFactory;
|
|
||||||
|
|
||||||
import ctbrec.Model;
|
import ctbrec.Model;
|
||||||
import ctbrec.sites.Site;
|
import ctbrec.sites.Site;
|
||||||
import ctbrec.ui.SiteUiFactory;
|
import ctbrec.ui.SiteUiFactory;
|
||||||
|
@ -16,10 +14,8 @@ import ctbrec.ui.controls.SearchPopoverTreeList;
|
||||||
import javafx.application.Platform;
|
import javafx.application.Platform;
|
||||||
import javafx.concurrent.Task;
|
import javafx.concurrent.Task;
|
||||||
|
|
||||||
|
@Slf4j
|
||||||
public class ThumbOverviewTabSearchTask extends Task<List<Model>> {
|
public class ThumbOverviewTabSearchTask extends Task<List<Model>> {
|
||||||
|
|
||||||
private static final Logger LOG = LoggerFactory.getLogger(ThumbOverviewTabSearchTask.class);
|
|
||||||
|
|
||||||
private final Site site;
|
private final Site site;
|
||||||
private final SearchPopover popover;
|
private final SearchPopover popover;
|
||||||
private final SearchPopoverTreeList popoverTreeList;
|
private final SearchPopoverTreeList popoverTreeList;
|
||||||
|
@ -50,14 +46,14 @@ public class ThumbOverviewTabSearchTask extends Task<List<Model>> {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected void failed() {
|
protected void failed() {
|
||||||
LOG.error("Search failed", getException());
|
log.error("Search failed", getException());
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected void succeeded() {
|
protected void succeeded() {
|
||||||
Platform.runLater(() -> {
|
Platform.runLater(() -> {
|
||||||
List<Model> models = getValue();
|
List<Model> models = getValue();
|
||||||
LOG.debug("Search result {} {}", isCancelled(), models);
|
log.debug("Search result {} {}", isCancelled(), models);
|
||||||
if(models.isEmpty()) {
|
if(models.isEmpty()) {
|
||||||
popover.hide();
|
popover.hide();
|
||||||
} else {
|
} else {
|
||||||
|
|
|
@ -1,5 +1,7 @@
|
||||||
package ctbrec.ui.tabs.recorded;
|
package ctbrec.ui.tabs.recorded;
|
||||||
|
|
||||||
|
|
||||||
|
import lombok.extern.slf4j.Slf4j;
|
||||||
import ctbrec.Config;
|
import ctbrec.Config;
|
||||||
import ctbrec.Model;
|
import ctbrec.Model;
|
||||||
import ctbrec.recorder.Recorder;
|
import ctbrec.recorder.Recorder;
|
||||||
|
@ -17,18 +19,14 @@ import javafx.concurrent.WorkerStateEvent;
|
||||||
import javafx.geometry.Insets;
|
import javafx.geometry.Insets;
|
||||||
import javafx.scene.layout.BorderPane;
|
import javafx.scene.layout.BorderPane;
|
||||||
import javafx.util.Duration;
|
import javafx.util.Duration;
|
||||||
import org.slf4j.Logger;
|
|
||||||
import org.slf4j.LoggerFactory;
|
|
||||||
|
|
||||||
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.TimeUnit;
|
import java.util.concurrent.TimeUnit;
|
||||||
import java.util.function.Predicate;
|
import java.util.function.Predicate;
|
||||||
|
|
||||||
|
@Slf4j
|
||||||
public class RecordLaterTab extends AbstractRecordedModelsTab {
|
public class RecordLaterTab extends AbstractRecordedModelsTab {
|
||||||
private static final Logger LOG = LoggerFactory.getLogger(RecordLaterTab.class);
|
|
||||||
|
|
||||||
private ScheduledService<List<JavaFxModel>> updateService;
|
private ScheduledService<List<JavaFxModel>> updateService;
|
||||||
|
|
||||||
public RecordLaterTab(String title, Recorder recorder, List<Site> sites) {
|
public RecordLaterTab(String title, Recorder recorder, List<Site> sites) {
|
||||||
|
@ -72,7 +70,7 @@ public class RecordLaterTab extends AbstractRecordedModelsTab {
|
||||||
updateService = createUpdateService();
|
updateService = createUpdateService();
|
||||||
updateService.setPeriod(new Duration(TimeUnit.SECONDS.toMillis(2)));
|
updateService.setPeriod(new Duration(TimeUnit.SECONDS.toMillis(2)));
|
||||||
updateService.setOnSucceeded(this::onUpdateSuccess);
|
updateService.setOnSucceeded(this::onUpdateSuccess);
|
||||||
updateService.setOnFailed(event -> LOG.info("Couldn't get list of models from recorder", event.getSource().getException()));
|
updateService.setOnFailed(event -> log.info("Couldn't get list of models from recorder", event.getSource().getException()));
|
||||||
}
|
}
|
||||||
|
|
||||||
private void onUpdateSuccess(WorkerStateEvent event) {
|
private void onUpdateSuccess(WorkerStateEvent event) {
|
||||||
|
@ -117,7 +115,7 @@ public class RecordLaterTab extends AbstractRecordedModelsTab {
|
||||||
return new Task<>() {
|
return new Task<>() {
|
||||||
@Override
|
@Override
|
||||||
public List<JavaFxModel> call() {
|
public List<JavaFxModel> call() {
|
||||||
LOG.trace("Updating models marked for later recording");
|
log.trace("Updating models marked for later recording");
|
||||||
return recorder.getModels().stream().filter(Model::isMarkedForLaterRecording).map(JavaFxModel::new).toList();
|
return recorder.getModels().stream().filter(Model::isMarkedForLaterRecording).map(JavaFxModel::new).toList();
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
|
@ -1,5 +1,7 @@
|
||||||
package ctbrec.ui.tabs.recorded;
|
package ctbrec.ui.tabs.recorded;
|
||||||
|
|
||||||
|
|
||||||
|
import lombok.extern.slf4j.Slf4j;
|
||||||
import ctbrec.Config;
|
import ctbrec.Config;
|
||||||
import ctbrec.Model;
|
import ctbrec.Model;
|
||||||
import ctbrec.Recording;
|
import ctbrec.Recording;
|
||||||
|
@ -30,9 +32,6 @@ import javafx.scene.layout.HBox;
|
||||||
import javafx.util.Callback;
|
import javafx.util.Callback;
|
||||||
import javafx.util.Duration;
|
import javafx.util.Duration;
|
||||||
import javafx.util.converter.NumberStringConverter;
|
import javafx.util.converter.NumberStringConverter;
|
||||||
import org.slf4j.Logger;
|
|
||||||
import org.slf4j.LoggerFactory;
|
|
||||||
|
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.security.InvalidKeyException;
|
import java.security.InvalidKeyException;
|
||||||
import java.security.NoSuchAlgorithmException;
|
import java.security.NoSuchAlgorithmException;
|
||||||
|
@ -48,9 +47,8 @@ import java.util.function.Predicate;
|
||||||
|
|
||||||
import static ctbrec.Recording.State.RECORDING;
|
import static ctbrec.Recording.State.RECORDING;
|
||||||
|
|
||||||
|
@Slf4j
|
||||||
public class RecordedModelsTab extends AbstractRecordedModelsTab {
|
public class RecordedModelsTab extends AbstractRecordedModelsTab {
|
||||||
private static final Logger LOG = LoggerFactory.getLogger(RecordedModelsTab.class);
|
|
||||||
|
|
||||||
private ScheduledService<List<JavaFxModel>> updateService;
|
private ScheduledService<List<JavaFxModel>> updateService;
|
||||||
private volatile boolean cellEditing = false;
|
private volatile boolean cellEditing = false;
|
||||||
|
|
||||||
|
@ -232,7 +230,7 @@ public class RecordedModelsTab extends AbstractRecordedModelsTab {
|
||||||
updateService = createUpdateService();
|
updateService = createUpdateService();
|
||||||
updateService.setPeriod(new Duration(TimeUnit.SECONDS.toMillis(2)));
|
updateService.setPeriod(new Duration(TimeUnit.SECONDS.toMillis(2)));
|
||||||
updateService.setOnSucceeded(this::onUpdateSuccess);
|
updateService.setOnSucceeded(this::onUpdateSuccess);
|
||||||
updateService.setOnFailed(event -> LOG.info("Couldn't get list of models from recorder", event.getSource().getException()));
|
updateService.setOnFailed(event -> log.info("Couldn't get list of models from recorder", event.getSource().getException()));
|
||||||
}
|
}
|
||||||
|
|
||||||
private void onUpdateSuccess(WorkerStateEvent event) {
|
private void onUpdateSuccess(WorkerStateEvent event) {
|
||||||
|
@ -311,7 +309,7 @@ public class RecordedModelsTab extends AbstractRecordedModelsTab {
|
||||||
return new Task<>() {
|
return new Task<>() {
|
||||||
@Override
|
@Override
|
||||||
public List<JavaFxModel> call() throws InvalidKeyException, NoSuchAlgorithmException, IOException {
|
public List<JavaFxModel> call() throws InvalidKeyException, NoSuchAlgorithmException, IOException {
|
||||||
LOG.trace("Updating recorded models");
|
log.trace("Updating recorded models");
|
||||||
List<Recording> recordings = recorder.getRecordings();
|
List<Recording> recordings = recorder.getRecordings();
|
||||||
List<Model> onlineModels = recorder.getOnlineModels();
|
List<Model> onlineModels = recorder.getOnlineModels();
|
||||||
return recorder.getModels().stream().filter(Predicate.not(Model::isMarkedForLaterRecording)).map(JavaFxModel::new).peek(fxm -> { // NOSONAR
|
return recorder.getModels().stream().filter(Predicate.not(Model::isMarkedForLaterRecording)).map(JavaFxModel::new).peek(fxm -> { // NOSONAR
|
||||||
|
|
|
@ -1,8 +1,6 @@
|
||||||
package ctbrec;
|
package ctbrec;
|
||||||
|
|
||||||
import org.slf4j.Logger;
|
import lombok.extern.slf4j.Slf4j;
|
||||||
import org.slf4j.LoggerFactory;
|
|
||||||
|
|
||||||
import javax.crypto.Mac;
|
import javax.crypto.Mac;
|
||||||
import javax.crypto.spec.SecretKeySpec;
|
import javax.crypto.spec.SecretKeySpec;
|
||||||
import java.security.InvalidKeyException;
|
import java.security.InvalidKeyException;
|
||||||
|
@ -12,15 +10,13 @@ import java.util.Base64;
|
||||||
|
|
||||||
import static java.nio.charset.StandardCharsets.UTF_8;
|
import static java.nio.charset.StandardCharsets.UTF_8;
|
||||||
|
|
||||||
|
@Slf4j
|
||||||
public class Hmac {
|
public class Hmac {
|
||||||
|
|
||||||
private Hmac() {
|
private Hmac() {
|
||||||
}
|
}
|
||||||
|
|
||||||
private static final Logger LOG = LoggerFactory.getLogger(Hmac.class);
|
|
||||||
|
|
||||||
public static byte[] generateKey() {
|
public static byte[] generateKey() {
|
||||||
LOG.debug("Generating HMAC key");
|
log.debug("Generating HMAC key");
|
||||||
SecureRandom random = new SecureRandom();
|
SecureRandom random = new SecureRandom();
|
||||||
byte[] key = new byte[32];
|
byte[] key = new byte[32];
|
||||||
random.nextBytes(key);
|
random.nextBytes(key);
|
||||||
|
|
|
@ -1,34 +1,31 @@
|
||||||
package ctbrec;
|
package ctbrec;
|
||||||
|
|
||||||
|
|
||||||
|
import lombok.extern.slf4j.Slf4j;
|
||||||
import kotlin.Pair;
|
import kotlin.Pair;
|
||||||
import okhttp3.Interceptor;
|
import okhttp3.Interceptor;
|
||||||
import okhttp3.Request;
|
import okhttp3.Request;
|
||||||
import okhttp3.Response;
|
import okhttp3.Response;
|
||||||
import org.slf4j.Logger;
|
|
||||||
import org.slf4j.LoggerFactory;
|
|
||||||
|
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
|
|
||||||
|
@Slf4j
|
||||||
public class LoggingInterceptor implements Interceptor {
|
public class LoggingInterceptor implements Interceptor {
|
||||||
|
|
||||||
private static final Logger LOG = LoggerFactory.getLogger(LoggingInterceptor.class);
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Response intercept(Chain chain) throws IOException {
|
public Response intercept(Chain chain) throws IOException {
|
||||||
long t1 = System.nanoTime();
|
long t1 = System.nanoTime();
|
||||||
Request request = chain.request();
|
Request request = chain.request();
|
||||||
LOG.debug("OkHttp Sending request {} on {}", request.url(), chain.connection());
|
log.debug("OkHttp Sending request {} on {}", request.url(), chain.connection());
|
||||||
for (Pair<?, ?> header : request.headers()) {
|
for (Pair<?, ?> header : request.headers()) {
|
||||||
LOG.debug("{}: {}", header.getFirst(), header.getSecond());
|
log.debug("{}: {}", header.getFirst(), header.getSecond());
|
||||||
}
|
}
|
||||||
if (request.method().equalsIgnoreCase("POST")) {
|
if (request.method().equalsIgnoreCase("POST")) {
|
||||||
LOG.debug("Body: {}", request.body());
|
log.debug("Body: {}", request.body());
|
||||||
}
|
}
|
||||||
Response response = chain.proceed(request);
|
Response response = chain.proceed(request);
|
||||||
long t2 = System.nanoTime();
|
long t2 = System.nanoTime();
|
||||||
LOG.debug("OkHttp Received {} response for {} in {}ms", response.code(), response.request().url(), (t2 - t1) / 1e6d);
|
log.debug("OkHttp Received {} response for {} in {}ms", response.code(), response.request().url(), (t2 - t1) / 1e6d);
|
||||||
for (Pair<?, ?> header : response.headers()) {
|
for (Pair<?, ?> header : response.headers()) {
|
||||||
LOG.debug("{}: {}", header.getFirst(), header.getSecond());
|
log.debug("{}: {}", header.getFirst(), header.getSecond());
|
||||||
}
|
}
|
||||||
return response;
|
return response;
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,5 +1,7 @@
|
||||||
package ctbrec;
|
package ctbrec;
|
||||||
|
|
||||||
|
|
||||||
|
import lombok.extern.slf4j.Slf4j;
|
||||||
import java.io.File;
|
import java.io.File;
|
||||||
import java.net.URI;
|
import java.net.URI;
|
||||||
import java.net.URISyntaxException;
|
import java.net.URISyntaxException;
|
||||||
|
@ -7,14 +9,8 @@ import java.nio.file.Path;
|
||||||
import java.nio.file.Paths;
|
import java.nio.file.Paths;
|
||||||
import java.util.Arrays;
|
import java.util.Arrays;
|
||||||
import java.util.Map.Entry;
|
import java.util.Map.Entry;
|
||||||
|
@Slf4j
|
||||||
import org.slf4j.Logger;
|
|
||||||
import org.slf4j.LoggerFactory;
|
|
||||||
|
|
||||||
public class OS {
|
public class OS {
|
||||||
|
|
||||||
private static final Logger LOG = LoggerFactory.getLogger(OS.class);
|
|
||||||
|
|
||||||
private static final String USER_HOME = "user.home";
|
private static final String USER_HOME = "user.home";
|
||||||
private static final String OS_NAME = "os.name";
|
private static final String OS_NAME = "os.name";
|
||||||
private static final String CTBREC = "ctbrec";
|
private static final String CTBREC = "ctbrec";
|
||||||
|
@ -100,7 +96,7 @@ public class OS {
|
||||||
default:
|
default:
|
||||||
throw new UnsupportedOperatingSystemException(System.getProperty(OS_NAME));
|
throw new UnsupportedOperatingSystemException(System.getProperty(OS_NAME));
|
||||||
}
|
}
|
||||||
LOG.debug("Browser command: {}", Arrays.toString(cmd));
|
log.debug("Browser command: {}", Arrays.toString(cmd));
|
||||||
return cmd;
|
return cmd;
|
||||||
} catch (URISyntaxException e) {
|
} catch (URISyntaxException e) {
|
||||||
throw new ForkProcessException(e);
|
throw new ForkProcessException(e);
|
||||||
|
@ -135,7 +131,7 @@ public class OS {
|
||||||
default:
|
default:
|
||||||
throw new UnsupportedOperatingSystemException(System.getProperty(OS_NAME));
|
throw new UnsupportedOperatingSystemException(System.getProperty(OS_NAME));
|
||||||
}
|
}
|
||||||
LOG.debug("FFmpeg command: {}", Arrays.toString(cmd));
|
log.debug("FFmpeg command: {}", Arrays.toString(cmd));
|
||||||
return cmd;
|
return cmd;
|
||||||
} catch (URISyntaxException e) {
|
} catch (URISyntaxException e) {
|
||||||
throw new ForkProcessException(e);
|
throw new ForkProcessException(e);
|
||||||
|
|
|
@ -1,18 +1,16 @@
|
||||||
package ctbrec.event;
|
package ctbrec.event;
|
||||||
|
|
||||||
|
|
||||||
|
import lombok.extern.slf4j.Slf4j;
|
||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
import java.util.UUID;
|
import java.util.UUID;
|
||||||
import java.util.concurrent.Executors;
|
import java.util.concurrent.Executors;
|
||||||
|
|
||||||
import org.slf4j.Logger;
|
|
||||||
import org.slf4j.LoggerFactory;
|
|
||||||
|
|
||||||
import com.google.common.eventbus.AsyncEventBus;
|
import com.google.common.eventbus.AsyncEventBus;
|
||||||
import com.google.common.eventbus.EventBus;
|
import com.google.common.eventbus.EventBus;
|
||||||
|
|
||||||
|
@Slf4j
|
||||||
public class EventBusHolder {
|
public class EventBusHolder {
|
||||||
private static final Logger LOG = LoggerFactory.getLogger(EventBusHolder.class);
|
|
||||||
private static Map<String, EventHandler> handlers = new HashMap<>();
|
private static Map<String, EventHandler> handlers = new HashMap<>();
|
||||||
|
|
||||||
private EventBusHolder() {}
|
private EventBusHolder() {}
|
||||||
|
@ -27,11 +25,11 @@ public class EventBusHolder {
|
||||||
|
|
||||||
public static void register(EventHandler handler) {
|
public static void register(EventHandler handler) {
|
||||||
if(handlers.containsKey(handler.getId())) {
|
if(handlers.containsKey(handler.getId())) {
|
||||||
LOG.warn("EventHandler with ID {} is already registered", handler.getId());
|
log.warn("EventHandler with ID {} is already registered", handler.getId());
|
||||||
} else {
|
} else {
|
||||||
BUS.register(handler);
|
BUS.register(handler);
|
||||||
handlers.put(handler.getId(), handler);
|
handlers.put(handler.getId(), handler);
|
||||||
LOG.debug("EventHandler with ID {} has been added", handler.getId());
|
log.debug("EventHandler with ID {} has been added", handler.getId());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -40,7 +38,7 @@ public class EventBusHolder {
|
||||||
if(handler != null) {
|
if(handler != null) {
|
||||||
BUS.unregister(handler);
|
BUS.unregister(handler);
|
||||||
handlers.remove(id);
|
handlers.remove(id);
|
||||||
LOG.debug("EventHandler with ID {} has been removed", id);
|
log.debug("EventHandler with ID {} has been removed", id);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,14 +1,13 @@
|
||||||
package ctbrec.event;
|
package ctbrec.event;
|
||||||
|
|
||||||
|
|
||||||
|
import lombok.extern.slf4j.Slf4j;
|
||||||
import com.google.common.eventbus.Subscribe;
|
import com.google.common.eventbus.Subscribe;
|
||||||
import ctbrec.Config;
|
import ctbrec.Config;
|
||||||
import ctbrec.event.Event.Type;
|
import ctbrec.event.Event.Type;
|
||||||
import ctbrec.event.EventHandlerConfiguration.ActionConfiguration;
|
import ctbrec.event.EventHandlerConfiguration.ActionConfiguration;
|
||||||
import ctbrec.event.EventHandlerConfiguration.PredicateConfiguration;
|
import ctbrec.event.EventHandlerConfiguration.PredicateConfiguration;
|
||||||
import lombok.EqualsAndHashCode;
|
import lombok.EqualsAndHashCode;
|
||||||
import org.slf4j.Logger;
|
|
||||||
import org.slf4j.LoggerFactory;
|
|
||||||
|
|
||||||
import java.lang.reflect.InvocationTargetException;
|
import java.lang.reflect.InvocationTargetException;
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.Collections;
|
import java.util.Collections;
|
||||||
|
@ -17,9 +16,8 @@ import java.util.function.Consumer;
|
||||||
import java.util.function.Predicate;
|
import java.util.function.Predicate;
|
||||||
|
|
||||||
@EqualsAndHashCode(of = "id")
|
@EqualsAndHashCode(of = "id")
|
||||||
|
@Slf4j
|
||||||
public class EventHandler {
|
public class EventHandler {
|
||||||
private static final Logger LOG = LoggerFactory.getLogger(EventHandler.class);
|
|
||||||
|
|
||||||
private List<EventPredicate> predicates = new ArrayList<>();
|
private List<EventPredicate> predicates = new ArrayList<>();
|
||||||
private final List<Action> actions;
|
private final List<Action> actions;
|
||||||
private String id;
|
private String id;
|
||||||
|
@ -48,7 +46,7 @@ public class EventHandler {
|
||||||
@Subscribe
|
@Subscribe
|
||||||
public void reactToEvent(Event evt) {
|
public void reactToEvent(Event evt) {
|
||||||
if (Config.getInstance().getSettings().eventsSuspended) {
|
if (Config.getInstance().getSettings().eventsSuspended) {
|
||||||
LOG.debug("Events are suspended. Ignoring {}", evt);
|
log.debug("Events are suspended. Ignoring {}", evt);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -65,7 +63,7 @@ public class EventHandler {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
LOG.error("Error while processing event", e);
|
log.error("Error while processing event", e);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -77,7 +75,7 @@ public class EventHandler {
|
||||||
@SuppressWarnings("unchecked")
|
@SuppressWarnings("unchecked")
|
||||||
Class<EventPredicate> cls = (Class<EventPredicate>) Class.forName(pc.getType());
|
Class<EventPredicate> cls = (Class<EventPredicate>) Class.forName(pc.getType());
|
||||||
if (cls == null) {
|
if (cls == null) {
|
||||||
LOG.warn("Ignoring unknown action {}", cls);
|
log.warn("Ignoring unknown action {}", cls);
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
EventPredicate predicate = cls.getDeclaredConstructor().newInstance();
|
EventPredicate predicate = cls.getDeclaredConstructor().newInstance();
|
||||||
|
@ -85,7 +83,7 @@ public class EventHandler {
|
||||||
predicateList.add(predicate);
|
predicateList.add(predicate);
|
||||||
} catch (InstantiationException | IllegalAccessException | ClassNotFoundException | IllegalArgumentException | InvocationTargetException |
|
} catch (InstantiationException | IllegalAccessException | ClassNotFoundException | IllegalArgumentException | InvocationTargetException |
|
||||||
NoSuchMethodException | SecurityException e) {
|
NoSuchMethodException | SecurityException e) {
|
||||||
LOG.warn("Error while creating action {} {}", pc.getType(), pc.getConfiguration(), e);
|
log.warn("Error while creating action {} {}", pc.getType(), pc.getConfiguration(), e);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return predicateList;
|
return predicateList;
|
||||||
|
@ -98,14 +96,14 @@ public class EventHandler {
|
||||||
@SuppressWarnings("unchecked")
|
@SuppressWarnings("unchecked")
|
||||||
Class<Action> cls = (Class<Action>) Class.forName(ac.getType());
|
Class<Action> cls = (Class<Action>) Class.forName(ac.getType());
|
||||||
if (cls == null) {
|
if (cls == null) {
|
||||||
LOG.warn("Ignoring unknown action {}", cls);
|
log.warn("Ignoring unknown action {}", cls);
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
Action action = cls.getDeclaredConstructor().newInstance();
|
Action action = cls.getDeclaredConstructor().newInstance();
|
||||||
action.configure(ac);
|
action.configure(ac);
|
||||||
actionList.add(action);
|
actionList.add(action);
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
LOG.warn("Error while creating action {} {}", ac.getType(), ac.getConfiguration(), e);
|
log.warn("Error while creating action {} {}", ac.getType(), ac.getConfiguration(), e);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return actionList;
|
return actionList;
|
||||||
|
|
|
@ -1,18 +1,14 @@
|
||||||
package ctbrec.event;
|
package ctbrec.event;
|
||||||
|
|
||||||
|
|
||||||
|
import lombok.extern.slf4j.Slf4j;
|
||||||
import java.util.Arrays;
|
import java.util.Arrays;
|
||||||
|
|
||||||
import org.slf4j.Logger;
|
|
||||||
import org.slf4j.LoggerFactory;
|
|
||||||
|
|
||||||
import ctbrec.OS;
|
import ctbrec.OS;
|
||||||
import ctbrec.event.EventHandlerConfiguration.ActionConfiguration;
|
import ctbrec.event.EventHandlerConfiguration.ActionConfiguration;
|
||||||
import ctbrec.io.StreamRedirector;
|
import ctbrec.io.StreamRedirector;
|
||||||
|
|
||||||
|
@Slf4j
|
||||||
public class ExecuteProgram extends Action {
|
public class ExecuteProgram extends Action {
|
||||||
|
|
||||||
private static final transient Logger LOG = LoggerFactory.getLogger(ExecuteProgram.class);
|
|
||||||
|
|
||||||
private String executable;
|
private String executable;
|
||||||
|
|
||||||
public ExecuteProgram() {
|
public ExecuteProgram() {
|
||||||
|
@ -33,7 +29,7 @@ public class ExecuteProgram extends Action {
|
||||||
String[] cmd = new String[args.length+1];
|
String[] cmd = new String[args.length+1];
|
||||||
cmd[0] = executable;
|
cmd[0] = executable;
|
||||||
System.arraycopy(args, 0, cmd, 1, args.length);
|
System.arraycopy(args, 0, cmd, 1, args.length);
|
||||||
LOG.debug("Executing {}", Arrays.toString(cmd));
|
log.debug("Executing {}", Arrays.toString(cmd));
|
||||||
process = rt.exec(cmd, OS.getEnvironment());
|
process = rt.exec(cmd, OS.getEnvironment());
|
||||||
|
|
||||||
// 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,
|
||||||
|
@ -48,9 +44,9 @@ public class ExecuteProgram extends Action {
|
||||||
err.start();
|
err.start();
|
||||||
|
|
||||||
process.waitFor();
|
process.waitFor();
|
||||||
LOG.debug("Executing {} finished", executable);
|
log.debug("Executing {} finished", executable);
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
LOG.error("Error while executing {}", executable, e);
|
log.error("Error while executing {}", executable, e);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1,5 +1,7 @@
|
||||||
package ctbrec.io;
|
package ctbrec.io;
|
||||||
|
|
||||||
|
|
||||||
|
import lombok.extern.slf4j.Slf4j;
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.Collection;
|
import java.util.Collection;
|
||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
|
@ -10,18 +12,12 @@ import java.util.Map.Entry;
|
||||||
import java.util.NoSuchElementException;
|
import java.util.NoSuchElementException;
|
||||||
import java.util.Objects;
|
import java.util.Objects;
|
||||||
import java.util.Optional;
|
import java.util.Optional;
|
||||||
|
|
||||||
import org.slf4j.Logger;
|
|
||||||
import org.slf4j.LoggerFactory;
|
|
||||||
|
|
||||||
import okhttp3.Cookie;
|
import okhttp3.Cookie;
|
||||||
import okhttp3.CookieJar;
|
import okhttp3.CookieJar;
|
||||||
import okhttp3.HttpUrl;
|
import okhttp3.HttpUrl;
|
||||||
|
|
||||||
|
@Slf4j
|
||||||
public class CookieJarImpl implements CookieJar {
|
public class CookieJarImpl implements CookieJar {
|
||||||
|
|
||||||
private static final Logger LOG = LoggerFactory.getLogger(CookieJarImpl.class);
|
|
||||||
|
|
||||||
private final HashMap<String, List<Cookie>> cookieStore = new HashMap<>();
|
private final HashMap<String, List<Cookie>> cookieStore = new HashMap<>();
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -35,7 +31,7 @@ public class CookieJarImpl implements CookieJar {
|
||||||
String name = oldCookie.name();
|
String name = oldCookie.name();
|
||||||
for (Cookie newCookie : cookies) {
|
for (Cookie newCookie : cookies) {
|
||||||
if(newCookie.name().equalsIgnoreCase(name)) {
|
if(newCookie.name().equalsIgnoreCase(name)) {
|
||||||
LOG.trace("Replacing cookie {} {} -> {} [{}]", oldCookie.name(), oldCookie.value(), newCookie.value(), oldCookie.domain());
|
log.trace("Replacing cookie {} {} -> {} [{}]", oldCookie.name(), oldCookie.value(), newCookie.value(), oldCookie.domain());
|
||||||
iterator.remove();
|
iterator.remove();
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
@ -43,17 +39,17 @@ public class CookieJarImpl implements CookieJar {
|
||||||
}
|
}
|
||||||
cookiesForUrl.addAll(cookies);
|
cookiesForUrl.addAll(cookies);
|
||||||
cookieStore.put(host, cookiesForUrl);
|
cookieStore.put(host, cookiesForUrl);
|
||||||
LOG.trace("Adding cookie: {} for {}", cookiesForUrl, host);
|
log.trace("Adding cookie: {} for {}", cookiesForUrl, host);
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
cookieStore.put(host, cookies);
|
cookieStore.put(host, cookies);
|
||||||
LOG.trace("Storing cookie: {} for {}", cookies, host);
|
log.trace("Storing cookie: {} for {}", cookies, host);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public List<Cookie> loadForRequest(HttpUrl url) {
|
public List<Cookie> loadForRequest(HttpUrl url) {
|
||||||
LOG.debug("Loading cookies for {}", url);
|
log.debug("Loading cookies for {}", url);
|
||||||
String host = getDomain(url);
|
String host = getDomain(url);
|
||||||
List<Cookie> cookies = cookieStore.get(host);
|
List<Cookie> cookies = cookieStore.get(host);
|
||||||
List<Cookie> result = new ArrayList<>();
|
List<Cookie> result = new ArrayList<>();
|
||||||
|
@ -62,8 +58,8 @@ public class CookieJarImpl implements CookieJar {
|
||||||
addCookieToResult(url, result, cookie);
|
addCookieToResult(url, result, cookie);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
LOG.trace("Cookies for {}", url);
|
log.trace("Cookies for {}", url);
|
||||||
Optional.ofNullable(result).ifPresent(cookiez -> cookiez.forEach(c -> LOG.trace("Cookies for {}: {}", url, c)));
|
Optional.ofNullable(result).ifPresent(cookiez -> cookiez.forEach(c -> log.trace("Cookies for {}: {}", url, c)));
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -107,7 +103,7 @@ public class CookieJarImpl implements CookieJar {
|
||||||
Cookie cookie = iterator.next();
|
Cookie cookie = iterator.next();
|
||||||
if(Objects.equals(cookie.name(), name)) {
|
if(Objects.equals(cookie.name(), name)) {
|
||||||
iterator.remove();
|
iterator.remove();
|
||||||
LOG.debug("Removed cookie \"{}\" for {}", name, url);
|
log.debug("Removed cookie \"{}\" for {}", name, url);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,9 +1,8 @@
|
||||||
package ctbrec.io;
|
package ctbrec.io;
|
||||||
|
|
||||||
import ctbrec.Config;
|
|
||||||
import org.slf4j.Logger;
|
|
||||||
import org.slf4j.LoggerFactory;
|
|
||||||
|
|
||||||
|
import lombok.extern.slf4j.Slf4j;
|
||||||
|
import ctbrec.Config;
|
||||||
import java.io.File;
|
import java.io.File;
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.io.OutputStream;
|
import java.io.OutputStream;
|
||||||
|
@ -11,10 +10,8 @@ import java.nio.file.*;
|
||||||
import java.nio.file.attribute.BasicFileAttributes;
|
import java.nio.file.attribute.BasicFileAttributes;
|
||||||
import java.util.EnumSet;
|
import java.util.EnumSet;
|
||||||
|
|
||||||
|
@Slf4j
|
||||||
public class IoUtils {
|
public class IoUtils {
|
||||||
|
|
||||||
private static final Logger LOG = LoggerFactory.getLogger(IoUtils.class);
|
|
||||||
|
|
||||||
private IoUtils() {
|
private IoUtils() {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -25,7 +22,7 @@ public class IoUtils {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if (parent.exists()) {
|
if (parent.exists()) {
|
||||||
LOG.debug("Deleting empty directory {}", parent.getAbsolutePath());
|
log.debug("Deleting empty directory {}", parent.getAbsolutePath());
|
||||||
Files.delete(parent.toPath());
|
Files.delete(parent.toPath());
|
||||||
}
|
}
|
||||||
parent = parent.getParentFile();
|
parent = parent.getParentFile();
|
||||||
|
@ -44,11 +41,11 @@ public class IoUtils {
|
||||||
deleteDirectory(file);
|
deleteDirectory(file);
|
||||||
} else {
|
} else {
|
||||||
try {
|
try {
|
||||||
LOG.trace("Deleting {}", file.getAbsolutePath());
|
log.trace("Deleting {}", file.getAbsolutePath());
|
||||||
Files.delete(file.toPath());
|
Files.delete(file.toPath());
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
deletedAllFiles = false;
|
deletedAllFiles = false;
|
||||||
LOG.debug("Couldn't delete {}", file, e);
|
log.debug("Couldn't delete {}", file, e);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -78,7 +75,7 @@ public class IoUtils {
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
} catch (IOException e) {
|
} catch (IOException e) {
|
||||||
LOG.error("Couldn't determine size of directory {}", dir, e);
|
log.error("Couldn't determine size of directory {}", dir, e);
|
||||||
}
|
}
|
||||||
return size[0];
|
return size[0];
|
||||||
}
|
}
|
||||||
|
@ -88,7 +85,7 @@ public class IoUtils {
|
||||||
try {
|
try {
|
||||||
outputStream.close();
|
outputStream.close();
|
||||||
} catch (IOException e) {
|
} catch (IOException e) {
|
||||||
LOG.error(errorMsg, e);
|
log.error(errorMsg, e);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,18 +1,15 @@
|
||||||
package ctbrec.io;
|
package ctbrec.io;
|
||||||
|
|
||||||
|
|
||||||
|
import lombok.extern.slf4j.Slf4j;
|
||||||
import static java.util.concurrent.TimeUnit.*;
|
import static java.util.concurrent.TimeUnit.*;
|
||||||
|
|
||||||
import java.io.InputStream;
|
import java.io.InputStream;
|
||||||
import java.io.OutputStream;
|
import java.io.OutputStream;
|
||||||
import java.util.Objects;
|
import java.util.Objects;
|
||||||
import java.util.concurrent.ScheduledExecutorService;
|
import java.util.concurrent.ScheduledExecutorService;
|
||||||
|
@Slf4j
|
||||||
import org.slf4j.Logger;
|
|
||||||
import org.slf4j.LoggerFactory;
|
|
||||||
|
|
||||||
public class ProcessStreamRedirector implements Runnable {
|
public class ProcessStreamRedirector implements Runnable {
|
||||||
private static final Logger LOG = LoggerFactory.getLogger(ProcessStreamRedirector.class);
|
|
||||||
|
|
||||||
private InputStream in;
|
private InputStream in;
|
||||||
private OutputStream out;
|
private OutputStream out;
|
||||||
private boolean keepGoing = true;
|
private boolean keepGoing = true;
|
||||||
|
@ -39,7 +36,7 @@ public class ProcessStreamRedirector implements Runnable {
|
||||||
}
|
}
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
if (!Objects.equals(e.getMessage(), "Stream Closed")) {
|
if (!Objects.equals(e.getMessage(), "Stream Closed")) {
|
||||||
LOG.debug("Error while reading from process output stream: {}", e.getLocalizedMessage(), e);
|
log.debug("Error while reading from process output stream: {}", e.getLocalizedMessage(), e);
|
||||||
}
|
}
|
||||||
keepGoing = false;
|
keepGoing = false;
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,14 +1,11 @@
|
||||||
package ctbrec.io;
|
package ctbrec.io;
|
||||||
|
|
||||||
|
|
||||||
|
import lombok.extern.slf4j.Slf4j;
|
||||||
import java.io.InputStream;
|
import java.io.InputStream;
|
||||||
import java.io.OutputStream;
|
import java.io.OutputStream;
|
||||||
|
@Slf4j
|
||||||
import org.slf4j.Logger;
|
|
||||||
import org.slf4j.LoggerFactory;
|
|
||||||
|
|
||||||
public class StreamRedirector implements Runnable {
|
public class StreamRedirector implements Runnable {
|
||||||
private static final Logger LOG = LoggerFactory.getLogger(StreamRedirector.class);
|
|
||||||
|
|
||||||
private InputStream in;
|
private InputStream in;
|
||||||
private OutputStream out;
|
private OutputStream out;
|
||||||
|
|
||||||
|
@ -26,9 +23,9 @@ public class StreamRedirector implements Runnable {
|
||||||
while(in != null && (length = in.read(buffer)) >= 0) {
|
while(in != null && (length = in.read(buffer)) >= 0) {
|
||||||
out.write(buffer, 0, length);
|
out.write(buffer, 0, length);
|
||||||
}
|
}
|
||||||
LOG.trace("Stream redirect thread ended");
|
log.trace("Stream redirect thread ended");
|
||||||
} catch(Exception e) {
|
} catch(Exception e) {
|
||||||
LOG.warn("Couldn't redirect stream: {}", e.getLocalizedMessage());
|
log.warn("Couldn't redirect stream: {}", e.getLocalizedMessage());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,5 +1,7 @@
|
||||||
package ctbrec.recorder;
|
package ctbrec.recorder;
|
||||||
|
|
||||||
|
|
||||||
|
import lombok.extern.slf4j.Slf4j;
|
||||||
import ctbrec.Config;
|
import ctbrec.Config;
|
||||||
import ctbrec.Model;
|
import ctbrec.Model;
|
||||||
import ctbrec.event.EventBusHolder;
|
import ctbrec.event.EventBusHolder;
|
||||||
|
@ -7,9 +9,6 @@ import ctbrec.event.ModelIsOnlineEvent;
|
||||||
import ctbrec.event.ModelStateChangedEvent;
|
import ctbrec.event.ModelStateChangedEvent;
|
||||||
import ctbrec.io.HttpException;
|
import ctbrec.io.HttpException;
|
||||||
import ctbrec.sites.chaturbate.ChaturbateModel;
|
import ctbrec.sites.chaturbate.ChaturbateModel;
|
||||||
import org.slf4j.Logger;
|
|
||||||
import org.slf4j.LoggerFactory;
|
|
||||||
|
|
||||||
import java.io.InterruptedIOException;
|
import java.io.InterruptedIOException;
|
||||||
import java.net.SocketTimeoutException;
|
import java.net.SocketTimeoutException;
|
||||||
import java.time.Duration;
|
import java.time.Duration;
|
||||||
|
@ -23,8 +22,8 @@ import java.util.concurrent.*;
|
||||||
import static ctbrec.Model.State.OFFLINE;
|
import static ctbrec.Model.State.OFFLINE;
|
||||||
import static ctbrec.Model.State.UNCHECKED;
|
import static ctbrec.Model.State.UNCHECKED;
|
||||||
|
|
||||||
|
@Slf4j
|
||||||
public class OnlineMonitor extends Thread {
|
public class OnlineMonitor extends Thread {
|
||||||
private static final Logger LOG = LoggerFactory.getLogger(OnlineMonitor.class);
|
|
||||||
private static final boolean IGNORE_CACHE = true;
|
private static final boolean IGNORE_CACHE = true;
|
||||||
|
|
||||||
private volatile boolean running = false;
|
private volatile boolean running = false;
|
||||||
|
@ -59,7 +58,7 @@ public class OnlineMonitor extends Thread {
|
||||||
Duration timeCheckTook = Duration.between(begin, end);
|
Duration timeCheckTook = Duration.between(begin, end);
|
||||||
suspendUntilNextIteration(models, timeCheckTook);
|
suspendUntilNextIteration(models, timeCheckTook);
|
||||||
}
|
}
|
||||||
LOG.debug("{} terminated", getName());
|
log.debug("{} terminated", getName());
|
||||||
}
|
}
|
||||||
|
|
||||||
private void removeDeletedModels(List<Model> models) {
|
private void removeDeletedModels(List<Model> models) {
|
||||||
|
@ -90,12 +89,12 @@ public class OnlineMonitor extends Thread {
|
||||||
try {
|
try {
|
||||||
future.get(timeout.toMillis(), TimeUnit.MILLISECONDS);
|
future.get(timeout.toMillis(), TimeUnit.MILLISECONDS);
|
||||||
} catch (InterruptedException e) {
|
} catch (InterruptedException e) {
|
||||||
LOG.debug("Online check interrupted for model {}", future.getModel(), e);
|
log.debug("Online check interrupted for model {}", future.getModel(), e);
|
||||||
Thread.currentThread().interrupt();
|
Thread.currentThread().interrupt();
|
||||||
} catch (ExecutionException e) {
|
} catch (ExecutionException e) {
|
||||||
LOG.info("Error while checking online state for model {}", future.getModel(), e);
|
log.info("Error while checking online state for model {}", future.getModel(), e);
|
||||||
} catch (TimeoutException e) {
|
} catch (TimeoutException e) {
|
||||||
LOG.debug("Online check didn't finish after {}ms for model {}", timeout.toMillis(), future.getModel());
|
log.debug("Online check didn't finish after {}ms for model {}", timeout.toMillis(), future.getModel());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -130,19 +129,19 @@ public class OnlineMonitor extends Thread {
|
||||||
} else {
|
} else {
|
||||||
state = model.getOnlineState(false);
|
state = model.getOnlineState(false);
|
||||||
}
|
}
|
||||||
LOG.debug("Model online state: {} {}", model.getName(), state);
|
log.debug("Model online state: {} {}", model.getName(), state);
|
||||||
setModelStateNotified(model, state);
|
setModelStateNotified(model, state);
|
||||||
} catch (HttpException e) {
|
} catch (HttpException e) {
|
||||||
LOG.error("Couldn't check if model {} is online. HTTP Response: {} - {}", model.getName(), e.getResponseCode(), e.getResponseMessage());
|
log.error("Couldn't check if model {} is online. HTTP Response: {} - {}", model.getName(), e.getResponseCode(), e.getResponseMessage());
|
||||||
} catch (SocketTimeoutException e) {
|
} catch (SocketTimeoutException e) {
|
||||||
LOG.error("Couldn't check if model {} is online. Request timed out", model.getName());
|
log.error("Couldn't check if model {} is online. Request timed out", model.getName());
|
||||||
} catch (InterruptedException | InterruptedIOException e) {
|
} catch (InterruptedException | InterruptedIOException e) {
|
||||||
Thread.currentThread().interrupt();
|
Thread.currentThread().interrupt();
|
||||||
if (running) {
|
if (running) {
|
||||||
LOG.error("Couldn't check if model {} is online", model.getName(), e);
|
log.error("Couldn't check if model {} is online", model.getName(), e);
|
||||||
}
|
}
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
LOG.error("Couldn't check if model {} is online", model.getName(), e);
|
log.error("Couldn't check if model {} is online", model.getName(), e);
|
||||||
}
|
}
|
||||||
return model;
|
return model;
|
||||||
});
|
});
|
||||||
|
@ -150,18 +149,18 @@ public class OnlineMonitor extends Thread {
|
||||||
}
|
}
|
||||||
|
|
||||||
private void suspendUntilNextIteration(List<Model> models, Duration timeCheckTook) {
|
private void suspendUntilNextIteration(List<Model> models, Duration timeCheckTook) {
|
||||||
LOG.debug("Online check for {} models took {} seconds", models.size(), timeCheckTook.getSeconds());
|
log.debug("Online check for {} models took {} seconds", models.size(), timeCheckTook.getSeconds());
|
||||||
long sleepTime = config.getSettings().onlineCheckIntervalInSecs;
|
long sleepTime = config.getSettings().onlineCheckIntervalInSecs;
|
||||||
if (timeCheckTook.getSeconds() < sleepTime) {
|
if (timeCheckTook.getSeconds() < sleepTime) {
|
||||||
try {
|
try {
|
||||||
if (running) {
|
if (running) {
|
||||||
long millis = TimeUnit.SECONDS.toMillis(sleepTime - timeCheckTook.getSeconds());
|
long millis = TimeUnit.SECONDS.toMillis(sleepTime - timeCheckTook.getSeconds());
|
||||||
LOG.trace("Sleeping {}ms", millis);
|
log.trace("Sleeping {}ms", millis);
|
||||||
Thread.sleep(millis);
|
Thread.sleep(millis);
|
||||||
}
|
}
|
||||||
} catch (InterruptedException e) {
|
} catch (InterruptedException e) {
|
||||||
Thread.currentThread().interrupt();
|
Thread.currentThread().interrupt();
|
||||||
LOG.trace("Sleep interrupted");
|
log.trace("Sleep interrupted");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,13 +1,12 @@
|
||||||
package ctbrec.recorder;
|
package ctbrec.recorder;
|
||||||
|
|
||||||
|
|
||||||
|
import lombok.extern.slf4j.Slf4j;
|
||||||
import ctbrec.Config;
|
import ctbrec.Config;
|
||||||
import ctbrec.Model;
|
import ctbrec.Model;
|
||||||
import ctbrec.ModelGroup;
|
import ctbrec.ModelGroup;
|
||||||
import ctbrec.Recording;
|
import ctbrec.Recording;
|
||||||
import ctbrec.recorder.download.RecordingProcess;
|
import ctbrec.recorder.download.RecordingProcess;
|
||||||
import org.slf4j.Logger;
|
|
||||||
import org.slf4j.LoggerFactory;
|
|
||||||
|
|
||||||
import com.google.common.collect.Comparators;
|
import com.google.common.collect.Comparators;
|
||||||
|
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
|
@ -21,9 +20,8 @@ import java.util.Optional;
|
||||||
import java.util.concurrent.ExecutionException;
|
import java.util.concurrent.ExecutionException;
|
||||||
import java.util.concurrent.TimeUnit;
|
import java.util.concurrent.TimeUnit;
|
||||||
|
|
||||||
|
@Slf4j
|
||||||
public class RecordingPreconditions {
|
public class RecordingPreconditions {
|
||||||
|
|
||||||
private static final Logger LOG = LoggerFactory.getLogger(RecordingPreconditions.class);
|
|
||||||
public static final boolean IGNORE_CACHE = true;
|
public static final boolean IGNORE_CACHE = true;
|
||||||
|
|
||||||
private final Config config;
|
private final Config config;
|
||||||
|
@ -37,7 +35,7 @@ public class RecordingPreconditions {
|
||||||
}
|
}
|
||||||
|
|
||||||
void check(Model model) throws IOException, InvalidKeyException, NoSuchAlgorithmException, ExecutionException {
|
void check(Model model) throws IOException, InvalidKeyException, NoSuchAlgorithmException, ExecutionException {
|
||||||
LOG.debug("Checking preconditions for model {}", model);
|
log.debug("Checking preconditions for model {}", model);
|
||||||
ensureRecorderIsActive();
|
ensureRecorderIsActive();
|
||||||
ensureNotInTimeoutPeriod();
|
ensureNotInTimeoutPeriod();
|
||||||
ensureModelIsNotSuspended(model);
|
ensureModelIsNotSuspended(model);
|
||||||
|
@ -98,7 +96,7 @@ public class RecordingPreconditions {
|
||||||
if (!downloadSlotAvailable()) {
|
if (!downloadSlotAvailable()) {
|
||||||
long now = System.currentTimeMillis();
|
long now = System.currentTimeMillis();
|
||||||
if ((now - lastPreconditionMessage) > TimeUnit.MINUTES.toMillis(1)) {
|
if ((now - lastPreconditionMessage) > TimeUnit.MINUTES.toMillis(1)) {
|
||||||
LOG.info("The number of downloads is maxed out");
|
log.info("The number of downloads is maxed out");
|
||||||
lastPreconditionMessage = now;
|
lastPreconditionMessage = now;
|
||||||
}
|
}
|
||||||
// check, if we can stop a recording for a model with lower priority
|
// check, if we can stop a recording for a model with lower priority
|
||||||
|
@ -106,7 +104,7 @@ public class RecordingPreconditions {
|
||||||
if (lowerPrioRecordingProcess.isPresent()) {
|
if (lowerPrioRecordingProcess.isPresent()) {
|
||||||
RecordingProcess download = lowerPrioRecordingProcess.get().getRecordingProcess();
|
RecordingProcess download = lowerPrioRecordingProcess.get().getRecordingProcess();
|
||||||
Model lowerPrioModel = download.getModel();
|
Model lowerPrioModel = download.getModel();
|
||||||
LOG.info("Stopping recording for {}. Prio {} < {}", lowerPrioModel.getName(), lowerPrioModel.getPriority(), model.getPriority());
|
log.info("Stopping recording for {}. Prio {} < {}", lowerPrioModel.getName(), lowerPrioModel.getPriority(), model.getPriority());
|
||||||
recorder.stopRecordingProcess(lowerPrioRecordingProcess.get());
|
recorder.stopRecordingProcess(lowerPrioRecordingProcess.get());
|
||||||
} else {
|
} else {
|
||||||
throw new PreconditionNotMetException("Other models have higher prio, not starting recording for " + model.getName());
|
throw new PreconditionNotMetException("Other models have higher prio, not starting recording for " + model.getName());
|
||||||
|
@ -186,7 +184,7 @@ public class RecordingPreconditions {
|
||||||
throw new PreconditionNotMetException(otherModel.get() + "'s online state has not been checked yet");
|
throw new PreconditionNotMetException(otherModel.get() + "'s online state has not been checked yet");
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
LOG.warn("Model for url {} was not found", modelUrl);
|
log.warn("Model for url {} was not found", modelUrl);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -255,7 +253,7 @@ public class RecordingPreconditions {
|
||||||
} catch (PreconditionNotMetException e) {
|
} catch (PreconditionNotMetException e) {
|
||||||
// precondition for other model not met
|
// precondition for other model not met
|
||||||
} catch (IOException e) {
|
} catch (IOException e) {
|
||||||
LOG.warn("Couldn't check if preconditions of other model from group are met. Assuming she's offline", e);
|
log.warn("Couldn't check if preconditions of other model from group are met. Assuming she's offline", e);
|
||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,6 +1,8 @@
|
||||||
package ctbrec.recorder;
|
package ctbrec.recorder;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
import lombok.extern.slf4j.Slf4j;
|
||||||
import com.fasterxml.jackson.databind.ObjectMapper;
|
import com.fasterxml.jackson.databind.ObjectMapper;
|
||||||
import ctbrec.*;
|
import ctbrec.*;
|
||||||
import ctbrec.event.EventBusHolder;
|
import ctbrec.event.EventBusHolder;
|
||||||
|
@ -24,9 +26,6 @@ import okhttp3.RequestBody;
|
||||||
import okhttp3.Response;
|
import okhttp3.Response;
|
||||||
import org.json.JSONObject;
|
import org.json.JSONObject;
|
||||||
import org.mapstruct.factory.Mappers;
|
import org.mapstruct.factory.Mappers;
|
||||||
import org.slf4j.Logger;
|
|
||||||
import org.slf4j.LoggerFactory;
|
|
||||||
|
|
||||||
import java.io.File;
|
import java.io.File;
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.security.InvalidKeyException;
|
import java.security.InvalidKeyException;
|
||||||
|
@ -37,13 +36,11 @@ import java.util.*;
|
||||||
import java.util.concurrent.locks.ReentrantLock;
|
import java.util.concurrent.locks.ReentrantLock;
|
||||||
import java.util.stream.Collectors;
|
import java.util.stream.Collectors;
|
||||||
|
|
||||||
|
@Slf4j
|
||||||
public class RemoteRecorder implements Recorder {
|
public class RemoteRecorder implements Recorder {
|
||||||
|
|
||||||
private static final String SUCCESS = "success";
|
private static final String SUCCESS = "success";
|
||||||
private static final String COULDNT_SEND_REQUEST_SERVER_HTTP_STATUS = "Couldn't send request to server. Response {} - {}";
|
private static final String COULDNT_SEND_REQUEST_SERVER_HTTP_STATUS = "Couldn't send request to server. Response {} - {}";
|
||||||
|
|
||||||
private static final Logger LOG = LoggerFactory.getLogger(RemoteRecorder.class);
|
|
||||||
|
|
||||||
public static final MediaType JSON = MediaType.parse("application/json; charset=utf-8");
|
public static final MediaType JSON = MediaType.parse("application/json; charset=utf-8");
|
||||||
private static final String LOG_MSG_SENDING_REQUERST = "Sending request to recording server: {}";
|
private static final String LOG_MSG_SENDING_REQUERST = "Sending request to recording server: {}";
|
||||||
|
|
||||||
|
@ -79,10 +76,10 @@ public class RemoteRecorder implements Recorder {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void addModel(Model model) throws IOException, InvalidKeyException, NoSuchAlgorithmException {
|
public void addModel(Model model) throws IOException, InvalidKeyException, NoSuchAlgorithmException {
|
||||||
LOG.trace("Model marked: {}", model.isMarkedForLaterRecording());
|
log.trace("Model marked: {}", model.isMarkedForLaterRecording());
|
||||||
LOG.trace("Model paused: {}", model.isSuspended());
|
log.trace("Model paused: {}", model.isSuspended());
|
||||||
LOG.trace("Model until: {}", model.getRecordUntil().equals(Instant.ofEpochMilli(Model.RECORD_INDEFINITELY)) ? "no limit" : model.getRecordUntil());
|
log.trace("Model until: {}", model.getRecordUntil().equals(Instant.ofEpochMilli(Model.RECORD_INDEFINITELY)) ? "no limit" : model.getRecordUntil());
|
||||||
LOG.trace("Model after: {}", model.getRecordUntilSubsequentAction());
|
log.trace("Model after: {}", model.getRecordUntilSubsequentAction());
|
||||||
sendRequest("start", model);
|
sendRequest("start", model);
|
||||||
findModel(model).ifPresent(cachedModel -> {
|
findModel(model).ifPresent(cachedModel -> {
|
||||||
cachedModel.setSuspended(model.isSuspended());
|
cachedModel.setSuspended(model.isSuspended());
|
||||||
|
@ -107,7 +104,7 @@ public class RemoteRecorder implements Recorder {
|
||||||
|
|
||||||
private Optional<String> sendRequest(String action) throws IOException, InvalidKeyException, NoSuchAlgorithmException {
|
private Optional<String> sendRequest(String action) throws IOException, InvalidKeyException, NoSuchAlgorithmException {
|
||||||
String msg = "{\"action\": \"" + action + "\"}";
|
String msg = "{\"action\": \"" + action + "\"}";
|
||||||
LOG.trace(LOG_MSG_SENDING_REQUERST, msg);
|
log.trace(LOG_MSG_SENDING_REQUERST, msg);
|
||||||
RequestBody requestBody = RequestBody.Companion.create(msg, JSON);
|
RequestBody requestBody = RequestBody.Companion.create(msg, JSON);
|
||||||
Request.Builder builder = new Request.Builder().url(getRecordingEndpoint()).post(requestBody);
|
Request.Builder builder = new Request.Builder().url(getRecordingEndpoint()).post(requestBody);
|
||||||
addHmacIfNeeded(msg, builder);
|
addHmacIfNeeded(msg, builder);
|
||||||
|
@ -117,7 +114,7 @@ public class RemoteRecorder implements Recorder {
|
||||||
if (response.isSuccessful()) {
|
if (response.isSuccessful()) {
|
||||||
return Optional.of(responseBody);
|
return Optional.of(responseBody);
|
||||||
} else {
|
} else {
|
||||||
LOG.error(COULDNT_SEND_REQUEST_SERVER_HTTP_STATUS, response.code(), responseBody);
|
log.error(COULDNT_SEND_REQUEST_SERVER_HTTP_STATUS, response.code(), responseBody);
|
||||||
return Optional.empty();
|
return Optional.empty();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -125,7 +122,7 @@ public class RemoteRecorder implements Recorder {
|
||||||
|
|
||||||
private void sendRequest(String action, Model model) throws IOException, InvalidKeyException, NoSuchAlgorithmException {
|
private void sendRequest(String action, Model model) throws IOException, InvalidKeyException, NoSuchAlgorithmException {
|
||||||
String payload = mapper.writeValueAsString(new ModelRequest(action, model));
|
String payload = mapper.writeValueAsString(new ModelRequest(action, model));
|
||||||
LOG.trace(LOG_MSG_SENDING_REQUERST, payload);
|
log.trace(LOG_MSG_SENDING_REQUERST, payload);
|
||||||
RequestBody body = RequestBody.Companion.create(payload, JSON);
|
RequestBody body = RequestBody.Companion.create(payload, JSON);
|
||||||
Request.Builder builder = new Request.Builder().url(getRecordingEndpoint()).post(body);
|
Request.Builder builder = new Request.Builder().url(getRecordingEndpoint()).post(body);
|
||||||
addHmacIfNeeded(payload, builder);
|
addHmacIfNeeded(payload, builder);
|
||||||
|
@ -148,7 +145,7 @@ public class RemoteRecorder implements Recorder {
|
||||||
String msg = mapper.writeValueAsString(recReq);
|
String msg = mapper.writeValueAsString(recReq);
|
||||||
RequestBody body = RequestBody.Companion.create(msg, JSON);
|
RequestBody body = RequestBody.Companion.create(msg, JSON);
|
||||||
Request.Builder builder = new Request.Builder().url(getRecordingEndpoint()).post(body);
|
Request.Builder builder = new Request.Builder().url(getRecordingEndpoint()).post(body);
|
||||||
LOG.trace(LOG_MSG_SENDING_REQUERST, msg);
|
log.trace(LOG_MSG_SENDING_REQUERST, msg);
|
||||||
addHmacIfNeeded(msg, builder);
|
addHmacIfNeeded(msg, builder);
|
||||||
Request request = builder.build();
|
Request request = builder.build();
|
||||||
try (Response response = client.execute(request)) {
|
try (Response response = client.execute(request)) {
|
||||||
|
@ -170,7 +167,7 @@ public class RemoteRecorder implements Recorder {
|
||||||
|
|
||||||
private void sendRequest(String action, ModelGroup modelGroup) throws IOException, InvalidKeyException, NoSuchAlgorithmException {
|
private void sendRequest(String action, ModelGroup modelGroup) throws IOException, InvalidKeyException, NoSuchAlgorithmException {
|
||||||
String payload = mapper.writeValueAsString(new ModelGroupRequest(action, modelGroup));
|
String payload = mapper.writeValueAsString(new ModelGroupRequest(action, modelGroup));
|
||||||
LOG.trace(LOG_MSG_SENDING_REQUERST, payload);
|
log.trace(LOG_MSG_SENDING_REQUERST, payload);
|
||||||
RequestBody body = RequestBody.Companion.create(payload, JSON);
|
RequestBody body = RequestBody.Companion.create(payload, JSON);
|
||||||
Request.Builder builder = new Request.Builder().url(getRecordingEndpoint()).post(body);
|
Request.Builder builder = new Request.Builder().url(getRecordingEndpoint()).post(body);
|
||||||
addHmacIfNeeded(payload, builder);
|
addHmacIfNeeded(payload, builder);
|
||||||
|
@ -283,11 +280,11 @@ public class RemoteRecorder implements Recorder {
|
||||||
try {
|
try {
|
||||||
updateModelGroups(body);
|
updateModelGroups(body);
|
||||||
} catch (IOException e) {
|
} catch (IOException e) {
|
||||||
LOG.error("Error while loading model groups from server", e);
|
log.error("Error while loading model groups from server", e);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
} catch (IOException | InvalidKeyException | NoSuchAlgorithmException e) {
|
} catch (IOException | InvalidKeyException | NoSuchAlgorithmException e) {
|
||||||
LOG.error("Error while loading model groups from server", e);
|
log.error("Error while loading model groups from server", e);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -318,11 +315,11 @@ public class RemoteRecorder implements Recorder {
|
||||||
noSpaceLeftDetected = false;
|
noSpaceLeftDetected = false;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
LOG.error(COULDNT_SYNCHRONIZE_WITH_SERVER_HTTP_STATUS, response.code(), json);
|
log.error(COULDNT_SYNCHRONIZE_WITH_SERVER_HTTP_STATUS, response.code(), json);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} catch (IOException | InvalidKeyException | NoSuchAlgorithmException | IllegalStateException e) {
|
} catch (IOException | InvalidKeyException | NoSuchAlgorithmException | IllegalStateException e) {
|
||||||
LOG.error(COULDNT_SYNCHRONIZE_WITH_SERVER, e);
|
log.error(COULDNT_SYNCHRONIZE_WITH_SERVER, e);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -348,14 +345,14 @@ public class RemoteRecorder implements Recorder {
|
||||||
}
|
}
|
||||||
lastSync = Instant.now();
|
lastSync = Instant.now();
|
||||||
} else {
|
} else {
|
||||||
LOG.error(SERVER_RETURNED_ERROR, resp.status, resp.msg);
|
log.error(SERVER_RETURNED_ERROR, resp.status, resp.msg);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
LOG.error(COULDNT_SYNCHRONIZE_WITH_SERVER_HTTP_STATUS, response.code(), json);
|
log.error(COULDNT_SYNCHRONIZE_WITH_SERVER_HTTP_STATUS, response.code(), json);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} catch (IOException | InvalidKeyException | NoSuchAlgorithmException | IllegalStateException e) {
|
} catch (IOException | InvalidKeyException | NoSuchAlgorithmException | IllegalStateException e) {
|
||||||
LOG.error(COULDNT_SYNCHRONIZE_WITH_SERVER, e);
|
log.error(COULDNT_SYNCHRONIZE_WITH_SERVER, e);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -380,14 +377,14 @@ public class RemoteRecorder implements Recorder {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
LOG.error(SERVER_RETURNED_ERROR, resp.status, resp.msg);
|
log.error(SERVER_RETURNED_ERROR, resp.status, resp.msg);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
LOG.error(COULDNT_SYNCHRONIZE_WITH_SERVER_HTTP_STATUS, response.code(), json);
|
log.error(COULDNT_SYNCHRONIZE_WITH_SERVER_HTTP_STATUS, response.code(), json);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} catch (IOException | InvalidKeyException | NoSuchAlgorithmException | IllegalStateException e) {
|
} catch (IOException | InvalidKeyException | NoSuchAlgorithmException | IllegalStateException e) {
|
||||||
LOG.error(COULDNT_SYNCHRONIZE_WITH_SERVER, e);
|
log.error(COULDNT_SYNCHRONIZE_WITH_SERVER, e);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -448,14 +445,14 @@ public class RemoteRecorder implements Recorder {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
LOG.error(SERVER_RETURNED_ERROR, resp.status, resp.msg);
|
log.error(SERVER_RETURNED_ERROR, resp.status, resp.msg);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
LOG.error(COULDNT_SYNCHRONIZE_WITH_SERVER_HTTP_STATUS, response.code(), json);
|
log.error(COULDNT_SYNCHRONIZE_WITH_SERVER_HTTP_STATUS, response.code(), json);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} catch (IOException | InvalidKeyException | NoSuchAlgorithmException | IllegalStateException e) {
|
} catch (IOException | InvalidKeyException | NoSuchAlgorithmException | IllegalStateException e) {
|
||||||
LOG.error(COULDNT_SYNCHRONIZE_WITH_SERVER, e);
|
log.error(COULDNT_SYNCHRONIZE_WITH_SERVER, e);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -629,7 +626,7 @@ public class RemoteRecorder implements Recorder {
|
||||||
public void rerunPostProcessing(Recording recording) throws IOException, InvalidKeyException, NoSuchAlgorithmException {
|
public void rerunPostProcessing(Recording recording) throws IOException, InvalidKeyException, NoSuchAlgorithmException {
|
||||||
RecordingRequest recReq = new RecordingRequest("rerunPostProcessing", recording);
|
RecordingRequest recReq = new RecordingRequest("rerunPostProcessing", recording);
|
||||||
String msg = mapper.writeValueAsString(recReq);
|
String msg = mapper.writeValueAsString(recReq);
|
||||||
LOG.debug(msg);
|
log.debug(msg);
|
||||||
RequestBody body = RequestBody.Companion.create(msg, JSON);
|
RequestBody body = RequestBody.Companion.create(msg, JSON);
|
||||||
Request.Builder builder = new Request.Builder().url(getRecordingEndpoint()).post(body);
|
Request.Builder builder = new Request.Builder().url(getRecordingEndpoint()).post(body);
|
||||||
addHmacIfNeeded(msg, builder);
|
addHmacIfNeeded(msg, builder);
|
||||||
|
@ -706,7 +703,7 @@ public class RemoteRecorder implements Recorder {
|
||||||
@Override
|
@Override
|
||||||
public void markForLaterRecording(Model model, boolean mark) throws InvalidKeyException, NoSuchAlgorithmException, IOException {
|
public void markForLaterRecording(Model model, boolean mark) throws InvalidKeyException, NoSuchAlgorithmException, IOException {
|
||||||
model.setMarkedForLaterRecording(mark);
|
model.setMarkedForLaterRecording(mark);
|
||||||
LOG.info("Marking model {} {}", model, mark);
|
log.info("Marking model {} {}", model, mark);
|
||||||
if (mark) {
|
if (mark) {
|
||||||
sendRequest("markForLater", model);
|
sendRequest("markForLater", model);
|
||||||
} else {
|
} else {
|
||||||
|
|
|
@ -1,11 +1,10 @@
|
||||||
package ctbrec.recorder.download;
|
package ctbrec.recorder.download;
|
||||||
|
|
||||||
|
|
||||||
|
import lombok.extern.slf4j.Slf4j;
|
||||||
import ctbrec.OS;
|
import ctbrec.OS;
|
||||||
import ctbrec.io.DevNull;
|
import ctbrec.io.DevNull;
|
||||||
import ctbrec.io.StreamRedirector;
|
import ctbrec.io.StreamRedirector;
|
||||||
import org.slf4j.Logger;
|
|
||||||
import org.slf4j.LoggerFactory;
|
|
||||||
|
|
||||||
import java.io.ByteArrayOutputStream;
|
import java.io.ByteArrayOutputStream;
|
||||||
import java.io.File;
|
import java.io.File;
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
|
@ -14,9 +13,8 @@ import java.util.Arrays;
|
||||||
import java.util.regex.Matcher;
|
import java.util.regex.Matcher;
|
||||||
import java.util.regex.Pattern;
|
import java.util.regex.Pattern;
|
||||||
|
|
||||||
|
@Slf4j
|
||||||
public class VideoLengthDetector {
|
public class VideoLengthDetector {
|
||||||
private static final Logger LOG = LoggerFactory.getLogger(VideoLengthDetector.class);
|
|
||||||
|
|
||||||
private VideoLengthDetector() {
|
private VideoLengthDetector() {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -37,7 +35,7 @@ public class VideoLengthDetector {
|
||||||
"-"
|
"-"
|
||||||
};
|
};
|
||||||
String[] cmdline = OS.getFFmpegCommand(args);
|
String[] cmdline = OS.getFFmpegCommand(args);
|
||||||
LOG.debug("Command line: {}", Arrays.toString(cmdline));
|
log.debug("Command line: {}", Arrays.toString(cmdline));
|
||||||
Process ffmpeg = Runtime.getRuntime().exec(cmdline, new String[0], videoFile.getParentFile());
|
Process ffmpeg = Runtime.getRuntime().exec(cmdline, new String[0], videoFile.getParentFile());
|
||||||
int exitCode;
|
int exitCode;
|
||||||
ByteArrayOutputStream stdErrBuffer = new ByteArrayOutputStream();
|
ByteArrayOutputStream stdErrBuffer = new ByteArrayOutputStream();
|
||||||
|
@ -46,16 +44,16 @@ public class VideoLengthDetector {
|
||||||
stdout.start();
|
stdout.start();
|
||||||
stderr.start();
|
stderr.start();
|
||||||
exitCode = ffmpeg.waitFor();
|
exitCode = ffmpeg.waitFor();
|
||||||
LOG.debug("FFmpeg exited with code {}", exitCode);
|
log.debug("FFmpeg exited with code {}", exitCode);
|
||||||
stdout.join();
|
stdout.join();
|
||||||
stderr.join();
|
stderr.join();
|
||||||
String ffmpegStderr = stdErrBuffer.toString();
|
String ffmpegStderr = stdErrBuffer.toString();
|
||||||
return parseDuration(ffmpegStderr);
|
return parseDuration(ffmpegStderr);
|
||||||
} catch (IOException | ProcessExitedUncleanException e) {
|
} catch (IOException | ProcessExitedUncleanException e) {
|
||||||
LOG.error("Error in FFMpeg thread", e);
|
log.error("Error in FFMpeg thread", e);
|
||||||
} catch (InterruptedException e) {
|
} catch (InterruptedException e) {
|
||||||
Thread.currentThread().interrupt();
|
Thread.currentThread().interrupt();
|
||||||
LOG.info("Interrupted while waiting for ffmpeg", e);
|
log.info("Interrupted while waiting for ffmpeg", e);
|
||||||
}
|
}
|
||||||
return Duration.ZERO.minusSeconds(1);
|
return Duration.ZERO.minusSeconds(1);
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,5 +1,7 @@
|
||||||
package ctbrec.recorder.download.dash;
|
package ctbrec.recorder.download.dash;
|
||||||
|
|
||||||
|
|
||||||
|
import lombok.extern.slf4j.Slf4j;
|
||||||
import ctbrec.Config;
|
import ctbrec.Config;
|
||||||
import ctbrec.Model;
|
import ctbrec.Model;
|
||||||
import ctbrec.Recording;
|
import ctbrec.Recording;
|
||||||
|
@ -13,9 +15,6 @@ import ctbrec.recorder.download.hls.NoStreamFoundException;
|
||||||
import ctbrec.recorder.download.hls.PostProcessingException;
|
import ctbrec.recorder.download.hls.PostProcessingException;
|
||||||
import okhttp3.Request;
|
import okhttp3.Request;
|
||||||
import okhttp3.Response;
|
import okhttp3.Response;
|
||||||
import org.slf4j.Logger;
|
|
||||||
import org.slf4j.LoggerFactory;
|
|
||||||
|
|
||||||
import javax.xml.bind.JAXBContext;
|
import javax.xml.bind.JAXBContext;
|
||||||
import javax.xml.bind.JAXBElement;
|
import javax.xml.bind.JAXBElement;
|
||||||
import javax.xml.bind.JAXBException;
|
import javax.xml.bind.JAXBException;
|
||||||
|
@ -38,11 +37,9 @@ import java.util.regex.Pattern;
|
||||||
import static ctbrec.Recording.State.POST_PROCESSING;
|
import static ctbrec.Recording.State.POST_PROCESSING;
|
||||||
import static ctbrec.io.HttpConstants.*;
|
import static ctbrec.io.HttpConstants.*;
|
||||||
|
|
||||||
|
@Slf4j
|
||||||
public class DashDownload extends AbstractDownload {
|
public class DashDownload extends AbstractDownload {
|
||||||
private static final String CONTENT_LENGTH = "Content-Length";
|
private static final String CONTENT_LENGTH = "Content-Length";
|
||||||
|
|
||||||
private static final Logger LOG = LoggerFactory.getLogger(DashDownload.class);
|
|
||||||
|
|
||||||
private int audioCounter = 0;
|
private int audioCounter = 0;
|
||||||
private int videoCounter = 0;
|
private int videoCounter = 0;
|
||||||
private DecimalFormat df = new DecimalFormat("00000");
|
private DecimalFormat df = new DecimalFormat("00000");
|
||||||
|
@ -74,7 +71,7 @@ public class DashDownload extends AbstractDownload {
|
||||||
.header(REFERER, model.getSite().getBaseUrl())
|
.header(REFERER, model.getSite().getBaseUrl())
|
||||||
.header(CONNECTION, KEEP_ALIVE)
|
.header(CONNECTION, KEEP_ALIVE)
|
||||||
.build(); // @formatter:on
|
.build(); // @formatter:on
|
||||||
LOG.trace("Loading manifest {}", url);
|
log.trace("Loading manifest {}", url);
|
||||||
for (int tries = 1; tries <= 10; tries++) {
|
for (int tries = 1; tries <= 10; tries++) {
|
||||||
try (Response response = httpClient.execute(request)) {
|
try (Response response = httpClient.execute(request)) {
|
||||||
if (response.isSuccessful()) {
|
if (response.isSuccessful()) {
|
||||||
|
@ -85,7 +82,7 @@ public class DashDownload extends AbstractDownload {
|
||||||
if (tries == 10) {
|
if (tries == 10) {
|
||||||
throw httpException;
|
throw httpException;
|
||||||
} else {
|
} else {
|
||||||
LOG.debug("Couldn't load manifest", httpException);
|
log.debug("Couldn't load manifest", httpException);
|
||||||
waitSomeTime(100l * tries);
|
waitSomeTime(100l * tries);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
|
@ -165,12 +162,12 @@ public class DashDownload extends AbstractDownload {
|
||||||
private void setInitState(boolean isVideo, File file) {
|
private void setInitState(boolean isVideo, File file) {
|
||||||
if (isVideo) {
|
if (isVideo) {
|
||||||
if (file.exists() && file.length() > 0) {
|
if (file.exists() && file.length() > 0) {
|
||||||
LOG.debug("Video init chunk loaded");
|
log.debug("Video init chunk loaded");
|
||||||
videoInitLoaded = true;
|
videoInitLoaded = true;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
if (file.exists() && file.length() > 0) {
|
if (file.exists() && file.length() > 0) {
|
||||||
LOG.debug("Audio init chunk loaded");
|
log.debug("Audio init chunk loaded");
|
||||||
audioInitLoaded = true;
|
audioInitLoaded = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -191,7 +188,7 @@ public class DashDownload extends AbstractDownload {
|
||||||
for (tries = 1; tries <= 10; tries++) {
|
for (tries = 1; tries <= 10; tries++) {
|
||||||
try (Response response = httpClient.execute(request)) {
|
try (Response response = httpClient.execute(request)) {
|
||||||
if (!response.isSuccessful()) {
|
if (!response.isSuccessful()) {
|
||||||
LOG.trace("Loading segment failed, try {}, {} size:{} {}", tries, response.code(), response.headers().values(CONTENT_LENGTH), url);
|
log.trace("Loading segment failed, try {}, {} size:{} {}", tries, response.code(), response.headers().values(CONTENT_LENGTH), url);
|
||||||
waitSomeTime(tries * 80l);
|
waitSomeTime(tries * 80l);
|
||||||
} else {
|
} else {
|
||||||
InputStream in = response.body().byteStream();
|
InputStream in = response.body().byteStream();
|
||||||
|
@ -214,7 +211,7 @@ public class DashDownload extends AbstractDownload {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
LOG.warn("Loading segment finally failed after {} tries {}", --tries, url);
|
log.warn("Loading segment finally failed after {} tries {}", --tries, url);
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -246,19 +243,19 @@ public class DashDownload extends AbstractDownload {
|
||||||
}
|
}
|
||||||
} catch (HttpException e) {
|
} catch (HttpException e) {
|
||||||
if (e.getResponseCode() == 404) {
|
if (e.getResponseCode() == 404) {
|
||||||
LOG.debug("Manifest not found (404). Model {} probably went offline", model);
|
log.debug("Manifest not found (404). Model {} probably went offline", model);
|
||||||
waitSomeTime(10_000);
|
waitSomeTime(10_000);
|
||||||
} else if (e.getResponseCode() == 403) {
|
} else if (e.getResponseCode() == 403) {
|
||||||
LOG.debug("Manifest access forbidden (403). Model {} probably went private or offline", model);
|
log.debug("Manifest access forbidden (403). Model {} probably went private or offline", model);
|
||||||
waitSomeTime(10_000);
|
waitSomeTime(10_000);
|
||||||
} else {
|
} else {
|
||||||
throw e;
|
throw e;
|
||||||
}
|
}
|
||||||
} catch (InterruptedException e) {
|
} catch (InterruptedException e) {
|
||||||
Thread.currentThread().interrupt();
|
Thread.currentThread().interrupt();
|
||||||
LOG.error("Error while downloading dash stream", e);
|
log.error("Error while downloading dash stream", e);
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
LOG.error("Error while downloading dash stream", e);
|
log.error("Error while downloading dash stream", e);
|
||||||
} finally {
|
} finally {
|
||||||
running = false;
|
running = false;
|
||||||
downloadFinished.set(true);
|
downloadFinished.set(true);
|
||||||
|
@ -280,7 +277,7 @@ public class DashDownload extends AbstractDownload {
|
||||||
|
|
||||||
private void downloadManifestAndItsSegments(Unmarshaller u) throws IOException, JAXBException, ExecutionException, InterruptedException {
|
private void downloadManifestAndItsSegments(Unmarshaller u) throws IOException, JAXBException, ExecutionException, InterruptedException {
|
||||||
String manifest = getManifest(manifestUrl);
|
String manifest = getManifest(manifestUrl);
|
||||||
LOG.trace("Manifest: {}", manifest);
|
log.trace("Manifest: {}", manifest);
|
||||||
@SuppressWarnings("unchecked")
|
@SuppressWarnings("unchecked")
|
||||||
JAXBElement<MPDtype> root = (JAXBElement<MPDtype>) u.unmarshal(new ByteArrayInputStream(manifest.getBytes()));
|
JAXBElement<MPDtype> root = (JAXBElement<MPDtype>) u.unmarshal(new ByteArrayInputStream(manifest.getBytes()));
|
||||||
MPDtype mpd = root.getValue();
|
MPDtype mpd = root.getValue();
|
||||||
|
@ -302,7 +299,7 @@ public class DashDownload extends AbstractDownload {
|
||||||
downloaded += downloadSegments(mpd, audio, false);
|
downloaded += downloadSegments(mpd, audio, false);
|
||||||
|
|
||||||
if (downloaded == 0) {
|
if (downloaded == 0) {
|
||||||
LOG.trace("No new segments - Sleeping a bit");
|
log.trace("No new segments - Sleeping a bit");
|
||||||
waitSomeTime(1000);
|
waitSomeTime(1000);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -346,7 +343,7 @@ public class DashDownload extends AbstractDownload {
|
||||||
}
|
}
|
||||||
} catch (InterruptedException e) {
|
} catch (InterruptedException e) {
|
||||||
Thread.currentThread().interrupt();
|
Thread.currentThread().interrupt();
|
||||||
LOG.error("Couldn't wait for download to finish", e);
|
log.error("Couldn't wait for download to finish", e);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,5 +1,7 @@
|
||||||
package ctbrec.recorder.download.dash;
|
package ctbrec.recorder.download.dash;
|
||||||
|
|
||||||
|
|
||||||
|
import lombok.extern.slf4j.Slf4j;
|
||||||
import java.io.File;
|
import java.io.File;
|
||||||
import java.io.FileInputStream;
|
import java.io.FileInputStream;
|
||||||
import java.io.FileOutputStream;
|
import java.io.FileOutputStream;
|
||||||
|
@ -7,16 +9,12 @@ import java.io.IOException;
|
||||||
import java.nio.file.Files;
|
import java.nio.file.Files;
|
||||||
import java.util.Arrays;
|
import java.util.Arrays;
|
||||||
import java.util.Optional;
|
import java.util.Optional;
|
||||||
|
|
||||||
import org.slf4j.Logger;
|
|
||||||
import org.slf4j.LoggerFactory;
|
|
||||||
|
|
||||||
import ctbrec.OS;
|
import ctbrec.OS;
|
||||||
import ctbrec.io.StreamRedirector;
|
import ctbrec.io.StreamRedirector;
|
||||||
import ctbrec.recorder.download.ProcessExitedUncleanException;
|
import ctbrec.recorder.download.ProcessExitedUncleanException;
|
||||||
|
|
||||||
|
@Slf4j
|
||||||
public class FfmpegMuxer {
|
public class FfmpegMuxer {
|
||||||
private static final Logger LOG = LoggerFactory.getLogger(FfmpegMuxer.class);
|
|
||||||
private static final int ALL_GOOD = 0;
|
private static final int ALL_GOOD = 0;
|
||||||
|
|
||||||
File segmentDir;
|
File segmentDir;
|
||||||
|
@ -42,11 +40,11 @@ public class FfmpegMuxer {
|
||||||
|
|
||||||
int exitCode = mergeTracks(mp4VideoTrack, mp4AudioTrack, targetFile);
|
int exitCode = mergeTracks(mp4VideoTrack, mp4AudioTrack, targetFile);
|
||||||
if (exitCode == ALL_GOOD) {
|
if (exitCode == ALL_GOOD) {
|
||||||
LOG.debug("Deleting merged video and audio tracks");
|
log.debug("Deleting merged video and audio tracks");
|
||||||
Files.delete(mp4VideoTrack.toPath());
|
Files.delete(mp4VideoTrack.toPath());
|
||||||
Files.delete(mp4AudioTrack.toPath());
|
Files.delete(mp4AudioTrack.toPath());
|
||||||
Files.deleteIfExists(new File(segmentDir, "merge.log").toPath());
|
Files.deleteIfExists(new File(segmentDir, "merge.log").toPath());
|
||||||
LOG.debug("Deleting segments");
|
log.debug("Deleting segments");
|
||||||
deleteFiles(segmentDir, videoSegments);
|
deleteFiles(segmentDir, videoSegments);
|
||||||
deleteFiles(segmentDir, audioSegments);
|
deleteFiles(segmentDir, audioSegments);
|
||||||
if (segmentDir.list().length == 0) {
|
if (segmentDir.list().length == 0) {
|
||||||
|
@ -63,7 +61,7 @@ public class FfmpegMuxer {
|
||||||
try {
|
try {
|
||||||
Files.delete(absFile.toPath());
|
Files.delete(absFile.toPath());
|
||||||
} catch(IOException e) {
|
} catch(IOException e) {
|
||||||
LOG.info("Couldn't delete segment {}", absFile, e);
|
log.info("Couldn't delete segment {}", absFile, e);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -97,7 +95,7 @@ public class FfmpegMuxer {
|
||||||
output.getCanonicalPath()
|
output.getCanonicalPath()
|
||||||
);
|
);
|
||||||
// @formatter:on
|
// @formatter:on
|
||||||
LOG.debug("Command line: {}", Arrays.toString(cmdline));
|
log.debug("Command line: {}", Arrays.toString(cmdline));
|
||||||
Process ffmpeg = Runtime.getRuntime().exec(cmdline);
|
Process ffmpeg = Runtime.getRuntime().exec(cmdline);
|
||||||
Thread stdout = new Thread(new StreamRedirector(ffmpeg.getInputStream(), muxLogStream));
|
Thread stdout = new Thread(new StreamRedirector(ffmpeg.getInputStream(), muxLogStream));
|
||||||
Thread stderr = new Thread(new StreamRedirector(ffmpeg.getErrorStream(), muxLogStream));
|
Thread stderr = new Thread(new StreamRedirector(ffmpeg.getErrorStream(), muxLogStream));
|
||||||
|
@ -109,7 +107,7 @@ public class FfmpegMuxer {
|
||||||
return exitCode;
|
return exitCode;
|
||||||
} catch (InterruptedException e) {
|
} catch (InterruptedException e) {
|
||||||
Thread.currentThread().interrupt();
|
Thread.currentThread().interrupt();
|
||||||
LOG.error("Interrupted while waiting for FFMPEG", e);
|
log.error("Interrupted while waiting for FFMPEG", e);
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,5 +1,7 @@
|
||||||
package ctbrec.recorder.download.hls;
|
package ctbrec.recorder.download.hls;
|
||||||
|
|
||||||
|
|
||||||
|
import lombok.extern.slf4j.Slf4j;
|
||||||
import com.iheartradio.m3u8.*;
|
import com.iheartradio.m3u8.*;
|
||||||
import com.iheartradio.m3u8.data.EncryptionData;
|
import com.iheartradio.m3u8.data.EncryptionData;
|
||||||
import com.iheartradio.m3u8.data.MediaPlaylist;
|
import com.iheartradio.m3u8.data.MediaPlaylist;
|
||||||
|
@ -23,9 +25,6 @@ import ctbrec.sites.Site;
|
||||||
import okhttp3.Request;
|
import okhttp3.Request;
|
||||||
import okhttp3.Request.Builder;
|
import okhttp3.Request.Builder;
|
||||||
import okhttp3.Response;
|
import okhttp3.Response;
|
||||||
import org.slf4j.Logger;
|
|
||||||
import org.slf4j.LoggerFactory;
|
|
||||||
|
|
||||||
import javax.xml.bind.JAXBException;
|
import javax.xml.bind.JAXBException;
|
||||||
import java.io.*;
|
import java.io.*;
|
||||||
import java.net.MalformedURLException;
|
import java.net.MalformedURLException;
|
||||||
|
@ -51,9 +50,8 @@ import static ctbrec.io.HttpConstants.*;
|
||||||
import static java.nio.charset.StandardCharsets.UTF_8;
|
import static java.nio.charset.StandardCharsets.UTF_8;
|
||||||
import static java.nio.file.StandardOpenOption.*;
|
import static java.nio.file.StandardOpenOption.*;
|
||||||
|
|
||||||
|
@Slf4j
|
||||||
public abstract class AbstractHlsDownload extends AbstractDownload {
|
public abstract class AbstractHlsDownload extends AbstractDownload {
|
||||||
|
|
||||||
private static final Logger LOG = LoggerFactory.getLogger(AbstractHlsDownload.class);
|
|
||||||
private static final int A_FEW_SECONDS = 10_000;
|
private static final int A_FEW_SECONDS = 10_000;
|
||||||
private static final int MAX_SECONDS_WITHOUT_TRANSFER = 30;
|
private static final int MAX_SECONDS_WITHOUT_TRANSFER = 30;
|
||||||
|
|
||||||
|
@ -101,7 +99,7 @@ public abstract class AbstractHlsDownload extends AbstractDownload {
|
||||||
}
|
}
|
||||||
|
|
||||||
protected void segmentDownloadFailed(SegmentDownload segmentDownload) {
|
protected void segmentDownloadFailed(SegmentDownload segmentDownload) {
|
||||||
LOG.info("Segment download failed with", segmentDownload.getException());
|
log.info("Segment download failed with", segmentDownload.getException());
|
||||||
stopRecordingOnHighSegmentErrorCount();
|
stopRecordingOnHighSegmentErrorCount();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -141,11 +139,11 @@ public abstract class AbstractHlsDownload extends AbstractDownload {
|
||||||
}
|
}
|
||||||
|
|
||||||
} catch (ParseException e) {
|
} catch (ParseException e) {
|
||||||
LOG.error("Couldn't parse HLS playlist for model {}\n{}", model, e.getInput(), e);
|
log.error("Couldn't parse HLS playlist for model {}\n{}", model, e.getInput(), e);
|
||||||
model.delay();
|
model.delay();
|
||||||
stop();
|
stop();
|
||||||
} catch (PlaylistException e) {
|
} catch (PlaylistException e) {
|
||||||
LOG.error("Couldn't parse HLS playlist for model {}", model, e);
|
log.error("Couldn't parse HLS playlist for model {}", model, e);
|
||||||
model.delay();
|
model.delay();
|
||||||
stop();
|
stop();
|
||||||
} catch (PlaylistTimeoutException e) {
|
} catch (PlaylistTimeoutException e) {
|
||||||
|
@ -157,23 +155,23 @@ public abstract class AbstractHlsDownload extends AbstractDownload {
|
||||||
}
|
}
|
||||||
} catch (EOFException e) {
|
} catch (EOFException e) {
|
||||||
// end of playlist reached
|
// end of playlist reached
|
||||||
LOG.debug("Reached end of playlist for model {}", model);
|
log.debug("Reached end of playlist for model {}", model);
|
||||||
stop();
|
stop();
|
||||||
} catch (HttpException e) {
|
} catch (HttpException e) {
|
||||||
consecutivePlaylistErrors++;
|
consecutivePlaylistErrors++;
|
||||||
handleHttpException(e);
|
handleHttpException(e);
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
LOG.error("Couldn't download segment for model {}", model, e);
|
log.error("Couldn't download segment for model {}", model, e);
|
||||||
model.delay();
|
model.delay();
|
||||||
stop();
|
stop();
|
||||||
} finally {
|
} finally {
|
||||||
if (consecutivePlaylistErrors > 0) {
|
if (consecutivePlaylistErrors > 0) {
|
||||||
LOG.debug("Consecutive playlist errors: {}", consecutivePlaylistErrors);
|
log.debug("Consecutive playlist errors: {}", consecutivePlaylistErrors);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (Duration.between(lastSegmentDownload, Instant.now()).getSeconds() > MAX_SECONDS_WITHOUT_TRANSFER) {
|
if (Duration.between(lastSegmentDownload, Instant.now()).getSeconds() > MAX_SECONDS_WITHOUT_TRANSFER) {
|
||||||
LOG.info("No video data received for {} seconds. Stopping recording for model {}", MAX_SECONDS_WITHOUT_TRANSFER, model);
|
log.info("No video data received for {} seconds. Stopping recording for model {}", MAX_SECONDS_WITHOUT_TRANSFER, model);
|
||||||
stop();
|
stop();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -198,7 +196,7 @@ public abstract class AbstractHlsDownload extends AbstractDownload {
|
||||||
}
|
}
|
||||||
} catch (InterruptedException e) {
|
} catch (InterruptedException e) {
|
||||||
Thread.currentThread().interrupt();
|
Thread.currentThread().interrupt();
|
||||||
LOG.error("Thread interrupted during segment download", e);
|
log.error("Thread interrupted during segment download", e);
|
||||||
} catch (ExecutionException e) {
|
} catch (ExecutionException e) {
|
||||||
// Something unexpected went wrong during the segment download.
|
// Something unexpected went wrong during the segment download.
|
||||||
// At this point we have taken care of that, but we take note of the error and if a certain threshold of errors is exceeded in a certain
|
// At this point we have taken care of that, but we take note of the error and if a certain threshold of errors is exceeded in a certain
|
||||||
|
@ -223,9 +221,9 @@ public abstract class AbstractHlsDownload extends AbstractDownload {
|
||||||
iterator.remove();
|
iterator.remove();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
LOG.debug("Segment errors in last {} secs for {}: {}", measurePeriodInSecs, getModel(), errorsInMeasurePeriod);
|
log.debug("Segment errors in last {} secs for {}: {}", measurePeriodInSecs, getModel(), errorsInMeasurePeriod);
|
||||||
if (errorsInMeasurePeriod > config.getSettings().segmentErrorThresholdToStopRecording) {
|
if (errorsInMeasurePeriod > config.getSettings().segmentErrorThresholdToStopRecording) {
|
||||||
LOG.info("Too many ({}) segment errors for {} - stopping recording", errorsInMeasurePeriod, getModel());
|
log.info("Too many ({}) segment errors for {} - stopping recording", errorsInMeasurePeriod, getModel());
|
||||||
stop();
|
stop();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -239,11 +237,11 @@ public abstract class AbstractHlsDownload extends AbstractDownload {
|
||||||
checkIfModelIsStillOnline("Playlist access forbidden (403). Model {} probably went private or offline. Model state: {}");
|
checkIfModelIsStillOnline("Playlist access forbidden (403). Model {} probably went private or offline. Model state: {}");
|
||||||
}
|
}
|
||||||
if (consecutivePlaylistErrors >= 3) {
|
if (consecutivePlaylistErrors >= 3) {
|
||||||
LOG.info("Playlist could not be downloaded for model {} {} times. Stopping recording", model, consecutivePlaylistErrors, e);
|
log.info("Playlist could not be downloaded for model {} {} times. Stopping recording", model, consecutivePlaylistErrors, e);
|
||||||
model.delay();
|
model.delay();
|
||||||
stop();
|
stop();
|
||||||
} else {
|
} else {
|
||||||
LOG.info("Playlist could not be downloaded for model {} {} times: {}", model, consecutivePlaylistErrors, e.getLocalizedMessage());
|
log.info("Playlist could not be downloaded for model {} {} times: {}", model, consecutivePlaylistErrors, e.getLocalizedMessage());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -254,32 +252,32 @@ public abstract class AbstractHlsDownload extends AbstractDownload {
|
||||||
} catch (Exception e1) {
|
} catch (Exception e1) {
|
||||||
modelState = State.UNKNOWN;
|
modelState = State.UNKNOWN;
|
||||||
}
|
}
|
||||||
LOG.info(errorMsg, model, modelState);
|
log.info(errorMsg, model, modelState);
|
||||||
if (modelState != State.ONLINE) {
|
if (modelState != State.ONLINE) {
|
||||||
stop();
|
stop();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
try {
|
try {
|
||||||
LOG.debug("Waiting {}ms before trying to update the playlist URL", A_FEW_SECONDS);
|
log.debug("Waiting {}ms before trying to update the playlist URL", A_FEW_SECONDS);
|
||||||
waitSomeTime();
|
waitSomeTime();
|
||||||
segmentPlaylistUrl = getSegmentPlaylistUrl(model);
|
segmentPlaylistUrl = getSegmentPlaylistUrl(model);
|
||||||
rescheduleTime = Instant.now();
|
rescheduleTime = Instant.now();
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
LOG.error("Playlist URL couldn't be updated after waiting for {}ms", A_FEW_SECONDS, e);
|
log.error("Playlist URL couldn't be updated after waiting for {}ms", A_FEW_SECONDS, e);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
protected String getSegmentPlaylistUrl(Model model) throws IOException, ExecutionException, ParseException, PlaylistException, JAXBException {
|
protected String getSegmentPlaylistUrl(Model model) throws IOException, ExecutionException, ParseException, PlaylistException, JAXBException {
|
||||||
LOG.debug("{}:{} stream idx: {}", model.getSite().getName(), model.getName(), model.getStreamUrlIndex());
|
log.debug("{}:{} stream idx: {}", model.getSite().getName(), model.getName(), model.getStreamUrlIndex());
|
||||||
List<StreamSource> streamSources = model.getStreamSources();
|
List<StreamSource> streamSources = model.getStreamSources();
|
||||||
Collections.sort(streamSources);
|
Collections.sort(streamSources);
|
||||||
for (StreamSource streamSource : streamSources) {
|
for (StreamSource streamSource : streamSources) {
|
||||||
LOG.debug("{}:{} src {}", model.getSite().getName(), model.getName(), streamSource);
|
log.debug("{}:{} src {}", model.getSite().getName(), model.getName(), streamSource);
|
||||||
}
|
}
|
||||||
StreamSource selectedStreamSource = selectStreamSource(streamSources);
|
StreamSource selectedStreamSource = selectStreamSource(streamSources);
|
||||||
String url = selectedStreamSource.getMediaPlaylistUrl();
|
String url = selectedStreamSource.getMediaPlaylistUrl();
|
||||||
selectedResolution = selectedStreamSource.getHeight();
|
selectedResolution = selectedStreamSource.getHeight();
|
||||||
LOG.debug("Segment playlist url {}", url);
|
log.debug("Segment playlist url {}", url);
|
||||||
return url;
|
return url;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -313,7 +311,7 @@ public abstract class AbstractHlsDownload extends AbstractDownload {
|
||||||
throw new HttpException(response.code(), response.message());
|
throw new HttpException(response.code(), response.message());
|
||||||
}
|
}
|
||||||
} catch (SocketTimeoutException e) {
|
} catch (SocketTimeoutException e) {
|
||||||
LOG.debug("Playlist request timed out ({}ms) for model {}:{} {} time{} (took {}ms)",
|
log.debug("Playlist request timed out ({}ms) for model {}:{} {} time{} (took {}ms)",
|
||||||
config.getSettings().playlistRequestTimeout,
|
config.getSettings().playlistRequestTimeout,
|
||||||
model.getSite().getName(),
|
model.getSite().getName(),
|
||||||
model,
|
model,
|
||||||
|
@ -384,7 +382,7 @@ public abstract class AbstractHlsDownload extends AbstractDownload {
|
||||||
playlistEmptyCount = 0;
|
playlistEmptyCount = 0;
|
||||||
}
|
}
|
||||||
if (playlistEmptyCount == 10) {
|
if (playlistEmptyCount == 10) {
|
||||||
LOG.info("Last 10 playlists were empty for {}. Stopping recording!", getModel());
|
log.info("Last 10 playlists were empty for {}. Stopping recording!", getModel());
|
||||||
model.delay();
|
model.delay();
|
||||||
internalStop();
|
internalStop();
|
||||||
}
|
}
|
||||||
|
@ -405,7 +403,7 @@ public abstract class AbstractHlsDownload extends AbstractDownload {
|
||||||
}
|
}
|
||||||
br.flush();
|
br.flush();
|
||||||
} catch (IOException e) {
|
} catch (IOException e) {
|
||||||
LOG.error("Couldn't write log file for missed segments", e);
|
log.error("Couldn't write log file for missed segments", e);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -454,7 +452,7 @@ public abstract class AbstractHlsDownload extends AbstractDownload {
|
||||||
} catch (InterruptedException e) {
|
} catch (InterruptedException e) {
|
||||||
Thread.currentThread().interrupt();
|
Thread.currentThread().interrupt();
|
||||||
if (running) {
|
if (running) {
|
||||||
LOG.error("Couldn't sleep. This might mess up the download!");
|
log.error("Couldn't sleep. This might mess up the download!");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,5 +1,7 @@
|
||||||
package ctbrec.recorder.download.hls;
|
package ctbrec.recorder.download.hls;
|
||||||
|
|
||||||
|
|
||||||
|
import lombok.extern.slf4j.Slf4j;
|
||||||
import com.iheartradio.m3u8.*;
|
import com.iheartradio.m3u8.*;
|
||||||
import com.iheartradio.m3u8.data.MediaPlaylist;
|
import com.iheartradio.m3u8.data.MediaPlaylist;
|
||||||
import com.iheartradio.m3u8.data.Playlist;
|
import com.iheartradio.m3u8.data.Playlist;
|
||||||
|
@ -19,9 +21,6 @@ import ctbrec.recorder.download.RecordingProcess;
|
||||||
import ctbrec.recorder.download.StreamSource;
|
import ctbrec.recorder.download.StreamSource;
|
||||||
import okhttp3.Request;
|
import okhttp3.Request;
|
||||||
import okhttp3.Response;
|
import okhttp3.Response;
|
||||||
import org.slf4j.Logger;
|
|
||||||
import org.slf4j.LoggerFactory;
|
|
||||||
|
|
||||||
import javax.xml.bind.JAXBException;
|
import javax.xml.bind.JAXBException;
|
||||||
import java.io.File;
|
import java.io.File;
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
|
@ -44,9 +43,8 @@ import java.util.regex.Pattern;
|
||||||
|
|
||||||
import static ctbrec.io.HttpConstants.*;
|
import static ctbrec.io.HttpConstants.*;
|
||||||
|
|
||||||
|
@Slf4j
|
||||||
public class FfmpegHlsDownload extends AbstractDownload {
|
public class FfmpegHlsDownload extends AbstractDownload {
|
||||||
|
|
||||||
private static final Logger LOG = LoggerFactory.getLogger(FfmpegHlsDownload.class);
|
|
||||||
private static final int MAX_SECONDS_WITHOUT_TRANSFER = 20;
|
private static final int MAX_SECONDS_WITHOUT_TRANSFER = 20;
|
||||||
|
|
||||||
private final HttpClient httpClient;
|
private final HttpClient httpClient;
|
||||||
|
@ -94,7 +92,7 @@ public class FfmpegHlsDownload extends AbstractDownload {
|
||||||
try {
|
try {
|
||||||
ffmpegStdIn.close();
|
ffmpegStdIn.close();
|
||||||
} catch (IOException e) {
|
} catch (IOException e) {
|
||||||
LOG.error("Couldn't terminate FFmpeg by closing stdin", e);
|
log.error("Couldn't terminate FFmpeg by closing stdin", e);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (ffmpegProcess != null) {
|
if (ffmpegProcess != null) {
|
||||||
|
@ -103,13 +101,13 @@ public class FfmpegHlsDownload extends AbstractDownload {
|
||||||
if (!waitFor && ffmpegProcess.isAlive()) {
|
if (!waitFor && ffmpegProcess.isAlive()) {
|
||||||
ffmpegProcess.destroy();
|
ffmpegProcess.destroy();
|
||||||
if (ffmpegProcess.isAlive()) {
|
if (ffmpegProcess.isAlive()) {
|
||||||
LOG.info("FFmpeg didn't terminate. Destroying the process with force!");
|
log.info("FFmpeg didn't terminate. Destroying the process with force!");
|
||||||
ffmpegProcess.destroyForcibly();
|
ffmpegProcess.destroyForcibly();
|
||||||
ffmpegProcess = null;
|
ffmpegProcess = null;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} catch (InterruptedException e) {
|
} catch (InterruptedException e) {
|
||||||
LOG.error("Interrupted while waiting for FFmpeg to terminate");
|
log.error("Interrupted while waiting for FFmpeg to terminate");
|
||||||
Thread.currentThread().interrupt();
|
Thread.currentThread().interrupt();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -127,7 +125,7 @@ public class FfmpegHlsDownload extends AbstractDownload {
|
||||||
.build();
|
.build();
|
||||||
ffmpeg.exec(cmdline, new String[0], target.getParentFile());
|
ffmpeg.exec(cmdline, new String[0], target.getParentFile());
|
||||||
} catch (IOException | ProcessExitedUncleanException e) {
|
} catch (IOException | ProcessExitedUncleanException e) {
|
||||||
LOG.error("Error in FFmpeg thread", e);
|
log.error("Error in FFmpeg thread", e);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -189,7 +187,7 @@ public class FfmpegHlsDownload extends AbstractDownload {
|
||||||
ffmpeg.shutdown(exitValue);
|
ffmpeg.shutdown(exitValue);
|
||||||
}
|
}
|
||||||
} catch (ProcessExitedUncleanException e) {
|
} catch (ProcessExitedUncleanException e) {
|
||||||
LOG.error("FFmpeg exited unclean", e);
|
log.error("FFmpeg exited unclean", e);
|
||||||
internalStop();
|
internalStop();
|
||||||
}
|
}
|
||||||
try {
|
try {
|
||||||
|
@ -198,21 +196,21 @@ public class FfmpegHlsDownload extends AbstractDownload {
|
||||||
startDownload();
|
startDownload();
|
||||||
}
|
}
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
LOG.error("Error while downloading MP4", e);
|
log.error("Error while downloading MP4", e);
|
||||||
stop();
|
stop();
|
||||||
}
|
}
|
||||||
if (!model.isOnline()) {
|
if (!model.isOnline()) {
|
||||||
LOG.debug("Model {} not online. Stop recording.", model);
|
log.debug("Model {} not online. Stop recording.", model);
|
||||||
stop();
|
stop();
|
||||||
}
|
}
|
||||||
if (splittingStrategy.splitNecessary(this)) {
|
if (splittingStrategy.splitNecessary(this)) {
|
||||||
LOG.debug("Split necessary for model {}. Stop recording.", model);
|
log.debug("Split necessary for model {}. Stop recording.", model);
|
||||||
internalStop();
|
internalStop();
|
||||||
} else {
|
} else {
|
||||||
rescheduleTime = Instant.now().plusSeconds(5);
|
rescheduleTime = Instant.now().plusSeconds(5);
|
||||||
}
|
}
|
||||||
if (Duration.between(timeOfLastTransfer, Instant.now()).getSeconds() > MAX_SECONDS_WITHOUT_TRANSFER) {
|
if (Duration.between(timeOfLastTransfer, Instant.now()).getSeconds() > MAX_SECONDS_WITHOUT_TRANSFER) {
|
||||||
LOG.debug("No video data received for {} seconds. Stopping recording for model {}", MAX_SECONDS_WITHOUT_TRANSFER, model);
|
log.debug("No video data received for {} seconds. Stopping recording for model {}", MAX_SECONDS_WITHOUT_TRANSFER, model);
|
||||||
stop();
|
stop();
|
||||||
}
|
}
|
||||||
return this;
|
return this;
|
||||||
|
@ -222,7 +220,7 @@ public class FfmpegHlsDownload extends AbstractDownload {
|
||||||
List<StreamSource> streamSources = model.getStreamSources();
|
List<StreamSource> streamSources = model.getStreamSources();
|
||||||
Collections.sort(streamSources);
|
Collections.sort(streamSources);
|
||||||
for (StreamSource streamSource : streamSources) {
|
for (StreamSource streamSource : streamSources) {
|
||||||
LOG.debug("{}:{} src {}", model.getSite().getName(), model.getName(), streamSource);
|
log.debug("{}:{} src {}", model.getSite().getName(), model.getName(), streamSource);
|
||||||
}
|
}
|
||||||
StreamSource selectedStreamSource = selectStreamSource(streamSources);
|
StreamSource selectedStreamSource = selectStreamSource(streamSources);
|
||||||
String playlistUrl = selectedStreamSource.getMediaPlaylistUrl();
|
String playlistUrl = selectedStreamSource.getMediaPlaylistUrl();
|
||||||
|
@ -245,14 +243,14 @@ public class FfmpegHlsDownload extends AbstractDownload {
|
||||||
if (media.hasTracks()) {
|
if (media.hasTracks()) {
|
||||||
TrackData firstTrack = media.getTracks().get(0);
|
TrackData firstTrack = media.getTracks().get(0);
|
||||||
if (firstTrack.isEncrypted()) {
|
if (firstTrack.isEncrypted()) {
|
||||||
LOG.warn("Video track is encrypted. Playlist URL: {}", playlistUrl);
|
log.warn("Video track is encrypted. Playlist URL: {}", playlistUrl);
|
||||||
}
|
}
|
||||||
String uri = firstTrack.getUri();
|
String uri = firstTrack.getUri();
|
||||||
if (!uri.startsWith("http")) {
|
if (!uri.startsWith("http")) {
|
||||||
URI context = URI.create(playlistUrl);
|
URI context = URI.create(playlistUrl);
|
||||||
uri = context.resolve(uri).toURL().toExternalForm();
|
uri = context.resolve(uri).toURL().toExternalForm();
|
||||||
}
|
}
|
||||||
LOG.debug("Media url {}", uri);
|
log.debug("Media url {}", uri);
|
||||||
return uri;
|
return uri;
|
||||||
} else {
|
} else {
|
||||||
throw new InvalidPlaylistException("Playlist has no media");
|
throw new InvalidPlaylistException("Playlist has no media");
|
||||||
|
@ -281,7 +279,7 @@ public class FfmpegHlsDownload extends AbstractDownload {
|
||||||
.build();
|
.build();
|
||||||
try (Response resp = httpClient.execute(request)) {
|
try (Response resp = httpClient.execute(request)) {
|
||||||
if (resp.isSuccessful()) {
|
if (resp.isSuccessful()) {
|
||||||
LOG.debug("Recording video stream to {}", targetFile);
|
log.debug("Recording video stream to {}", targetFile);
|
||||||
InputStream in = Objects.requireNonNull(resp.body()).byteStream();
|
InputStream in = Objects.requireNonNull(resp.body()).byteStream();
|
||||||
byte[] b = new byte[1024 * 4];
|
byte[] b = new byte[1024 * 4];
|
||||||
int len;
|
int len;
|
||||||
|
@ -295,20 +293,20 @@ public class FfmpegHlsDownload extends AbstractDownload {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} catch (SocketTimeoutException e) {
|
} catch (SocketTimeoutException e) {
|
||||||
LOG.debug("Socket timeout while downloading MP4 for {}. Stop recording.", model.getName());
|
log.debug("Socket timeout while downloading MP4 for {}. Stop recording.", model.getName());
|
||||||
model.delay();
|
model.delay();
|
||||||
stop();
|
stop();
|
||||||
} catch (IOException e) {
|
} catch (IOException e) {
|
||||||
LOG.debug("IO error while downloading MP4 for {}. Stop recording.", model.getName());
|
log.debug("IO error while downloading MP4 for {}. Stop recording.", model.getName());
|
||||||
model.delay();
|
model.delay();
|
||||||
stop();
|
stop();
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
LOG.error("Error while downloading MP4", e);
|
log.error("Error while downloading MP4", e);
|
||||||
stop();
|
stop();
|
||||||
} finally {
|
} finally {
|
||||||
ffmpegStreamLock.unlock();
|
ffmpegStreamLock.unlock();
|
||||||
}
|
}
|
||||||
LOG.debug("Record finished for model {}", model);
|
log.debug("Record finished for model {}", model);
|
||||||
running = false;
|
running = false;
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,5 +1,7 @@
|
||||||
package ctbrec.recorder.download.hls;
|
package ctbrec.recorder.download.hls;
|
||||||
|
|
||||||
|
|
||||||
|
import lombok.extern.slf4j.Slf4j;
|
||||||
import com.iheartradio.m3u8.*;
|
import com.iheartradio.m3u8.*;
|
||||||
import com.iheartradio.m3u8.data.*;
|
import com.iheartradio.m3u8.data.*;
|
||||||
import ctbrec.Config;
|
import ctbrec.Config;
|
||||||
|
@ -8,9 +10,6 @@ import ctbrec.Recording;
|
||||||
import ctbrec.io.HttpClient;
|
import ctbrec.io.HttpClient;
|
||||||
import ctbrec.io.IoUtils;
|
import ctbrec.io.IoUtils;
|
||||||
import ctbrec.recorder.download.hls.SegmentPlaylist.Segment;
|
import ctbrec.recorder.download.hls.SegmentPlaylist.Segment;
|
||||||
import org.slf4j.Logger;
|
|
||||||
import org.slf4j.LoggerFactory;
|
|
||||||
|
|
||||||
import java.io.*;
|
import java.io.*;
|
||||||
import java.net.MalformedURLException;
|
import java.net.MalformedURLException;
|
||||||
import java.net.URL;
|
import java.net.URL;
|
||||||
|
@ -28,10 +27,8 @@ import java.util.concurrent.ExecutorService;
|
||||||
import java.util.concurrent.Future;
|
import java.util.concurrent.Future;
|
||||||
import java.util.regex.Pattern;
|
import java.util.regex.Pattern;
|
||||||
|
|
||||||
|
@Slf4j
|
||||||
public class HlsDownload extends AbstractHlsDownload {
|
public class HlsDownload extends AbstractHlsDownload {
|
||||||
|
|
||||||
private static final Logger LOG = LoggerFactory.getLogger(HlsDownload.class);
|
|
||||||
|
|
||||||
protected Path downloadDir;
|
protected Path downloadDir;
|
||||||
|
|
||||||
private final Queue<Future<SegmentDownload>> segmentDownloads = new LinkedList<>();
|
private final Queue<Future<SegmentDownload>> segmentDownloads = new LinkedList<>();
|
||||||
|
@ -101,16 +98,16 @@ public class HlsDownload extends AbstractHlsDownload {
|
||||||
writer.write(master);
|
writer.write(master);
|
||||||
}
|
}
|
||||||
} catch (PlaylistException e) {
|
} catch (PlaylistException e) {
|
||||||
LOG.error("Updating segment playlist failed", e);
|
log.error("Updating segment playlist failed", e);
|
||||||
if (e.getErrors() != null) {
|
if (e.getErrors() != null) {
|
||||||
for (PlaylistError error : e.getErrors()) {
|
for (PlaylistError error : e.getErrors()) {
|
||||||
LOG.error("Playlist Error: {}", error);
|
log.error("Playlist Error: {}", error);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} catch (IOException | ParseException e) {
|
} catch (IOException | ParseException e) {
|
||||||
LOG.error("Updating segment playlist failed", e);
|
log.error("Updating segment playlist failed", e);
|
||||||
}
|
}
|
||||||
LOG.trace("Segment queue size for {}: {}", model, segmentDownloads.size());
|
log.trace("Segment queue size for {}: {}", model, segmentDownloads.size());
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -129,7 +126,7 @@ public class HlsDownload extends AbstractHlsDownload {
|
||||||
} catch (InterruptedException e) {
|
} catch (InterruptedException e) {
|
||||||
Thread.currentThread().interrupt();
|
Thread.currentThread().interrupt();
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
LOG.info("Segment download failed for model {} - skipping adding segment to playlist", model);
|
log.info("Segment download failed for model {} - skipping adding segment to playlist", model);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -151,7 +148,7 @@ public class HlsDownload extends AbstractHlsDownload {
|
||||||
@Override
|
@Override
|
||||||
public void finalizeDownload() {
|
public void finalizeDownload() {
|
||||||
updatePlaylist(false);
|
updatePlaylist(false);
|
||||||
LOG.debug("Download for {} terminated", model);
|
log.debug("Download for {} terminated", model);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -161,7 +158,7 @@ public class HlsDownload extends AbstractHlsDownload {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void stop() {
|
public void stop() {
|
||||||
LOG.debug("Recording stopped");
|
log.debug("Recording stopped");
|
||||||
internalStop();
|
internalStop();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1,5 +1,7 @@
|
||||||
package ctbrec.recorder.download.hls;
|
package ctbrec.recorder.download.hls;
|
||||||
|
|
||||||
|
|
||||||
|
import lombok.extern.slf4j.Slf4j;
|
||||||
import java.io.File;
|
import java.io.File;
|
||||||
import java.io.FileOutputStream;
|
import java.io.FileOutputStream;
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
|
@ -14,9 +16,6 @@ import java.util.concurrent.ThreadFactory;
|
||||||
import java.util.function.Consumer;
|
import java.util.function.Consumer;
|
||||||
|
|
||||||
import org.json.JSONObject;
|
import org.json.JSONObject;
|
||||||
import org.slf4j.Logger;
|
|
||||||
import org.slf4j.LoggerFactory;
|
|
||||||
|
|
||||||
import com.fasterxml.jackson.annotation.JsonProperty;
|
import com.fasterxml.jackson.annotation.JsonProperty;
|
||||||
import com.fasterxml.jackson.core.JsonParseException;
|
import com.fasterxml.jackson.core.JsonParseException;
|
||||||
import com.fasterxml.jackson.core.JsonParser;
|
import com.fasterxml.jackson.core.JsonParser;
|
||||||
|
@ -30,10 +29,8 @@ import ctbrec.io.json.ObjectMapperFactory;
|
||||||
import ctbrec.recorder.download.ProcessExitedUncleanException;
|
import ctbrec.recorder.download.ProcessExitedUncleanException;
|
||||||
import lombok.Data;
|
import lombok.Data;
|
||||||
|
|
||||||
|
@Slf4j
|
||||||
public class Hlsdl {
|
public class Hlsdl {
|
||||||
|
|
||||||
private static final Logger LOG = LoggerFactory.getLogger(Hlsdl.class);
|
|
||||||
|
|
||||||
// private static ScheduledExecutorService processOutputReader = Executors.newScheduledThreadPool(2, createThreadFactory("hlsdl output stream reader"));
|
// private static ScheduledExecutorService processOutputReader = Executors.newScheduledThreadPool(2, createThreadFactory("hlsdl output stream reader"));
|
||||||
|
|
||||||
private final ObjectMapper mapper = ObjectMapperFactory.getMapper();
|
private final ObjectMapper mapper = ObjectMapperFactory.getMapper();
|
||||||
|
@ -61,7 +58,7 @@ public class Hlsdl {
|
||||||
}
|
}
|
||||||
|
|
||||||
public void exec(String[] cmdline, String[] env, File executionDir) throws IOException {
|
public void exec(String[] cmdline, String[] env, File executionDir) throws IOException {
|
||||||
LOG.debug("hlsdl command line: {}", Arrays.toString(cmdline));
|
log.debug("hlsdl command line: {}", Arrays.toString(cmdline));
|
||||||
// process = Runtime.getRuntime().exec(cmdline, env, executionDir);
|
// process = Runtime.getRuntime().exec(cmdline, env, executionDir);
|
||||||
var builder = new ProcessBuilder(cmdline).directory(executionDir);
|
var builder = new ProcessBuilder(cmdline).directory(executionDir);
|
||||||
builder.redirectErrorStream(true);
|
builder.redirectErrorStream(true);
|
||||||
|
@ -72,14 +69,14 @@ public class Hlsdl {
|
||||||
|
|
||||||
|
|
||||||
public void shutdown(int exitCode) throws IOException {
|
public void shutdown(int exitCode) throws IOException {
|
||||||
LOG.debug("hlsdl exit code was {}", exitCode);
|
log.debug("hlsdl exit code was {}", exitCode);
|
||||||
processLogStream.flush();
|
processLogStream.flush();
|
||||||
processLogStream.close();
|
processLogStream.close();
|
||||||
streamReaderThread.interrupt();
|
streamReaderThread.interrupt();
|
||||||
try {
|
try {
|
||||||
streamReaderThread.join();
|
streamReaderThread.join();
|
||||||
} catch (InterruptedException e) {
|
} catch (InterruptedException e) {
|
||||||
LOG.warn("interrupted while joining stream reader thread: {}", e);
|
log.warn("interrupted while joining stream reader thread: {}", e);
|
||||||
}
|
}
|
||||||
// stdoutRedirector.setKeepGoing(false);
|
// stdoutRedirector.setKeepGoing(false);
|
||||||
// stderrRedirector.setKeepGoing(false);
|
// stderrRedirector.setKeepGoing(false);
|
||||||
|
@ -98,7 +95,7 @@ public class Hlsdl {
|
||||||
if (processLog == null) {
|
if (processLog == null) {
|
||||||
processLog = File.createTempFile("hlsdl_", ".log");
|
processLog = File.createTempFile("hlsdl_", ".log");
|
||||||
}
|
}
|
||||||
LOG.debug("Logging hlsdl output to {}", processLog);
|
log.debug("Logging hlsdl output to {}", processLog);
|
||||||
processLog.deleteOnExit();
|
processLog.deleteOnExit();
|
||||||
processLogStream = new FileOutputStream(processLog);
|
processLogStream = new FileOutputStream(processLog);
|
||||||
} else {
|
} else {
|
||||||
|
@ -119,7 +116,7 @@ public class Hlsdl {
|
||||||
var line = process.inputReader().readLine();
|
var line = process.inputReader().readLine();
|
||||||
|
|
||||||
if (line == null) {
|
if (line == null) {
|
||||||
LOG.trace("stream ended");
|
log.trace("stream ended");
|
||||||
w.close();
|
w.close();
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
@ -140,7 +137,7 @@ public class Hlsdl {
|
||||||
}
|
}
|
||||||
} catch (IOException e) {
|
} catch (IOException e) {
|
||||||
if (process.isAlive())
|
if (process.isAlive())
|
||||||
LOG.debug("Error in stream while process is still alive {}", e);
|
log.debug("Error in stream while process is still alive {}", e);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
@ -149,7 +146,7 @@ public class Hlsdl {
|
||||||
try {
|
try {
|
||||||
startCallback.accept(process);
|
startCallback.accept(process);
|
||||||
} catch(Exception e) {
|
} catch(Exception e) {
|
||||||
LOG.error("Exception in onStart callback", e);
|
log.error("Exception in onStart callback", e);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -157,7 +154,7 @@ public class Hlsdl {
|
||||||
try {
|
try {
|
||||||
exitCallback.accept(exitCode);
|
exitCallback.accept(exitCode);
|
||||||
} catch(Exception e) {
|
} catch(Exception e) {
|
||||||
LOG.error("Exception in onExit callback", e);
|
log.error("Exception in onExit callback", e);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -166,7 +163,7 @@ public class Hlsdl {
|
||||||
try {
|
try {
|
||||||
shutdown(exitCode);
|
shutdown(exitCode);
|
||||||
} catch (IOException e) {
|
} catch (IOException e) {
|
||||||
LOG.error("Error while shutting down hlsdl process", e);
|
log.error("Error while shutting down hlsdl process", e);
|
||||||
}
|
}
|
||||||
return exitCode;
|
return exitCode;
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,5 +1,7 @@
|
||||||
package ctbrec.recorder.download.hls;
|
package ctbrec.recorder.download.hls;
|
||||||
|
|
||||||
|
|
||||||
|
import lombok.extern.slf4j.Slf4j;
|
||||||
import com.iheartradio.m3u8.ParseException;
|
import com.iheartradio.m3u8.ParseException;
|
||||||
import com.iheartradio.m3u8.PlaylistException;
|
import com.iheartradio.m3u8.PlaylistException;
|
||||||
import ctbrec.Config;
|
import ctbrec.Config;
|
||||||
|
@ -9,9 +11,6 @@ import ctbrec.Recording;
|
||||||
import ctbrec.recorder.download.AbstractDownload;
|
import ctbrec.recorder.download.AbstractDownload;
|
||||||
import ctbrec.recorder.download.ProcessExitedUncleanException;
|
import ctbrec.recorder.download.ProcessExitedUncleanException;
|
||||||
import ctbrec.recorder.download.StreamSource;
|
import ctbrec.recorder.download.StreamSource;
|
||||||
import org.slf4j.Logger;
|
|
||||||
import org.slf4j.LoggerFactory;
|
|
||||||
|
|
||||||
import javax.xml.bind.JAXBException;
|
import javax.xml.bind.JAXBException;
|
||||||
import java.io.File;
|
import java.io.File;
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
|
@ -29,10 +28,8 @@ import java.util.regex.Pattern;
|
||||||
import static ctbrec.recorder.download.StreamSource.UNKNOWN;
|
import static ctbrec.recorder.download.StreamSource.UNKNOWN;
|
||||||
import static java.util.concurrent.TimeUnit.SECONDS;
|
import static java.util.concurrent.TimeUnit.SECONDS;
|
||||||
|
|
||||||
|
@Slf4j
|
||||||
public class HlsdlDownload extends AbstractDownload {
|
public class HlsdlDownload extends AbstractDownload {
|
||||||
|
|
||||||
private static final Logger LOG = LoggerFactory.getLogger(HlsdlDownload.class);
|
|
||||||
|
|
||||||
protected File targetFile;
|
protected File targetFile;
|
||||||
|
|
||||||
private transient Hlsdl hlsdl;
|
private transient Hlsdl hlsdl;
|
||||||
|
@ -79,12 +76,12 @@ public class HlsdlDownload extends AbstractDownload {
|
||||||
} else {
|
} else {
|
||||||
int seconds = 90;
|
int seconds = 90;
|
||||||
if (Duration.between(lastSizeChange, Instant.now()).toMillis() > SECONDS.toMillis(seconds)) {
|
if (Duration.between(lastSizeChange, Instant.now()).toMillis() > SECONDS.toMillis(seconds)) {
|
||||||
LOG.info("Recording size didn't change for {} secs. Stopping recording for {}", seconds, model);
|
log.info("Recording size didn't change for {} secs. Stopping recording for {}", seconds, model);
|
||||||
stop();
|
stop();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} catch (ProcessExitedUncleanException e) {
|
} catch (ProcessExitedUncleanException e) {
|
||||||
LOG.error("hlsdl exited unclean", e);
|
log.error("hlsdl exited unclean", e);
|
||||||
}
|
}
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
@ -98,7 +95,7 @@ public class HlsdlDownload extends AbstractDownload {
|
||||||
.build();
|
.build();
|
||||||
hlsdl.exec(cmdline, OS.getEnvironment(), targetFile.getParentFile());
|
hlsdl.exec(cmdline, OS.getEnvironment(), targetFile.getParentFile());
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
LOG.error("Error starting hlsdl", e);
|
log.error("Error starting hlsdl", e);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -124,16 +121,16 @@ public class HlsdlDownload extends AbstractDownload {
|
||||||
}
|
}
|
||||||
|
|
||||||
protected String getSegmentPlaylistUrl(Model model) throws IOException, ExecutionException, ParseException, PlaylistException, JAXBException {
|
protected String getSegmentPlaylistUrl(Model model) throws IOException, ExecutionException, ParseException, PlaylistException, JAXBException {
|
||||||
LOG.debug("{} stream idx: {}", model.getName(), model.getStreamUrlIndex());
|
log.debug("{} stream idx: {}", model.getName(), model.getStreamUrlIndex());
|
||||||
List<StreamSource> streamSources = model.getStreamSources();
|
List<StreamSource> streamSources = model.getStreamSources();
|
||||||
Collections.sort(streamSources);
|
Collections.sort(streamSources);
|
||||||
for (StreamSource streamSource : streamSources) {
|
for (StreamSource streamSource : streamSources) {
|
||||||
LOG.debug("{} src {}", model.getName(), streamSource);
|
log.debug("{} src {}", model.getName(), streamSource);
|
||||||
}
|
}
|
||||||
String url = null;
|
String url = null;
|
||||||
if (model.getStreamUrlIndex() >= 0 && model.getStreamUrlIndex() < streamSources.size()) {
|
if (model.getStreamUrlIndex() >= 0 && model.getStreamUrlIndex() < streamSources.size()) {
|
||||||
// TODO don't use the index, but the bandwidth. if the bandwidth does not match, take the closest one
|
// TODO don't use the index, but the bandwidth. if the bandwidth does not match, take the closest one
|
||||||
LOG.debug("{} selected {}", model.getName(), streamSources.get(model.getStreamUrlIndex()));
|
log.debug("{} selected {}", model.getName(), streamSources.get(model.getStreamUrlIndex()));
|
||||||
url = streamSources.get(model.getStreamUrlIndex()).getMediaPlaylistUrl();
|
url = streamSources.get(model.getStreamUrlIndex()).getMediaPlaylistUrl();
|
||||||
} else {
|
} else {
|
||||||
// filter out stream resolutions, which are out of range of the configured min and max
|
// filter out stream resolutions, which are out of range of the configured min and max
|
||||||
|
@ -147,11 +144,11 @@ public class HlsdlDownload extends AbstractDownload {
|
||||||
if (filteredStreamSources.isEmpty()) {
|
if (filteredStreamSources.isEmpty()) {
|
||||||
throw new ExecutionException(new NoStreamFoundException("No stream left in playlist"));
|
throw new ExecutionException(new NoStreamFoundException("No stream left in playlist"));
|
||||||
} else {
|
} else {
|
||||||
LOG.debug("{} selected {}", model.getName(), filteredStreamSources.get(filteredStreamSources.size() - 1));
|
log.debug("{} selected {}", model.getName(), filteredStreamSources.get(filteredStreamSources.size() - 1));
|
||||||
url = filteredStreamSources.get(filteredStreamSources.size() - 1).getMediaPlaylistUrl();
|
url = filteredStreamSources.get(filteredStreamSources.size() - 1).getMediaPlaylistUrl();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
LOG.debug("Segment playlist url {}", url);
|
log.debug("Segment playlist url {}", url);
|
||||||
return url;
|
return url;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -162,7 +159,7 @@ public class HlsdlDownload extends AbstractDownload {
|
||||||
if (hlsdlProcess != null) {
|
if (hlsdlProcess != null) {
|
||||||
hlsdlProcess.destroy();
|
hlsdlProcess.destroy();
|
||||||
if (hlsdlProcess.isAlive()) {
|
if (hlsdlProcess.isAlive()) {
|
||||||
LOG.info("hlsdl didn't terminate. Destroying the process with force!");
|
log.info("hlsdl didn't terminate. Destroying the process with force!");
|
||||||
hlsdlProcess.destroyForcibly();
|
hlsdlProcess.destroyForcibly();
|
||||||
hlsdlProcess = null;
|
hlsdlProcess = null;
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,5 +1,7 @@
|
||||||
package ctbrec.recorder.download.hls;
|
package ctbrec.recorder.download.hls;
|
||||||
|
|
||||||
|
|
||||||
|
import lombok.extern.slf4j.Slf4j;
|
||||||
import ctbrec.Config;
|
import ctbrec.Config;
|
||||||
import ctbrec.Model;
|
import ctbrec.Model;
|
||||||
import ctbrec.OS;
|
import ctbrec.OS;
|
||||||
|
@ -9,10 +11,6 @@ import ctbrec.recorder.FFmpeg;
|
||||||
import ctbrec.recorder.SimplifiedLocalRecorder;
|
import ctbrec.recorder.SimplifiedLocalRecorder;
|
||||||
import ctbrec.recorder.download.ProcessExitedUncleanException;
|
import ctbrec.recorder.download.ProcessExitedUncleanException;
|
||||||
import ctbrec.recorder.download.hls.SegmentPlaylist.Segment;
|
import ctbrec.recorder.download.hls.SegmentPlaylist.Segment;
|
||||||
|
|
||||||
import org.slf4j.Logger;
|
|
||||||
import org.slf4j.LoggerFactory;
|
|
||||||
|
|
||||||
import java.io.ByteArrayOutputStream;
|
import java.io.ByteArrayOutputStream;
|
||||||
import java.io.File;
|
import java.io.File;
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
|
@ -25,10 +23,8 @@ import java.util.concurrent.locks.Condition;
|
||||||
import java.util.concurrent.locks.ReentrantLock;
|
import java.util.concurrent.locks.ReentrantLock;
|
||||||
import java.util.regex.Pattern;
|
import java.util.regex.Pattern;
|
||||||
|
|
||||||
|
@Slf4j
|
||||||
public class MergedFfmpegHlsDownload extends AbstractHlsDownload {
|
public class MergedFfmpegHlsDownload extends AbstractHlsDownload {
|
||||||
|
|
||||||
private static final Logger LOG = LoggerFactory.getLogger(MergedFfmpegHlsDownload.class);
|
|
||||||
|
|
||||||
protected File targetFile;
|
protected File targetFile;
|
||||||
protected FFmpeg ffmpeg;
|
protected FFmpeg ffmpeg;
|
||||||
protected Process ffmpegProcess;
|
protected Process ffmpegProcess;
|
||||||
|
@ -57,7 +53,7 @@ public class MergedFfmpegHlsDownload extends AbstractHlsDownload {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void init(Config config, Model model, Instant startTime, ExecutorService executorService) throws IOException {
|
public void init(Config config, Model model, Instant startTime, ExecutorService executorService) throws IOException {
|
||||||
LOG.debug("init start");
|
log.debug("init start");
|
||||||
super.init(config, model, startTime, executorService);
|
super.init(config, model, startTime, executorService);
|
||||||
String fileSuffix = config.getSettings().ffmpegFileSuffix;
|
String fileSuffix = config.getSettings().ffmpegFileSuffix;
|
||||||
targetFile = config.getFileForRecording(model, fileSuffix, startTime);
|
targetFile = config.getFileForRecording(model, fileSuffix, startTime);
|
||||||
|
@ -83,7 +79,7 @@ public class MergedFfmpegHlsDownload extends AbstractHlsDownload {
|
||||||
ffmpeg.shutdown(exitValue);
|
ffmpeg.shutdown(exitValue);
|
||||||
}
|
}
|
||||||
} catch (ProcessExitedUncleanException e) {
|
} catch (ProcessExitedUncleanException e) {
|
||||||
LOG.error("FFmpeg exited unclean", e);
|
log.error("FFmpeg exited unclean", e);
|
||||||
}
|
}
|
||||||
|
|
||||||
return this;
|
return this;
|
||||||
|
@ -114,10 +110,10 @@ public class MergedFfmpegHlsDownload extends AbstractHlsDownload {
|
||||||
downloadData.writeTo(ffmpegStdIn);
|
downloadData.writeTo(ffmpegStdIn);
|
||||||
lastSegmentDownload = Instant.now();
|
lastSegmentDownload = Instant.now();
|
||||||
} catch (InterruptedException e) {
|
} catch (InterruptedException e) {
|
||||||
LOG.trace("Segment download interrupted for model {}", model, e);
|
log.trace("Segment download interrupted for model {}", model, e);
|
||||||
Thread.currentThread().interrupt();
|
Thread.currentThread().interrupt();
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
LOG.error("Segment download failed for model {}", model, e);
|
log.error("Segment download failed for model {}", model, e);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -144,7 +140,7 @@ public class MergedFfmpegHlsDownload extends AbstractHlsDownload {
|
||||||
.build();
|
.build();
|
||||||
ffmpeg.exec(cmdline, new String[0], target.getParentFile());
|
ffmpeg.exec(cmdline, new String[0], target.getParentFile());
|
||||||
} catch (IOException | ProcessExitedUncleanException e) {
|
} catch (IOException | ProcessExitedUncleanException e) {
|
||||||
LOG.error("Error in FFmpeg thread", e);
|
log.error("Error in FFmpeg thread", e);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -175,7 +171,7 @@ public class MergedFfmpegHlsDownload extends AbstractHlsDownload {
|
||||||
SimplifiedLocalRecorder.STATS.errorCount++;
|
SimplifiedLocalRecorder.STATS.errorCount++;
|
||||||
throw e;
|
throw e;
|
||||||
}
|
}
|
||||||
LOG.trace("Enqueuing segment for file {}", targetFile);
|
log.trace("Enqueuing segment for file {}", targetFile);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -204,7 +200,7 @@ public class MergedFfmpegHlsDownload extends AbstractHlsDownload {
|
||||||
try {
|
try {
|
||||||
ffmpegStdIn.close();
|
ffmpegStdIn.close();
|
||||||
} catch (IOException e) {
|
} catch (IOException e) {
|
||||||
LOG.error("Couldn't terminate FFmpeg by closing stdin", e);
|
log.error("Couldn't terminate FFmpeg by closing stdin", e);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -214,13 +210,13 @@ public class MergedFfmpegHlsDownload extends AbstractHlsDownload {
|
||||||
if (!waitFor && ffmpegProcess.isAlive()) {
|
if (!waitFor && ffmpegProcess.isAlive()) {
|
||||||
ffmpegProcess.destroy();
|
ffmpegProcess.destroy();
|
||||||
if (ffmpegProcess.isAlive()) {
|
if (ffmpegProcess.isAlive()) {
|
||||||
LOG.info("FFmpeg didn't terminate. Destroying the process with force!");
|
log.info("FFmpeg didn't terminate. Destroying the process with force!");
|
||||||
ffmpegProcess.destroyForcibly();
|
ffmpegProcess.destroyForcibly();
|
||||||
ffmpegProcess = null;
|
ffmpegProcess = null;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} catch (InterruptedException e) {
|
} catch (InterruptedException e) {
|
||||||
LOG.error("Interrupted while waiting for FFmpeg to terminate");
|
log.error("Interrupted while waiting for FFmpeg to terminate");
|
||||||
Thread.currentThread().interrupt();
|
Thread.currentThread().interrupt();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,5 +1,7 @@
|
||||||
package ctbrec.recorder.download.hls;
|
package ctbrec.recorder.download.hls;
|
||||||
|
|
||||||
|
|
||||||
|
import lombok.extern.slf4j.Slf4j;
|
||||||
import ctbrec.Model;
|
import ctbrec.Model;
|
||||||
import ctbrec.io.BandwidthMeter;
|
import ctbrec.io.BandwidthMeter;
|
||||||
import ctbrec.io.HttpClient;
|
import ctbrec.io.HttpClient;
|
||||||
|
@ -9,9 +11,6 @@ import ctbrec.recorder.download.hls.SegmentPlaylist.Segment;
|
||||||
import okhttp3.Request;
|
import okhttp3.Request;
|
||||||
import okhttp3.Request.Builder;
|
import okhttp3.Request.Builder;
|
||||||
import okhttp3.Response;
|
import okhttp3.Response;
|
||||||
import org.slf4j.Logger;
|
|
||||||
import org.slf4j.LoggerFactory;
|
|
||||||
|
|
||||||
import com.fasterxml.jackson.datatype.jsr310.deser.DurationDeserializer;
|
import com.fasterxml.jackson.datatype.jsr310.deser.DurationDeserializer;
|
||||||
|
|
||||||
import javax.crypto.NoSuchPaddingException;
|
import javax.crypto.NoSuchPaddingException;
|
||||||
|
@ -32,9 +31,8 @@ import java.time.Duration;
|
||||||
import static ctbrec.ErrorMessages.HTTP_RESPONSE_BODY_IS_NULL;
|
import static ctbrec.ErrorMessages.HTTP_RESPONSE_BODY_IS_NULL;
|
||||||
import static ctbrec.recorder.download.hls.AbstractHlsDownload.addHeaders;
|
import static ctbrec.recorder.download.hls.AbstractHlsDownload.addHeaders;
|
||||||
|
|
||||||
|
@Slf4j
|
||||||
public class SegmentDownload implements Callable<SegmentDownload> {
|
public class SegmentDownload implements Callable<SegmentDownload> {
|
||||||
private static final Logger LOG = LoggerFactory.getLogger(SegmentDownload.class);
|
|
||||||
|
|
||||||
protected final URL url;
|
protected final URL url;
|
||||||
protected final HttpClient client;
|
protected final HttpClient client;
|
||||||
protected final SegmentPlaylist playlist;
|
protected final SegmentPlaylist playlist;
|
||||||
|
@ -65,7 +63,7 @@ public class SegmentDownload implements Callable<SegmentDownload> {
|
||||||
for (int tries = 1; tries <= 3 && !Thread.currentThread().isInterrupted(); tries++) { // NOSONAR
|
for (int tries = 1; tries <= 3 && !Thread.currentThread().isInterrupted(); tries++) { // NOSONAR
|
||||||
if (expiresAt.isBefore(Instant.now())) {
|
if (expiresAt.isBefore(Instant.now())) {
|
||||||
// segment has sexpired, skip it
|
// segment has sexpired, skip it
|
||||||
LOG.warn("Segment for model {} is late {} seconds", model, Duration.between(expiresAt, Instant.now()));
|
log.warn("Segment for model {} is late {} seconds", model, Duration.between(expiresAt, Instant.now()));
|
||||||
failed = true;
|
failed = true;
|
||||||
exception = new Exception("Segment expired");
|
exception = new Exception("Segment expired");
|
||||||
break;
|
break;
|
||||||
|
@ -76,7 +74,7 @@ public class SegmentDownload implements Callable<SegmentDownload> {
|
||||||
handleResponse(response);
|
handleResponse(response);
|
||||||
break;
|
break;
|
||||||
} catch (FileNotFoundException e) {
|
} catch (FileNotFoundException e) {
|
||||||
LOG.debug("Segment does not exist {}", url.getFile());
|
log.debug("Segment does not exist {}", url.getFile());
|
||||||
failed = true;
|
failed = true;
|
||||||
exception = e;
|
exception = e;
|
||||||
break;
|
break;
|
||||||
|
@ -86,11 +84,11 @@ public class SegmentDownload implements Callable<SegmentDownload> {
|
||||||
break;
|
break;
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
if (tries == 3) {
|
if (tries == 3) {
|
||||||
LOG.warn("Error while downloading segment for {}. Segment {} finally failed: {}", model, url, e.getMessage());
|
log.warn("Error while downloading segment for {}. Segment {} finally failed: {}", model, url, e.getMessage());
|
||||||
failed = true;
|
failed = true;
|
||||||
exception = e;
|
exception = e;
|
||||||
} else {
|
} else {
|
||||||
LOG.debug("Error while downloading segment {} for {} on try {} - {}", url, model, tries, e.getMessage());
|
log.debug("Error while downloading segment {} for {} on try {} - {}", url, model, tries, e.getMessage());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,19 +1,17 @@
|
||||||
package ctbrec.recorder.postprocessing;
|
package ctbrec.recorder.postprocessing;
|
||||||
|
|
||||||
|
|
||||||
|
import lombok.extern.slf4j.Slf4j;
|
||||||
import java.io.File;
|
import java.io.File;
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.nio.file.Files;
|
import java.nio.file.Files;
|
||||||
|
|
||||||
import org.apache.commons.io.FileUtils;
|
import org.apache.commons.io.FileUtils;
|
||||||
import org.slf4j.Logger;
|
|
||||||
import org.slf4j.LoggerFactory;
|
|
||||||
|
|
||||||
import ctbrec.Recording;
|
import ctbrec.Recording;
|
||||||
|
|
||||||
|
@Slf4j
|
||||||
public class Copy extends AbstractPostProcessor {
|
public class Copy extends AbstractPostProcessor {
|
||||||
|
|
||||||
private static final transient Logger LOG = LoggerFactory.getLogger(Copy.class);
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public String getName() {
|
public String getName() {
|
||||||
return "create a copy";
|
return "create a copy";
|
||||||
|
@ -25,7 +23,7 @@ public class Copy extends AbstractPostProcessor {
|
||||||
File orig = rec.getPostProcessedFile();
|
File orig = rec.getPostProcessedFile();
|
||||||
String copyFilename = getFilenameForCopy(orig);
|
String copyFilename = getFilenameForCopy(orig);
|
||||||
File copy = new File(orig.getParentFile(), copyFilename);
|
File copy = new File(orig.getParentFile(), copyFilename);
|
||||||
LOG.info("Creating a copy {}", copy);
|
log.info("Creating a copy {}", copy);
|
||||||
if (orig.isFile()) {
|
if (orig.isFile()) {
|
||||||
Files.copy(rec.getPostProcessedFile().toPath(), copy.toPath());
|
Files.copy(rec.getPostProcessedFile().toPath(), copy.toPath());
|
||||||
} else {
|
} else {
|
||||||
|
|
|
@ -1,5 +1,7 @@
|
||||||
package ctbrec.recorder.postprocessing;
|
package ctbrec.recorder.postprocessing;
|
||||||
|
|
||||||
|
|
||||||
|
import lombok.extern.slf4j.Slf4j;
|
||||||
import static java.lang.Boolean.*;
|
import static java.lang.Boolean.*;
|
||||||
|
|
||||||
import java.io.File;
|
import java.io.File;
|
||||||
|
@ -11,10 +13,6 @@ import java.text.MessageFormat;
|
||||||
import java.text.NumberFormat;
|
import java.text.NumberFormat;
|
||||||
import java.util.Arrays;
|
import java.util.Arrays;
|
||||||
import java.util.Locale;
|
import java.util.Locale;
|
||||||
|
|
||||||
import org.slf4j.Logger;
|
|
||||||
import org.slf4j.LoggerFactory;
|
|
||||||
|
|
||||||
import ctbrec.Config;
|
import ctbrec.Config;
|
||||||
import ctbrec.OS;
|
import ctbrec.OS;
|
||||||
import ctbrec.Recording;
|
import ctbrec.Recording;
|
||||||
|
@ -22,10 +20,8 @@ import ctbrec.io.IoUtils;
|
||||||
import ctbrec.recorder.FFmpeg;
|
import ctbrec.recorder.FFmpeg;
|
||||||
import ctbrec.recorder.download.ProcessExitedUncleanException;
|
import ctbrec.recorder.download.ProcessExitedUncleanException;
|
||||||
|
|
||||||
|
@Slf4j
|
||||||
public class CreateContactSheet extends AbstractPlaceholderAwarePostProcessor {
|
public class CreateContactSheet extends AbstractPlaceholderAwarePostProcessor {
|
||||||
|
|
||||||
private static final Logger LOG = LoggerFactory.getLogger(CreateContactSheet.class);
|
|
||||||
|
|
||||||
public static final String TOTAL_SIZE = "total_size";
|
public static final String TOTAL_SIZE = "total_size";
|
||||||
public static final String PADDING = "padding";
|
public static final String PADDING = "padding";
|
||||||
public static final String COLS = "columns";
|
public static final String COLS = "columns";
|
||||||
|
@ -79,7 +75,7 @@ public class CreateContactSheet extends AbstractPlaceholderAwarePostProcessor {
|
||||||
output.getCanonicalPath()
|
output.getCanonicalPath()
|
||||||
};
|
};
|
||||||
String[] cmdline = OS.getFFmpegCommand(args);
|
String[] cmdline = OS.getFFmpegCommand(args);
|
||||||
LOG.trace("Executing {} in working directory {}", Arrays.toString(cmdline), executionDir);
|
log.trace("Executing {} in working directory {}", Arrays.toString(cmdline), executionDir);
|
||||||
File ffmpegLog = new File(System.getProperty("java.io.tmpdir"), "create_contact_sheet_" + rec.getId() + ".log");
|
File ffmpegLog = new File(System.getProperty("java.io.tmpdir"), "create_contact_sheet_" + rec.getId() + ".log");
|
||||||
FFmpeg ffmpeg = new FFmpeg.Builder()
|
FFmpeg ffmpeg = new FFmpeg.Builder()
|
||||||
.logOutput(config.getSettings().logFFmpegOutput)
|
.logOutput(config.getSettings().logFFmpegOutput)
|
||||||
|
@ -147,7 +143,7 @@ public class CreateContactSheet extends AbstractPlaceholderAwarePostProcessor {
|
||||||
output.getCanonicalPath()
|
output.getCanonicalPath()
|
||||||
};
|
};
|
||||||
String[] cmdline = OS.getFFmpegCommand(args);
|
String[] cmdline = OS.getFFmpegCommand(args);
|
||||||
LOG.trace("Executing {} in working directory {}", Arrays.toString(cmdline), executionDir);
|
log.trace("Executing {} in working directory {}", Arrays.toString(cmdline), executionDir);
|
||||||
|
|
||||||
FFmpeg ffmpeg = new FFmpeg.Builder()
|
FFmpeg ffmpeg = new FFmpeg.Builder()
|
||||||
.logOutput(config.getSettings().logFFmpegOutput)
|
.logOutput(config.getSettings().logFFmpegOutput)
|
||||||
|
|
|
@ -1,10 +1,9 @@
|
||||||
package ctbrec.recorder.postprocessing;
|
package ctbrec.recorder.postprocessing;
|
||||||
|
|
||||||
|
|
||||||
|
import lombok.extern.slf4j.Slf4j;
|
||||||
import ctbrec.Recording;
|
import ctbrec.Recording;
|
||||||
import org.apache.commons.io.FileUtils;
|
import org.apache.commons.io.FileUtils;
|
||||||
import org.slf4j.Logger;
|
|
||||||
import org.slf4j.LoggerFactory;
|
|
||||||
|
|
||||||
import java.io.File;
|
import java.io.File;
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.nio.file.Files;
|
import java.nio.file.Files;
|
||||||
|
@ -12,9 +11,8 @@ import java.util.Objects;
|
||||||
|
|
||||||
import static ctbrec.io.IoUtils.deleteEmptyParents;
|
import static ctbrec.io.IoUtils.deleteEmptyParents;
|
||||||
|
|
||||||
|
@Slf4j
|
||||||
public class Move extends AbstractPlaceholderAwarePostProcessor {
|
public class Move extends AbstractPlaceholderAwarePostProcessor {
|
||||||
|
|
||||||
private static final Logger LOG = LoggerFactory.getLogger(Move.class);
|
|
||||||
public static final String PATH_TEMPLATE = "path.template";
|
public static final String PATH_TEMPLATE = "path.template";
|
||||||
public static final String DEFAULT = "$sanitize(${modelName})" + File.separatorChar + "$format(${localDateTime})";
|
public static final String DEFAULT = "$sanitize(${modelName})" + File.separatorChar + "$format(${localDateTime})";
|
||||||
|
|
||||||
|
@ -34,7 +32,7 @@ public class Move extends AbstractPlaceholderAwarePostProcessor {
|
||||||
if (Objects.equals(src, target)) {
|
if (Objects.equals(src, target)) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
LOG.info("Moving {} to {}", src.getName(), target.getParentFile().getCanonicalPath());
|
log.info("Moving {} to {}", src.getName(), target.getParentFile().getCanonicalPath());
|
||||||
Files.createDirectories(target.getParentFile().toPath());
|
Files.createDirectories(target.getParentFile().toPath());
|
||||||
if (rec.getPostProcessedFile().isDirectory()) {
|
if (rec.getPostProcessedFile().isDirectory()) {
|
||||||
FileUtils.moveDirectory(rec.getPostProcessedFile(), target);
|
FileUtils.moveDirectory(rec.getPostProcessedFile(), target);
|
||||||
|
|
|
@ -1,23 +1,19 @@
|
||||||
package ctbrec.recorder.postprocessing;
|
package ctbrec.recorder.postprocessing;
|
||||||
|
|
||||||
|
|
||||||
|
import lombok.extern.slf4j.Slf4j;
|
||||||
import java.io.File;
|
import java.io.File;
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.nio.file.Files;
|
import java.nio.file.Files;
|
||||||
import java.util.Arrays;
|
import java.util.Arrays;
|
||||||
import java.util.Objects;
|
import java.util.Objects;
|
||||||
|
|
||||||
import org.slf4j.Logger;
|
|
||||||
import org.slf4j.LoggerFactory;
|
|
||||||
|
|
||||||
import ctbrec.OS;
|
import ctbrec.OS;
|
||||||
import ctbrec.Recording;
|
import ctbrec.Recording;
|
||||||
import ctbrec.io.IoUtils;
|
import ctbrec.io.IoUtils;
|
||||||
import ctbrec.recorder.FFmpeg;
|
import ctbrec.recorder.FFmpeg;
|
||||||
|
|
||||||
|
@Slf4j
|
||||||
public class Remux extends AbstractPostProcessor {
|
public class Remux extends AbstractPostProcessor {
|
||||||
|
|
||||||
private static final Logger LOG = LoggerFactory.getLogger(Remux.class);
|
|
||||||
|
|
||||||
public static final String PRE_FFMPEG_ARGS = "preffmpeg.args";
|
public static final String PRE_FFMPEG_ARGS = "preffmpeg.args";
|
||||||
public static final String FFMPEG_ARGS = "ffmpeg.args";
|
public static final String FFMPEG_ARGS = "ffmpeg.args";
|
||||||
public static final String FILE_EXT = "file.ext";
|
public static final String FILE_EXT = "file.ext";
|
||||||
|
@ -40,7 +36,7 @@ public class Remux extends AbstractPostProcessor {
|
||||||
File remuxedFile = new File(rec.getPostProcessedFile().getAbsolutePath() + '.' + fileExt);
|
File remuxedFile = new File(rec.getPostProcessedFile().getAbsolutePath() + '.' + fileExt);
|
||||||
String[] cmdline = prepareCommandline(inputFile, remuxedFile);
|
String[] cmdline = prepareCommandline(inputFile, remuxedFile);
|
||||||
File executionDir = rec.getPostProcessedFile().isDirectory() ? rec.getPostProcessedFile() : rec.getPostProcessedFile().getParentFile();
|
File executionDir = rec.getPostProcessedFile().isDirectory() ? rec.getPostProcessedFile() : rec.getPostProcessedFile().getParentFile();
|
||||||
LOG.info("Executing {} in working directory {}", Arrays.toString(cmdline), executionDir);
|
log.info("Executing {} in working directory {}", Arrays.toString(cmdline), executionDir);
|
||||||
|
|
||||||
File ffmpegLog = new File(System.getProperty("java.io.tmpdir"), "remux_" + rec.getId() + ".log");
|
File ffmpegLog = new File(System.getProperty("java.io.tmpdir"), "remux_" + rec.getId() + ".log");
|
||||||
FFmpeg ffmpeg = new FFmpeg.Builder()
|
FFmpeg ffmpeg = new FFmpeg.Builder()
|
||||||
|
@ -74,7 +70,7 @@ public class Remux extends AbstractPostProcessor {
|
||||||
rec.getAssociatedFiles().remove(inputFile.getCanonicalPath());
|
rec.getAssociatedFiles().remove(inputFile.getCanonicalPath());
|
||||||
rec.getAssociatedFiles().add(remuxedFile.getCanonicalPath());
|
rec.getAssociatedFiles().add(remuxedFile.getCanonicalPath());
|
||||||
} catch (IOException e) {
|
} catch (IOException e) {
|
||||||
LOG.error("Couldn't finalize remux post-processing step", e);
|
log.error("Couldn't finalize remux post-processing step", e);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,17 +1,15 @@
|
||||||
package ctbrec.recorder.postprocessing;
|
package ctbrec.recorder.postprocessing;
|
||||||
|
|
||||||
import ctbrec.Recording;
|
|
||||||
import org.slf4j.Logger;
|
|
||||||
import org.slf4j.LoggerFactory;
|
|
||||||
|
|
||||||
|
import lombok.extern.slf4j.Slf4j;
|
||||||
|
import ctbrec.Recording;
|
||||||
import java.io.File;
|
import java.io.File;
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.nio.file.Files;
|
import java.nio.file.Files;
|
||||||
import java.util.Objects;
|
import java.util.Objects;
|
||||||
|
|
||||||
|
@Slf4j
|
||||||
public class Rename extends AbstractPlaceholderAwarePostProcessor {
|
public class Rename extends AbstractPlaceholderAwarePostProcessor {
|
||||||
|
|
||||||
private static final Logger LOG = LoggerFactory.getLogger(Rename.class);
|
|
||||||
public static final String FILE_NAME_TEMPLATE = "filename.template";
|
public static final String FILE_NAME_TEMPLATE = "filename.template";
|
||||||
public static final String DEFAULT = "$sanitize(${modelName})_$format(${localDateTime}).${fileSuffix}";
|
public static final String DEFAULT = "$sanitize(${modelName})_$format(${localDateTime}).${fileSuffix}";
|
||||||
public static final String DEFAULT_DIR = "$sanitize(${modelName})_$format(${localDateTime})";
|
public static final String DEFAULT_DIR = "$sanitize(${modelName})_$format(${localDateTime})";
|
||||||
|
@ -32,7 +30,7 @@ public class Rename extends AbstractPlaceholderAwarePostProcessor {
|
||||||
if (Objects.equals(src, target)) {
|
if (Objects.equals(src, target)) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
LOG.info("Renaming {} to {}", src.getName(), target.getName());
|
log.info("Renaming {} to {}", src.getName(), target.getName());
|
||||||
Files.move(rec.getPostProcessedFile().toPath(), target.toPath());
|
Files.move(rec.getPostProcessedFile().toPath(), target.toPath());
|
||||||
rec.setPostProcessedFile(target);
|
rec.setPostProcessedFile(target);
|
||||||
if (Objects.equals(src, rec.getAbsoluteFile())) {
|
if (Objects.equals(src, rec.getAbsoluteFile())) {
|
||||||
|
|
|
@ -1,23 +1,20 @@
|
||||||
package ctbrec.recorder.postprocessing;
|
package ctbrec.recorder.postprocessing;
|
||||||
|
|
||||||
|
|
||||||
|
import lombok.extern.slf4j.Slf4j;
|
||||||
import java.io.File;
|
import java.io.File;
|
||||||
import java.io.FileOutputStream;
|
import java.io.FileOutputStream;
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.Arrays;
|
import java.util.Arrays;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
import org.slf4j.Logger;
|
|
||||||
import org.slf4j.LoggerFactory;
|
|
||||||
|
|
||||||
import ctbrec.OS;
|
import ctbrec.OS;
|
||||||
import ctbrec.Recording;
|
import ctbrec.Recording;
|
||||||
import ctbrec.io.StreamRedirector;
|
import ctbrec.io.StreamRedirector;
|
||||||
import ctbrec.recorder.download.ProcessExitedUncleanException;
|
import ctbrec.recorder.download.ProcessExitedUncleanException;
|
||||||
|
|
||||||
|
@Slf4j
|
||||||
public class Script extends AbstractPlaceholderAwarePostProcessor {
|
public class Script extends AbstractPlaceholderAwarePostProcessor {
|
||||||
|
|
||||||
private static final Logger LOG = LoggerFactory.getLogger(Script.class);
|
|
||||||
public static final String SCRIPT_EXECUTABLE = "script.executable";
|
public static final String SCRIPT_EXECUTABLE = "script.executable";
|
||||||
public static final String SCRIPT_PARAMS = "script.params";
|
public static final String SCRIPT_PARAMS = "script.params";
|
||||||
|
|
||||||
|
@ -32,8 +29,8 @@ public class Script extends AbstractPlaceholderAwarePostProcessor {
|
||||||
List<String> cmdline = buildCommandLine(ctx);
|
List<String> cmdline = buildCommandLine(ctx);
|
||||||
Runtime rt = Runtime.getRuntime();
|
Runtime rt = Runtime.getRuntime();
|
||||||
String[] args = cmdline.toArray(new String[0]);
|
String[] args = cmdline.toArray(new String[0]);
|
||||||
if (LOG.isDebugEnabled()) {
|
if (log.isDebugEnabled()) {
|
||||||
LOG.debug("Running {}", Arrays.toString(args));
|
log.debug("Running {}", Arrays.toString(args));
|
||||||
}
|
}
|
||||||
Process process = rt.exec(args, OS.getEnvironment());
|
Process process = rt.exec(args, OS.getEnvironment());
|
||||||
File logFile = File.createTempFile("execute_script_" + rec.getId() + "_", ".log");
|
File logFile = File.createTempFile("execute_script_" + rec.getId() + "_", ".log");
|
||||||
|
@ -41,7 +38,7 @@ public class Script extends AbstractPlaceholderAwarePostProcessor {
|
||||||
try (FileOutputStream logStream = new FileOutputStream(logFile)) {
|
try (FileOutputStream logStream = new FileOutputStream(logFile)) {
|
||||||
startLogging(process, logStream);
|
startLogging(process, logStream);
|
||||||
int exitCode = process.waitFor();
|
int exitCode = process.waitFor();
|
||||||
LOG.debug("Process finished with exit code {}", exitCode);
|
log.debug("Process finished with exit code {}", exitCode);
|
||||||
if (exitCode != 0) {
|
if (exitCode != 0) {
|
||||||
throw new ProcessExitedUncleanException("Script finished with exit code " + exitCode);
|
throw new ProcessExitedUncleanException("Script finished with exit code " + exitCode);
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,9 +1,8 @@
|
||||||
package ctbrec.servlet;
|
package ctbrec.servlet;
|
||||||
|
|
||||||
import org.json.JSONArray;
|
|
||||||
import org.slf4j.Logger;
|
|
||||||
import org.slf4j.LoggerFactory;
|
|
||||||
|
|
||||||
|
import lombok.extern.slf4j.Slf4j;
|
||||||
|
import org.json.JSONArray;
|
||||||
import javax.servlet.http.HttpServletRequest;
|
import javax.servlet.http.HttpServletRequest;
|
||||||
import javax.servlet.http.HttpServletResponse;
|
import javax.servlet.http.HttpServletResponse;
|
||||||
import java.io.FileNotFoundException;
|
import java.io.FileNotFoundException;
|
||||||
|
@ -12,8 +11,8 @@ import java.util.List;
|
||||||
|
|
||||||
import static javax.servlet.http.HttpServletResponse.SC_INTERNAL_SERVER_ERROR;
|
import static javax.servlet.http.HttpServletResponse.SC_INTERNAL_SERVER_ERROR;
|
||||||
|
|
||||||
|
@Slf4j
|
||||||
public class SearchServlet extends AbstractDocServlet {
|
public class SearchServlet extends AbstractDocServlet {
|
||||||
private static final Logger LOG = LoggerFactory.getLogger(SearchServlet.class);
|
|
||||||
private static final String Q = "term";
|
private static final String Q = "term";
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -37,7 +36,7 @@ public class SearchServlet extends AbstractDocServlet {
|
||||||
try {
|
try {
|
||||||
resp.sendError(SC_INTERNAL_SERVER_ERROR, "Internal Server Error");
|
resp.sendError(SC_INTERNAL_SERVER_ERROR, "Internal Server Error");
|
||||||
} catch (IOException ioe) {
|
} catch (IOException ioe) {
|
||||||
LOG.error("Error while sending error response", ioe);
|
log.error("Error while sending error response", ioe);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,5 +1,7 @@
|
||||||
package ctbrec.sites.bonga;
|
package ctbrec.sites.bonga;
|
||||||
|
|
||||||
|
|
||||||
|
import lombok.extern.slf4j.Slf4j;
|
||||||
import ctbrec.Model;
|
import ctbrec.Model;
|
||||||
import ctbrec.StringUtil;
|
import ctbrec.StringUtil;
|
||||||
import ctbrec.io.HttpClient;
|
import ctbrec.io.HttpClient;
|
||||||
|
@ -11,9 +13,6 @@ import okhttp3.RequestBody;
|
||||||
import okhttp3.Response;
|
import okhttp3.Response;
|
||||||
import org.json.JSONArray;
|
import org.json.JSONArray;
|
||||||
import org.json.JSONObject;
|
import org.json.JSONObject;
|
||||||
import org.slf4j.Logger;
|
|
||||||
import org.slf4j.LoggerFactory;
|
|
||||||
|
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.net.URLEncoder;
|
import java.net.URLEncoder;
|
||||||
import java.util.*;
|
import java.util.*;
|
||||||
|
@ -23,10 +22,8 @@ import java.util.regex.Pattern;
|
||||||
import static ctbrec.ErrorMessages.HTTP_RESPONSE_BODY_IS_NULL;
|
import static ctbrec.ErrorMessages.HTTP_RESPONSE_BODY_IS_NULL;
|
||||||
import static ctbrec.io.HttpConstants.*;
|
import static ctbrec.io.HttpConstants.*;
|
||||||
|
|
||||||
|
@Slf4j
|
||||||
public class BongaCams extends AbstractSite {
|
public class BongaCams extends AbstractSite {
|
||||||
|
|
||||||
private static final Logger LOG = LoggerFactory.getLogger(BongaCams.class);
|
|
||||||
|
|
||||||
private String baseUrl = "https://bongacams.com";
|
private String baseUrl = "https://bongacams.com";
|
||||||
|
|
||||||
private BongaCamsHttpClient httpClient;
|
private BongaCamsHttpClient httpClient;
|
||||||
|
@ -157,7 +154,7 @@ public class BongaCams extends AbstractSite {
|
||||||
parseModelList(models, json);
|
parseModelList(models, json);
|
||||||
return models;
|
return models;
|
||||||
} else {
|
} else {
|
||||||
LOG.warn("Search result: {}", json.toString(2));
|
log.warn("Search result: {}", json.toString(2));
|
||||||
return Collections.emptyList();
|
return Collections.emptyList();
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
|
|
|
@ -1,14 +1,13 @@
|
||||||
package ctbrec.sites.bonga;
|
package ctbrec.sites.bonga;
|
||||||
|
|
||||||
|
|
||||||
|
import lombok.extern.slf4j.Slf4j;
|
||||||
import ctbrec.Config;
|
import ctbrec.Config;
|
||||||
import ctbrec.io.HttpClient;
|
import ctbrec.io.HttpClient;
|
||||||
import ctbrec.io.HttpException;
|
import ctbrec.io.HttpException;
|
||||||
import okhttp3.*;
|
import okhttp3.*;
|
||||||
import org.json.JSONArray;
|
import org.json.JSONArray;
|
||||||
import org.json.JSONObject;
|
import org.json.JSONObject;
|
||||||
import org.slf4j.Logger;
|
|
||||||
import org.slf4j.LoggerFactory;
|
|
||||||
|
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Locale;
|
import java.util.Locale;
|
||||||
|
@ -19,9 +18,8 @@ import java.util.Objects;
|
||||||
import static ctbrec.ErrorMessages.HTTP_RESPONSE_BODY_IS_NULL;
|
import static ctbrec.ErrorMessages.HTTP_RESPONSE_BODY_IS_NULL;
|
||||||
import static ctbrec.io.HttpConstants.*;
|
import static ctbrec.io.HttpConstants.*;
|
||||||
|
|
||||||
|
@Slf4j
|
||||||
public class BongaCamsHttpClient extends HttpClient {
|
public class BongaCamsHttpClient extends HttpClient {
|
||||||
|
|
||||||
private static final Logger LOG = LoggerFactory.getLogger(BongaCamsHttpClient.class);
|
|
||||||
private static final String SORT_COOKIE = "ls01";
|
private static final String SORT_COOKIE = "ls01";
|
||||||
private final BongaCams site;
|
private final BongaCams site;
|
||||||
private int userId = 0;
|
private int userId = 0;
|
||||||
|
@ -59,7 +57,7 @@ public class BongaCamsHttpClient extends HttpClient {
|
||||||
boolean cookiesWorked = checkLoginSuccess();
|
boolean cookiesWorked = checkLoginSuccess();
|
||||||
if (cookiesWorked) {
|
if (cookiesWorked) {
|
||||||
loggedIn = true;
|
loggedIn = true;
|
||||||
LOG.debug("Logged in with cookies");
|
log.debug("Logged in with cookies");
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1,5 +1,7 @@
|
||||||
package ctbrec.sites.cam4;
|
package ctbrec.sites.cam4;
|
||||||
|
|
||||||
|
|
||||||
|
import lombok.extern.slf4j.Slf4j;
|
||||||
import static ctbrec.io.HttpConstants.*;
|
import static ctbrec.io.HttpConstants.*;
|
||||||
import static java.nio.charset.StandardCharsets.*;
|
import static java.nio.charset.StandardCharsets.*;
|
||||||
|
|
||||||
|
@ -7,9 +9,6 @@ import java.io.IOException;
|
||||||
import java.util.Locale;
|
import java.util.Locale;
|
||||||
|
|
||||||
import org.json.JSONObject;
|
import org.json.JSONObject;
|
||||||
import org.slf4j.Logger;
|
|
||||||
import org.slf4j.LoggerFactory;
|
|
||||||
|
|
||||||
import ctbrec.Config;
|
import ctbrec.Config;
|
||||||
import ctbrec.io.HttpClient;
|
import ctbrec.io.HttpClient;
|
||||||
import okhttp3.MediaType;
|
import okhttp3.MediaType;
|
||||||
|
@ -17,10 +16,8 @@ import okhttp3.Request;
|
||||||
import okhttp3.RequestBody;
|
import okhttp3.RequestBody;
|
||||||
import okhttp3.Response;
|
import okhttp3.Response;
|
||||||
|
|
||||||
|
@Slf4j
|
||||||
public class Cam4HttpClient extends HttpClient {
|
public class Cam4HttpClient extends HttpClient {
|
||||||
|
|
||||||
private static final Logger LOG = LoggerFactory.getLogger(Cam4HttpClient.class);
|
|
||||||
|
|
||||||
public Cam4HttpClient(Config config) {
|
public Cam4HttpClient(Config config) {
|
||||||
super("cam4", config);
|
super("cam4", config);
|
||||||
}
|
}
|
||||||
|
@ -34,12 +31,12 @@ public class Cam4HttpClient extends HttpClient {
|
||||||
boolean cookiesWorked = checkLoginSuccess();
|
boolean cookiesWorked = checkLoginSuccess();
|
||||||
if (cookiesWorked) {
|
if (cookiesWorked) {
|
||||||
loggedIn = true;
|
loggedIn = true;
|
||||||
LOG.debug("Logged in with cookies");
|
log.debug("Logged in with cookies");
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
String url = Cam4.BASE_URI + "/rest/v2.0/login";
|
String url = Cam4.BASE_URI + "/rest/v2.0/login";
|
||||||
LOG.debug("Logging in {}", url);
|
log.debug("Logging in {}", url);
|
||||||
JSONObject bodyJson = new JSONObject();
|
JSONObject bodyJson = new JSONObject();
|
||||||
bodyJson.put("username", config.getSettings().cam4Username);
|
bodyJson.put("username", config.getSettings().cam4Username);
|
||||||
bodyJson.put("password", config.getSettings().cam4Password);
|
bodyJson.put("password", config.getSettings().cam4Password);
|
||||||
|
@ -55,7 +52,7 @@ public class Cam4HttpClient extends HttpClient {
|
||||||
.build();
|
.build();
|
||||||
try (Response response = execute(req)) {
|
try (Response response = execute(req)) {
|
||||||
String body = response.body().string();
|
String body = response.body().string();
|
||||||
LOG.debug("Response: {} {}", response.code(), body);
|
log.debug("Response: {} {}", response.code(), body);
|
||||||
if (response.isSuccessful()) {
|
if (response.isSuccessful()) {
|
||||||
JSONObject json = new JSONObject(body);
|
JSONObject json = new JSONObject(body);
|
||||||
return json.optInt("userId") != 0;
|
return json.optInt("userId") != 0;
|
||||||
|
@ -72,7 +69,7 @@ public class Cam4HttpClient extends HttpClient {
|
||||||
public boolean checkLoginSuccess() throws IOException {
|
public boolean checkLoginSuccess() throws IOException {
|
||||||
String url = Cam4.BASE_URI + "/rest/v2.0/login/user";
|
String url = Cam4.BASE_URI + "/rest/v2.0/login/user";
|
||||||
//String url = "http://login.cam4.com:1234/rest/v2.0/login/user";
|
//String url = "http://login.cam4.com:1234/rest/v2.0/login/user";
|
||||||
LOG.debug("Checkin login success by calling {}", url);
|
log.debug("Checkin login success by calling {}", url);
|
||||||
Request req = new Request.Builder()
|
Request req = new Request.Builder()
|
||||||
.url(url)
|
.url(url)
|
||||||
.header(USER_AGENT, config.getSettings().httpUserAgent)
|
.header(USER_AGENT, config.getSettings().httpUserAgent)
|
||||||
|
@ -83,7 +80,7 @@ public class Cam4HttpClient extends HttpClient {
|
||||||
.build();
|
.build();
|
||||||
try (Response response = execute(req)) {
|
try (Response response = execute(req)) {
|
||||||
String body = response.body().string();
|
String body = response.body().string();
|
||||||
LOG.debug("Response: {} {}", response.code(), body);
|
log.debug("Response: {} {}", response.code(), body);
|
||||||
if (response.isSuccessful()) {
|
if (response.isSuccessful()) {
|
||||||
JSONObject json = new JSONObject(body);
|
JSONObject json = new JSONObject(body);
|
||||||
return json.optInt("userId") != 0;
|
return json.optInt("userId") != 0;
|
||||||
|
|
|
@ -1,5 +1,7 @@
|
||||||
package ctbrec.sites.cam4;
|
package ctbrec.sites.cam4;
|
||||||
|
|
||||||
|
|
||||||
|
import lombok.extern.slf4j.Slf4j;
|
||||||
import static ctbrec.io.HttpConstants.*;
|
import static ctbrec.io.HttpConstants.*;
|
||||||
|
|
||||||
import java.io.EOFException;
|
import java.io.EOFException;
|
||||||
|
@ -12,9 +14,6 @@ import java.util.concurrent.TimeUnit;
|
||||||
import java.util.concurrent.TimeoutException;
|
import java.util.concurrent.TimeoutException;
|
||||||
|
|
||||||
import org.json.JSONObject;
|
import org.json.JSONObject;
|
||||||
import org.slf4j.Logger;
|
|
||||||
import org.slf4j.LoggerFactory;
|
|
||||||
|
|
||||||
import ctbrec.Config;
|
import ctbrec.Config;
|
||||||
import ctbrec.io.HttpException;
|
import ctbrec.io.HttpException;
|
||||||
import ctbrec.sites.ModelOfflineException;
|
import ctbrec.sites.ModelOfflineException;
|
||||||
|
@ -24,10 +23,8 @@ import okhttp3.WebSocket;
|
||||||
import okhttp3.WebSocketListener;
|
import okhttp3.WebSocketListener;
|
||||||
import okio.ByteString;
|
import okio.ByteString;
|
||||||
|
|
||||||
|
@Slf4j
|
||||||
public class Cam4WsClient {
|
public class Cam4WsClient {
|
||||||
|
|
||||||
private static final Logger LOG = LoggerFactory.getLogger(Cam4WsClient.class);
|
|
||||||
|
|
||||||
private Cam4 site;
|
private Cam4 site;
|
||||||
private Cam4Model model;
|
private Cam4Model model;
|
||||||
private Config config;
|
private Config config;
|
||||||
|
@ -82,7 +79,7 @@ public class Cam4WsClient {
|
||||||
|
|
||||||
private CompletableFuture<String> send(String p, String msg) {
|
private CompletableFuture<String> send(String p, String msg) {
|
||||||
CompletableFuture<String> future = new CompletableFuture<>();
|
CompletableFuture<String> future = new CompletableFuture<>();
|
||||||
LOG.trace("--> {}", msg);
|
log.trace("--> {}", msg);
|
||||||
boolean sent = websocket.send(msg);
|
boolean sent = websocket.send(msg);
|
||||||
if (!sent) {
|
if (!sent) {
|
||||||
future.completeExceptionally(new IOException("send() returned false"));
|
future.completeExceptionally(new IOException("send() returned false"));
|
||||||
|
@ -126,7 +123,7 @@ public class Cam4WsClient {
|
||||||
CompletableFuture<Boolean> connectedAndAuthorized = new CompletableFuture<>();
|
CompletableFuture<Boolean> connectedAndAuthorized = new CompletableFuture<>();
|
||||||
|
|
||||||
String url = shard + ".ws?v=5";
|
String url = shard + ".ws?v=5";
|
||||||
LOG.trace("Opening websocket {}", url);
|
log.trace("Opening websocket {}", url);
|
||||||
Request req = new Request.Builder() // @formatter:off
|
Request req = new Request.Builder() // @formatter:off
|
||||||
.url(url)
|
.url(url)
|
||||||
.header(USER_AGENT, config.getSettings().httpUserAgent)
|
.header(USER_AGENT, config.getSettings().httpUserAgent)
|
||||||
|
@ -140,9 +137,9 @@ public class Cam4WsClient {
|
||||||
public void onOpen(WebSocket webSocket, Response response) {
|
public void onOpen(WebSocket webSocket, Response response) {
|
||||||
super.onOpen(webSocket, response);
|
super.onOpen(webSocket, response);
|
||||||
try {
|
try {
|
||||||
LOG.trace("open: {}", response.body().string());
|
log.trace("open: {}", response.body().string());
|
||||||
} catch (IOException e) {
|
} catch (IOException e) {
|
||||||
LOG.error("Connection open, but couldn't get the response body", e);
|
log.error("Connection open, but couldn't get the response body", e);
|
||||||
}
|
}
|
||||||
send("", "{\"t\":\"d\",\"d\":{\"r\":" + (r++) + ",\"a\":\"s\",\"b\":{\"c\":{\"sdk.js.2-3-1\":1}}}}");
|
send("", "{\"t\":\"d\",\"d\":{\"r\":" + (r++) + ",\"a\":\"s\",\"b\":{\"c\":{\"sdk.js.2-3-1\":1}}}}");
|
||||||
send("", "{\"t\":\"d\",\"d\":{\"r\":" + (r++) + ",\"a\":\"auth\",\"b\":{\"cred\":\"" + token + "\"}}}");
|
send("", "{\"t\":\"d\",\"d\":{\"r\":" + (r++) + ",\"a\":\"auth\",\"b\":{\"cred\":\"" + token + "\"}}}");
|
||||||
|
@ -151,7 +148,7 @@ public class Cam4WsClient {
|
||||||
@Override
|
@Override
|
||||||
public void onClosed(WebSocket webSocket, int code, String reason) {
|
public void onClosed(WebSocket webSocket, int code, String reason) {
|
||||||
super.onClosed(webSocket, code, reason);
|
super.onClosed(webSocket, code, reason);
|
||||||
LOG.trace("closed: {} {}", code, reason);
|
log.trace("closed: {} {}", code, reason);
|
||||||
connectedAndAuthorized.complete(false);
|
connectedAndAuthorized.complete(false);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -163,12 +160,12 @@ public class Cam4WsClient {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if(response != null) {
|
if(response != null) {
|
||||||
LOG.error("failure {}: {}", model, response.body().string(), t);
|
log.error("failure {}: {}", model, response.body().string(), t);
|
||||||
} else {
|
} else {
|
||||||
LOG.error("failure {}:", model, t);
|
log.error("failure {}:", model, t);
|
||||||
}
|
}
|
||||||
} catch (IOException e) {
|
} catch (IOException e) {
|
||||||
LOG.error("Connection failure and couldn't get the response body", e);
|
log.error("Connection failure and couldn't get the response body", e);
|
||||||
} finally {
|
} finally {
|
||||||
connectedAndAuthorized.completeExceptionally(t);
|
connectedAndAuthorized.completeExceptionally(t);
|
||||||
}
|
}
|
||||||
|
@ -177,7 +174,7 @@ public class Cam4WsClient {
|
||||||
@Override
|
@Override
|
||||||
public void onMessage(WebSocket webSocket, String text) {
|
public void onMessage(WebSocket webSocket, String text) {
|
||||||
super.onMessage(webSocket, text);
|
super.onMessage(webSocket, text);
|
||||||
LOG.trace("msgt: {}", text);
|
log.trace("msgt: {}", text);
|
||||||
JSONObject response = new JSONObject(text);
|
JSONObject response = new JSONObject(text);
|
||||||
if (response.has("d")) {
|
if (response.has("d")) {
|
||||||
JSONObject d = response.getJSONObject("d");
|
JSONObject d = response.getJSONObject("d");
|
||||||
|
@ -207,7 +204,7 @@ public class Cam4WsClient {
|
||||||
@Override
|
@Override
|
||||||
public void onMessage(WebSocket webSocket, ByteString bytes) {
|
public void onMessage(WebSocket webSocket, ByteString bytes) {
|
||||||
super.onMessage(webSocket, bytes);
|
super.onMessage(webSocket, bytes);
|
||||||
LOG.trace("msgb: {}", bytes.hex());
|
log.trace("msgb: {}", bytes.hex());
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
return connectedAndAuthorized;
|
return connectedAndAuthorized;
|
||||||
|
|
|
@ -1,5 +1,7 @@
|
||||||
package ctbrec.sites.camsoda;
|
package ctbrec.sites.camsoda;
|
||||||
|
|
||||||
|
|
||||||
|
import lombok.extern.slf4j.Slf4j;
|
||||||
import ctbrec.Model;
|
import ctbrec.Model;
|
||||||
import ctbrec.io.HttpClient;
|
import ctbrec.io.HttpClient;
|
||||||
import ctbrec.io.HttpException;
|
import ctbrec.io.HttpException;
|
||||||
|
@ -8,9 +10,6 @@ import okhttp3.Request;
|
||||||
import okhttp3.Response;
|
import okhttp3.Response;
|
||||||
import org.json.JSONArray;
|
import org.json.JSONArray;
|
||||||
import org.json.JSONObject;
|
import org.json.JSONObject;
|
||||||
import org.slf4j.Logger;
|
|
||||||
import org.slf4j.LoggerFactory;
|
|
||||||
|
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.net.URLEncoder;
|
import java.net.URLEncoder;
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
|
@ -22,9 +21,8 @@ import java.util.regex.Pattern;
|
||||||
import static ctbrec.io.HttpConstants.USER_AGENT;
|
import static ctbrec.io.HttpConstants.USER_AGENT;
|
||||||
import static java.nio.charset.StandardCharsets.UTF_8;
|
import static java.nio.charset.StandardCharsets.UTF_8;
|
||||||
|
|
||||||
|
@Slf4j
|
||||||
public class Camsoda extends AbstractSite {
|
public class Camsoda extends AbstractSite {
|
||||||
|
|
||||||
private static final Logger LOG = LoggerFactory.getLogger(Camsoda.class);
|
|
||||||
public static final String BASE_URI = "https://www.camsoda.com";
|
public static final String BASE_URI = "https://www.camsoda.com";
|
||||||
private HttpClient httpClient;
|
private HttpClient httpClient;
|
||||||
|
|
||||||
|
@ -153,7 +151,7 @@ public class Camsoda extends AbstractSite {
|
||||||
}
|
}
|
||||||
return models;
|
return models;
|
||||||
} else {
|
} else {
|
||||||
LOG.warn("Search result: {}", json.toString(2));
|
log.warn("Search result: {}", json.toString(2));
|
||||||
return Collections.emptyList();
|
return Collections.emptyList();
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
|
|
|
@ -1,5 +1,7 @@
|
||||||
package ctbrec.sites.camsoda;
|
package ctbrec.sites.camsoda;
|
||||||
|
|
||||||
|
|
||||||
|
import lombok.extern.slf4j.Slf4j;
|
||||||
import static java.util.regex.Pattern.*;
|
import static java.util.regex.Pattern.*;
|
||||||
|
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
|
@ -8,9 +10,6 @@ import java.util.regex.Matcher;
|
||||||
import java.util.regex.Pattern;
|
import java.util.regex.Pattern;
|
||||||
|
|
||||||
import org.json.JSONObject;
|
import org.json.JSONObject;
|
||||||
import org.slf4j.Logger;
|
|
||||||
import org.slf4j.LoggerFactory;
|
|
||||||
|
|
||||||
import ctbrec.Config;
|
import ctbrec.Config;
|
||||||
import ctbrec.io.HttpClient;
|
import ctbrec.io.HttpClient;
|
||||||
import ctbrec.io.HttpException;
|
import ctbrec.io.HttpException;
|
||||||
|
@ -18,9 +17,8 @@ import okhttp3.FormBody;
|
||||||
import okhttp3.Request;
|
import okhttp3.Request;
|
||||||
import okhttp3.Response;
|
import okhttp3.Response;
|
||||||
|
|
||||||
|
@Slf4j
|
||||||
public class CamsodaHttpClient extends HttpClient {
|
public class CamsodaHttpClient extends HttpClient {
|
||||||
|
|
||||||
private static final Logger LOG = LoggerFactory.getLogger(CamsodaHttpClient.class);
|
|
||||||
private static final Pattern CSRF_PATTERN = Pattern.compile("\"csrf\"\\s*:\\s*\"(.*?)\"", MULTILINE | DOTALL);
|
private static final Pattern CSRF_PATTERN = Pattern.compile("\"csrf\"\\s*:\\s*\"(.*?)\"", MULTILINE | DOTALL);
|
||||||
private String csrfToken = null;
|
private String csrfToken = null;
|
||||||
|
|
||||||
|
@ -37,7 +35,7 @@ public class CamsodaHttpClient extends HttpClient {
|
||||||
// persisted cookies might let us log in
|
// persisted cookies might let us log in
|
||||||
if (checkLoginSuccess()) {
|
if (checkLoginSuccess()) {
|
||||||
loggedIn = true;
|
loggedIn = true;
|
||||||
LOG.debug("Logged in with cookies");
|
log.debug("Logged in with cookies");
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1,5 +1,7 @@
|
||||||
package ctbrec.sites.dreamcam;
|
package ctbrec.sites.dreamcam;
|
||||||
|
|
||||||
|
|
||||||
|
import lombok.extern.slf4j.Slf4j;
|
||||||
import ctbrec.*;
|
import ctbrec.*;
|
||||||
import ctbrec.io.BandwidthMeter;
|
import ctbrec.io.BandwidthMeter;
|
||||||
import ctbrec.io.HttpClient;
|
import ctbrec.io.HttpClient;
|
||||||
|
@ -13,9 +15,6 @@ import okhttp3.WebSocket;
|
||||||
import okhttp3.WebSocketListener;
|
import okhttp3.WebSocketListener;
|
||||||
import okio.ByteString;
|
import okio.ByteString;
|
||||||
import org.json.JSONObject;
|
import org.json.JSONObject;
|
||||||
import org.slf4j.Logger;
|
|
||||||
import org.slf4j.LoggerFactory;
|
|
||||||
|
|
||||||
import java.io.File;
|
import java.io.File;
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.io.OutputStream;
|
import java.io.OutputStream;
|
||||||
|
@ -30,9 +29,8 @@ import java.util.regex.Pattern;
|
||||||
|
|
||||||
import static ctbrec.io.HttpConstants.*;
|
import static ctbrec.io.HttpConstants.*;
|
||||||
|
|
||||||
|
@Slf4j
|
||||||
public class DreamcamDownload extends AbstractDownload {
|
public class DreamcamDownload extends AbstractDownload {
|
||||||
|
|
||||||
private static final Logger LOG = LoggerFactory.getLogger(DreamcamDownload.class);
|
|
||||||
private static final int MAX_SECONDS_WITHOUT_TRANSFER = 30;
|
private static final int MAX_SECONDS_WITHOUT_TRANSFER = 30;
|
||||||
|
|
||||||
private final HttpClient httpClient;
|
private final HttpClient httpClient;
|
||||||
|
@ -91,7 +89,7 @@ public class DreamcamDownload extends AbstractDownload {
|
||||||
try {
|
try {
|
||||||
ffmpegStdIn.close();
|
ffmpegStdIn.close();
|
||||||
} catch (IOException e) {
|
} catch (IOException e) {
|
||||||
LOG.error("Couldn't terminate FFmpeg by closing stdin", e);
|
log.error("Couldn't terminate FFmpeg by closing stdin", e);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (ffmpegProcess != null) {
|
if (ffmpegProcess != null) {
|
||||||
|
@ -100,13 +98,13 @@ public class DreamcamDownload extends AbstractDownload {
|
||||||
if (!waitFor && ffmpegProcess.isAlive()) {
|
if (!waitFor && ffmpegProcess.isAlive()) {
|
||||||
ffmpegProcess.destroy();
|
ffmpegProcess.destroy();
|
||||||
if (ffmpegProcess.isAlive()) {
|
if (ffmpegProcess.isAlive()) {
|
||||||
LOG.info("FFmpeg didn't terminate. Destroying the process with force!");
|
log.info("FFmpeg didn't terminate. Destroying the process with force!");
|
||||||
ffmpegProcess.destroyForcibly();
|
ffmpegProcess.destroyForcibly();
|
||||||
ffmpegProcess = null;
|
ffmpegProcess = null;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} catch (InterruptedException e) {
|
} catch (InterruptedException e) {
|
||||||
LOG.error("Interrupted while waiting for FFmpeg to terminate");
|
log.error("Interrupted while waiting for FFmpeg to terminate");
|
||||||
Thread.currentThread().interrupt();
|
Thread.currentThread().interrupt();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -124,7 +122,7 @@ public class DreamcamDownload extends AbstractDownload {
|
||||||
.build();
|
.build();
|
||||||
ffmpeg.exec(cmdline, new String[0], target.getParentFile());
|
ffmpeg.exec(cmdline, new String[0], target.getParentFile());
|
||||||
} catch (IOException | ProcessExitedUncleanException e) {
|
} catch (IOException | ProcessExitedUncleanException e) {
|
||||||
LOG.error("Error in FFmpeg thread", e);
|
log.error("Error in FFmpeg thread", e);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -186,7 +184,7 @@ public class DreamcamDownload extends AbstractDownload {
|
||||||
ffmpeg.shutdown(exitValue);
|
ffmpeg.shutdown(exitValue);
|
||||||
}
|
}
|
||||||
} catch (ProcessExitedUncleanException e) {
|
} catch (ProcessExitedUncleanException e) {
|
||||||
LOG.error("FFmpeg exited unclean", e);
|
log.error("FFmpeg exited unclean", e);
|
||||||
internalStop();
|
internalStop();
|
||||||
}
|
}
|
||||||
try {
|
try {
|
||||||
|
@ -195,22 +193,22 @@ public class DreamcamDownload extends AbstractDownload {
|
||||||
startDownload();
|
startDownload();
|
||||||
}
|
}
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
LOG.error("Error while downloading", e);
|
log.error("Error while downloading", e);
|
||||||
stop();
|
stop();
|
||||||
}
|
}
|
||||||
if (!model.isOnline()) {
|
if (!model.isOnline()) {
|
||||||
LOG.debug("Model {} not online. Stop recording.", model);
|
log.debug("Model {} not online. Stop recording.", model);
|
||||||
stop();
|
stop();
|
||||||
}
|
}
|
||||||
if (splittingStrategy.splitNecessary(this)) {
|
if (splittingStrategy.splitNecessary(this)) {
|
||||||
LOG.debug("Split necessary for model {}. Stop recording.", model);
|
log.debug("Split necessary for model {}. Stop recording.", model);
|
||||||
internalStop();
|
internalStop();
|
||||||
rescheduleTime = Instant.now();
|
rescheduleTime = Instant.now();
|
||||||
} else {
|
} else {
|
||||||
rescheduleTime = Instant.now().plusSeconds(5);
|
rescheduleTime = Instant.now().plusSeconds(5);
|
||||||
}
|
}
|
||||||
if (Duration.between(timeOfLastTransfer, Instant.now()).getSeconds() > MAX_SECONDS_WITHOUT_TRANSFER) {
|
if (Duration.between(timeOfLastTransfer, Instant.now()).getSeconds() > MAX_SECONDS_WITHOUT_TRANSFER) {
|
||||||
LOG.debug("No video data received for {} seconds. Stopping recording for model {}", MAX_SECONDS_WITHOUT_TRANSFER, model);
|
log.debug("No video data received for {} seconds. Stopping recording for model {}", MAX_SECONDS_WITHOUT_TRANSFER, model);
|
||||||
stop();
|
stop();
|
||||||
}
|
}
|
||||||
return this;
|
return this;
|
||||||
|
@ -222,9 +220,9 @@ public class DreamcamDownload extends AbstractDownload {
|
||||||
ffmpegStreamLock.lock();
|
ffmpegStreamLock.lock();
|
||||||
try {
|
try {
|
||||||
wsUrl = model.getWsUrl();
|
wsUrl = model.getWsUrl();
|
||||||
LOG.debug("{} ws url: {}", model.getName(), wsUrl);
|
log.debug("{} ws url: {}", model.getName(), wsUrl);
|
||||||
if (StringUtil.isBlank(wsUrl)) {
|
if (StringUtil.isBlank(wsUrl)) {
|
||||||
LOG.error("{}: Stream URL not found", model);
|
log.error("{}: Stream URL not found", model);
|
||||||
stop();
|
stop();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
@ -241,7 +239,7 @@ public class DreamcamDownload extends AbstractDownload {
|
||||||
@Override
|
@Override
|
||||||
public void onOpen(WebSocket webSocket, Response response) {
|
public void onOpen(WebSocket webSocket, Response response) {
|
||||||
super.onOpen(webSocket, response);
|
super.onOpen(webSocket, response);
|
||||||
LOG.debug("{}: Websocket open", model);
|
log.debug("{}: Websocket open", model);
|
||||||
if (response != null) {
|
if (response != null) {
|
||||||
response.close();
|
response.close();
|
||||||
}
|
}
|
||||||
|
@ -254,7 +252,7 @@ public class DreamcamDownload extends AbstractDownload {
|
||||||
@Override
|
@Override
|
||||||
public void onClosed(WebSocket webSocket, int code, String reason) {
|
public void onClosed(WebSocket webSocket, int code, String reason) {
|
||||||
super.onClosed(webSocket, code, reason);
|
super.onClosed(webSocket, code, reason);
|
||||||
LOG.trace("{}: Websocket closed", model);
|
log.trace("{}: Websocket closed", model);
|
||||||
stop();
|
stop();
|
||||||
synchronized (monitor) {
|
synchronized (monitor) {
|
||||||
monitor.notifyAll();
|
monitor.notifyAll();
|
||||||
|
@ -264,7 +262,7 @@ public class DreamcamDownload extends AbstractDownload {
|
||||||
@Override
|
@Override
|
||||||
public void onFailure(WebSocket webSocket, Throwable t, Response response) {
|
public void onFailure(WebSocket webSocket, Throwable t, Response response) {
|
||||||
super.onFailure(webSocket, t, response);
|
super.onFailure(webSocket, t, response);
|
||||||
LOG.debug("{}: Websocket failed: {}", model, t.getMessage());
|
log.debug("{}: Websocket failed: {}", model, t.getMessage());
|
||||||
if (response != null) {
|
if (response != null) {
|
||||||
response.close();
|
response.close();
|
||||||
}
|
}
|
||||||
|
@ -277,7 +275,7 @@ public class DreamcamDownload extends AbstractDownload {
|
||||||
@Override
|
@Override
|
||||||
public void onMessage(WebSocket webSocket, String text) {
|
public void onMessage(WebSocket webSocket, String text) {
|
||||||
super.onMessage(webSocket, text);
|
super.onMessage(webSocket, text);
|
||||||
LOG.trace("{} ws message: {}", model, text);
|
log.trace("{} ws message: {}", model, text);
|
||||||
JSONObject message = new JSONObject(text);
|
JSONObject message = new JSONObject(text);
|
||||||
if (message.optString("url").equals("stream/qual")) {
|
if (message.optString("url").equals("stream/qual")) {
|
||||||
JSONObject msg = new JSONObject();
|
JSONObject msg = new JSONObject();
|
||||||
|
@ -300,7 +298,7 @@ public class DreamcamDownload extends AbstractDownload {
|
||||||
}
|
}
|
||||||
} catch (IOException e) {
|
} catch (IOException e) {
|
||||||
if (running) {
|
if (running) {
|
||||||
LOG.error("Couldn't write video stream to file", e);
|
log.error("Couldn't write video stream to file", e);
|
||||||
stop();
|
stop();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -313,12 +311,12 @@ public class DreamcamDownload extends AbstractDownload {
|
||||||
monitor.wait();
|
monitor.wait();
|
||||||
} catch (InterruptedException e) {
|
} catch (InterruptedException e) {
|
||||||
Thread.currentThread().interrupt();
|
Thread.currentThread().interrupt();
|
||||||
LOG.warn("Interrupted while waiting for the download to terminate");
|
log.warn("Interrupted while waiting for the download to terminate");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} catch (IOException ex) {
|
} catch (IOException ex) {
|
||||||
if (running) {
|
if (running) {
|
||||||
LOG.error("Error while downloading: {}", ex.getMessage());
|
log.error("Error while downloading: {}", ex.getMessage());
|
||||||
stop();
|
stop();
|
||||||
}
|
}
|
||||||
} finally {
|
} finally {
|
||||||
|
|
|
@ -1,5 +1,7 @@
|
||||||
package ctbrec.sites.dreamcam;
|
package ctbrec.sites.dreamcam;
|
||||||
|
|
||||||
|
|
||||||
|
import lombok.extern.slf4j.Slf4j;
|
||||||
import ctbrec.AbstractModel;
|
import ctbrec.AbstractModel;
|
||||||
import ctbrec.Config;
|
import ctbrec.Config;
|
||||||
import ctbrec.StringUtil;
|
import ctbrec.StringUtil;
|
||||||
|
@ -12,9 +14,6 @@ import okhttp3.Request;
|
||||||
import okhttp3.Response;
|
import okhttp3.Response;
|
||||||
import org.json.JSONArray;
|
import org.json.JSONArray;
|
||||||
import org.json.JSONObject;
|
import org.json.JSONObject;
|
||||||
import org.slf4j.Logger;
|
|
||||||
import org.slf4j.LoggerFactory;
|
|
||||||
|
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.text.MessageFormat;
|
import java.text.MessageFormat;
|
||||||
import java.time.Duration;
|
import java.time.Duration;
|
||||||
|
@ -28,9 +27,8 @@ import java.util.concurrent.ExecutionException;
|
||||||
import static ctbrec.Model.State.*;
|
import static ctbrec.Model.State.*;
|
||||||
import static ctbrec.io.HttpConstants.*;
|
import static ctbrec.io.HttpConstants.*;
|
||||||
|
|
||||||
|
@Slf4j
|
||||||
public class DreamcamModel extends AbstractModel {
|
public class DreamcamModel extends AbstractModel {
|
||||||
|
|
||||||
private static final Logger LOG = LoggerFactory.getLogger(DreamcamModel.class);
|
|
||||||
private static final String API_URL = "https://bss.dreamcamtrue.com";
|
private static final String API_URL = "https://bss.dreamcamtrue.com";
|
||||||
private int[] resolution = new int[2];
|
private int[] resolution = new int[2];
|
||||||
private JSONObject modelInfo;
|
private JSONObject modelInfo;
|
||||||
|
@ -83,7 +81,7 @@ public class DreamcamModel extends AbstractModel {
|
||||||
src.setMediaPlaylistUrl(getPlaylistUrl());
|
src.setMediaPlaylistUrl(getPlaylistUrl());
|
||||||
sources.add(src);
|
sources.add(src);
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
LOG.error("Can not get stream sources for {}: {}", getName(), e.getMessage());
|
log.error("Can not get stream sources for {}: {}", getName(), e.getMessage());
|
||||||
throw new InvalidPlaylistException(e.getMessage());
|
throw new InvalidPlaylistException(e.getMessage());
|
||||||
}
|
}
|
||||||
return sources;
|
return sources;
|
||||||
|
@ -100,7 +98,7 @@ public class DreamcamModel extends AbstractModel {
|
||||||
String streamType = s.getString("streamType");
|
String streamType = s.getString("streamType");
|
||||||
if (streamType.equals("video2D")) {
|
if (streamType.equals("video2D")) {
|
||||||
mediaUrl = s.optString("url");
|
mediaUrl = s.optString("url");
|
||||||
LOG.trace("PlaylistUrl for {}: {}", getName(), mediaUrl);
|
log.trace("PlaylistUrl for {}: {}", getName(), mediaUrl);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,15 +1,11 @@
|
||||||
package ctbrec.sites.fc2live;
|
package ctbrec.sites.fc2live;
|
||||||
|
|
||||||
import org.slf4j.Logger;
|
import lombok.extern.slf4j.Slf4j;
|
||||||
import org.slf4j.LoggerFactory;
|
|
||||||
|
|
||||||
import ctbrec.io.HttpClient;
|
import ctbrec.io.HttpClient;
|
||||||
import ctbrec.recorder.download.hls.HlsDownload;
|
import ctbrec.recorder.download.hls.HlsDownload;
|
||||||
|
|
||||||
|
@Slf4j
|
||||||
public class Fc2HlsDownload extends HlsDownload {
|
public class Fc2HlsDownload extends HlsDownload {
|
||||||
|
|
||||||
private static final Logger LOG = LoggerFactory.getLogger(Fc2HlsDownload.class);
|
|
||||||
|
|
||||||
public Fc2HlsDownload(HttpClient client) {
|
public Fc2HlsDownload(HttpClient client) {
|
||||||
super(client);
|
super(client);
|
||||||
}
|
}
|
||||||
|
@ -22,7 +18,7 @@ public class Fc2HlsDownload extends HlsDownload {
|
||||||
super.call();
|
super.call();
|
||||||
} catch (InterruptedException e) {
|
} catch (InterruptedException e) {
|
||||||
Thread.currentThread().interrupt();
|
Thread.currentThread().interrupt();
|
||||||
LOG.error("Couldn't start download for {}", model, e);
|
log.error("Couldn't start download for {}", model, e);
|
||||||
} finally {
|
} finally {
|
||||||
fc2Model.closeWebsocket();
|
fc2Model.closeWebsocket();
|
||||||
}
|
}
|
||||||
|
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue