forked from j62/ctbrec
Add button to pause recording entirely without pausing all models
This commit is contained in:
parent
12033e9923
commit
f7775b4671
10
CHANGELOG.md
10
CHANGELOG.md
|
@ -1,3 +1,13 @@
|
||||||
|
3.10.3
|
||||||
|
========================
|
||||||
|
* Fix: Recordings couldn't be found in client server setup, if the client was
|
||||||
|
running on Windows and the server on Linux
|
||||||
|
* Fix: Video length detection was done on the original file instead of the
|
||||||
|
post-processed one
|
||||||
|
* Added scrollbars to the settings tab to support smaller screens
|
||||||
|
* Added auto-redirect to the web-interface
|
||||||
|
* Added button to pause recording entirely without pausing all models
|
||||||
|
|
||||||
3.10.2
|
3.10.2
|
||||||
========================
|
========================
|
||||||
* Fix: Flirt4Free browsing
|
* Fix: Flirt4Free browsing
|
||||||
|
|
|
@ -0,0 +1,42 @@
|
||||||
|
package ctbrec.ui.action;
|
||||||
|
|
||||||
|
import ctbrec.recorder.Recorder;
|
||||||
|
import ctbrec.ui.controls.Dialogs;
|
||||||
|
import javafx.application.Platform;
|
||||||
|
import javafx.scene.Cursor;
|
||||||
|
import javafx.scene.control.ToggleButton;
|
||||||
|
|
||||||
|
public class ToggleRecordingAction {
|
||||||
|
|
||||||
|
private ToggleButton toggleButton;
|
||||||
|
private Recorder recorder;
|
||||||
|
private boolean pause;
|
||||||
|
|
||||||
|
public ToggleRecordingAction(ToggleButton toggleButton, Recorder recorder) {
|
||||||
|
this.toggleButton = toggleButton;
|
||||||
|
this.recorder = recorder;
|
||||||
|
pause = toggleButton.isSelected();
|
||||||
|
}
|
||||||
|
|
||||||
|
public void execute() {
|
||||||
|
toggleButton.setCursor(Cursor.WAIT);
|
||||||
|
Thread t = new Thread(() -> {
|
||||||
|
try {
|
||||||
|
if (pause) {
|
||||||
|
recorder.pause();
|
||||||
|
Platform.runLater(() -> toggleButton.setText("Resume Recorder"));
|
||||||
|
} else {
|
||||||
|
recorder.resume();
|
||||||
|
Platform.runLater(() -> toggleButton.setText("Pause Recorder"));
|
||||||
|
}
|
||||||
|
} catch (Exception e) {
|
||||||
|
Dialogs.showError(toggleButton.getScene(), "Toggle Recorder", "An error ocurred while toggling the recorder", e);
|
||||||
|
Platform.runLater(() -> toggleButton.setSelected(!toggleButton.isSelected()));
|
||||||
|
} finally {
|
||||||
|
Platform.runLater(() -> toggleButton.setCursor(Cursor.DEFAULT));
|
||||||
|
}
|
||||||
|
});
|
||||||
|
t.setDaemon(true);
|
||||||
|
t.start();
|
||||||
|
}
|
||||||
|
}
|
|
@ -45,6 +45,7 @@ import ctbrec.ui.action.PauseAction;
|
||||||
import ctbrec.ui.action.PlayAction;
|
import ctbrec.ui.action.PlayAction;
|
||||||
import ctbrec.ui.action.ResumeAction;
|
import ctbrec.ui.action.ResumeAction;
|
||||||
import ctbrec.ui.action.StopRecordingAction;
|
import ctbrec.ui.action.StopRecordingAction;
|
||||||
|
import ctbrec.ui.action.ToggleRecordingAction;
|
||||||
import ctbrec.ui.controls.DateTimeCellFactory;
|
import ctbrec.ui.controls.DateTimeCellFactory;
|
||||||
import ctbrec.ui.controls.Dialogs;
|
import ctbrec.ui.controls.Dialogs;
|
||||||
import ctbrec.ui.controls.SearchBox;
|
import ctbrec.ui.controls.SearchBox;
|
||||||
|
@ -79,6 +80,7 @@ import javafx.scene.control.TableColumn.SortType;
|
||||||
import javafx.scene.control.TableRow;
|
import javafx.scene.control.TableRow;
|
||||||
import javafx.scene.control.TableView;
|
import javafx.scene.control.TableView;
|
||||||
import javafx.scene.control.TextField;
|
import javafx.scene.control.TextField;
|
||||||
|
import javafx.scene.control.ToggleButton;
|
||||||
import javafx.scene.control.ToggleGroup;
|
import javafx.scene.control.ToggleGroup;
|
||||||
import javafx.scene.control.Tooltip;
|
import javafx.scene.control.Tooltip;
|
||||||
import javafx.scene.control.cell.CheckBoxTableCell;
|
import javafx.scene.control.cell.CheckBoxTableCell;
|
||||||
|
@ -122,6 +124,7 @@ public class RecordedModelsTab extends Tab implements TabSelectionListener {
|
||||||
Button addModelButton = new Button("Record");
|
Button addModelButton = new Button("Record");
|
||||||
Button pauseAll = new Button("Pause All");
|
Button pauseAll = new Button("Pause All");
|
||||||
Button resumeAll = new Button("Resume All");
|
Button resumeAll = new Button("Resume All");
|
||||||
|
ToggleButton toggleRecording = new ToggleButton("Pause Recording");
|
||||||
TextField filter;
|
TextField filter;
|
||||||
|
|
||||||
public RecordedModelsTab(String title, Recorder recorder, List<Site> sites) {
|
public RecordedModelsTab(String title, Recorder recorder, List<Site> sites) {
|
||||||
|
@ -274,12 +277,15 @@ public class RecordedModelsTab extends Tab implements TabSelectionListener {
|
||||||
BorderPane.setMargin(addModelBox, new Insets(5));
|
BorderPane.setMargin(addModelBox, new Insets(5));
|
||||||
addModelButton.setOnAction(this::addModel);
|
addModelButton.setOnAction(this::addModel);
|
||||||
addModelButton.setPadding(new Insets(5));
|
addModelButton.setPadding(new Insets(5));
|
||||||
addModelBox.getChildren().addAll(modelLabel, model, addModelButton, pauseAll, resumeAll);
|
addModelBox.getChildren().addAll(modelLabel, model, addModelButton, pauseAll, resumeAll, toggleRecording);
|
||||||
HBox.setMargin(pauseAll, new Insets(0, 0, 0, 20));
|
HBox.setMargin(pauseAll, new Insets(0, 0, 0, 20));
|
||||||
pauseAll.setOnAction(this::pauseAll);
|
pauseAll.setOnAction(this::pauseAll);
|
||||||
resumeAll.setOnAction(this::resumeAll);
|
resumeAll.setOnAction(this::resumeAll);
|
||||||
pauseAll.setPadding(new Insets(5));
|
pauseAll.setPadding(new Insets(5));
|
||||||
resumeAll.setPadding(new Insets(5));
|
resumeAll.setPadding(new Insets(5));
|
||||||
|
toggleRecording.setPadding(new Insets(5));
|
||||||
|
toggleRecording.setOnAction(this::toggleRecording);
|
||||||
|
HBox.setMargin(toggleRecording, new Insets(0, 0, 0, 20));
|
||||||
|
|
||||||
HBox filterContainer = new HBox();
|
HBox filterContainer = new HBox();
|
||||||
filterContainer.setSpacing(0);
|
filterContainer.setSpacing(0);
|
||||||
|
@ -301,7 +307,6 @@ public class RecordedModelsTab extends Tab implements TabSelectionListener {
|
||||||
filterContainer.getChildren().add(filter);
|
filterContainer.getChildren().add(filter);
|
||||||
addModelBox.getChildren().add(filterContainer);
|
addModelBox.getChildren().add(filterContainer);
|
||||||
|
|
||||||
|
|
||||||
BorderPane root = new BorderPane();
|
BorderPane root = new BorderPane();
|
||||||
root.setPadding(new Insets(5));
|
root.setPadding(new Insets(5));
|
||||||
root.setTop(addModelBox);
|
root.setTop(addModelBox);
|
||||||
|
@ -437,6 +442,10 @@ public class RecordedModelsTab extends Tab implements TabSelectionListener {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void toggleRecording(ActionEvent evt) {
|
||||||
|
new ToggleRecordingAction(toggleRecording, recorder).execute();
|
||||||
|
}
|
||||||
|
|
||||||
void initializeUpdateService() {
|
void initializeUpdateService() {
|
||||||
updateService = createUpdateService();
|
updateService = createUpdateService();
|
||||||
updateService.setPeriod(new Duration(TimeUnit.SECONDS.toMillis(2)));
|
updateService.setPeriod(new Duration(TimeUnit.SECONDS.toMillis(2)));
|
||||||
|
|
|
@ -699,4 +699,22 @@ public class NextGenLocalRecorder implements Recorder {
|
||||||
Map<Model, Recording> getRecordingProcesses() {
|
Map<Model, Recording> getRecordingProcesses() {
|
||||||
return recordingProcesses;
|
return recordingProcesses;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void pause() throws InvalidKeyException, NoSuchAlgorithmException, IOException {
|
||||||
|
LOG.info("Pausing recorder");
|
||||||
|
try {
|
||||||
|
recording = false;
|
||||||
|
stopRecordingProcesses();
|
||||||
|
} catch (Exception e) {
|
||||||
|
recording = true;
|
||||||
|
throw e;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void resume() throws InvalidKeyException, NoSuchAlgorithmException, IOException {
|
||||||
|
LOG.info("Resuming recorder");
|
||||||
|
recording = true;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -113,7 +113,7 @@ public interface Recorder {
|
||||||
public void rerunPostProcessing(Recording recording) throws IOException, InvalidKeyException, NoSuchAlgorithmException;
|
public void rerunPostProcessing(Recording recording) throws IOException, InvalidKeyException, NoSuchAlgorithmException;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Tells the recorder, that the recrodng priority for the given model has changed
|
* Tells the recorder, that the recording priority for the given model has changed
|
||||||
*
|
*
|
||||||
* @param model the model with changed priority. The new value can be retrieved with {@link Model#getPriority()}
|
* @param model the model with changed priority. The new value can be retrieved with {@link Model#getPriority()}
|
||||||
* @throws IOException
|
* @throws IOException
|
||||||
|
@ -123,4 +123,21 @@ public interface Recorder {
|
||||||
public void priorityChanged(Model model) throws IOException, InvalidKeyException, NoSuchAlgorithmException;
|
public void priorityChanged(Model model) throws IOException, InvalidKeyException, NoSuchAlgorithmException;
|
||||||
|
|
||||||
public void setNote(Recording rec, String note) throws IOException, InvalidKeyException, NoSuchAlgorithmException;
|
public void setNote(Recording rec, String note) throws IOException, InvalidKeyException, NoSuchAlgorithmException;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Pauses the recording of models entirely. The state of which models should be recorded and which are paused
|
||||||
|
* is kept.
|
||||||
|
* @throws IOException
|
||||||
|
* @throws NoSuchAlgorithmException
|
||||||
|
* @throws InvalidKeyException
|
||||||
|
*/
|
||||||
|
public void pause() throws InvalidKeyException, NoSuchAlgorithmException, IOException;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Resumes recording
|
||||||
|
* @throws IOException
|
||||||
|
* @throws NoSuchAlgorithmException
|
||||||
|
* @throws InvalidKeyException
|
||||||
|
*/
|
||||||
|
public void resume() throws InvalidKeyException, NoSuchAlgorithmException, IOException;
|
||||||
}
|
}
|
||||||
|
|
|
@ -11,6 +11,7 @@ import java.util.ArrayList;
|
||||||
import java.util.Collections;
|
import java.util.Collections;
|
||||||
import java.util.Iterator;
|
import java.util.Iterator;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
import java.util.Optional;
|
||||||
|
|
||||||
import org.json.JSONObject;
|
import org.json.JSONObject;
|
||||||
import org.slf4j.Logger;
|
import org.slf4j.Logger;
|
||||||
|
@ -42,6 +43,7 @@ import okhttp3.Response;
|
||||||
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 Logger LOG = LoggerFactory.getLogger(RemoteRecorder.class);
|
private static final Logger LOG = LoggerFactory.getLogger(RemoteRecorder.class);
|
||||||
|
|
||||||
|
@ -98,6 +100,24 @@ public class RemoteRecorder implements Recorder {
|
||||||
sendRequest("stopAt", model);
|
sendRequest("stopAt", model);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private Optional<String> sendRequest(String action) throws IOException, InvalidKeyException, NoSuchAlgorithmException {
|
||||||
|
String msg = "{\"action\": \"" + action + "\"}";
|
||||||
|
LOG.debug("Sending request to recording server: {}", msg);
|
||||||
|
RequestBody requestBody = RequestBody.create(JSON, msg);
|
||||||
|
Request.Builder builder = new Request.Builder().url(getRecordingEndpoint()).post(requestBody);
|
||||||
|
addHmacIfNeeded(msg, builder);
|
||||||
|
Request request = builder.build();
|
||||||
|
try (Response response = client.execute(request)) {
|
||||||
|
String responseBody = response.body().string();
|
||||||
|
if (response.isSuccessful()) {
|
||||||
|
return Optional.of(responseBody);
|
||||||
|
} else {
|
||||||
|
LOG.error(COULDNT_SEND_REQUEST_SERVER_HTTP_STATUS, response.code(), responseBody);
|
||||||
|
return Optional.empty();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
private void sendRequest(String action, Model model) throws IOException, InvalidKeyException, NoSuchAlgorithmException {
|
private void sendRequest(String action, Model model) throws IOException, InvalidKeyException, NoSuchAlgorithmException {
|
||||||
String payload = modelRequestAdapter.toJson(new ModelRequest(action, model));
|
String payload = modelRequestAdapter.toJson(new ModelRequest(action, model));
|
||||||
LOG.debug("Sending request to recording server: {}", payload);
|
LOG.debug("Sending request to recording server: {}", payload);
|
||||||
|
@ -561,4 +581,14 @@ public class RemoteRecorder implements Recorder {
|
||||||
public void setNote(Recording recording, String note) throws IOException, InvalidKeyException, NoSuchAlgorithmException {
|
public void setNote(Recording recording, String note) throws IOException, InvalidKeyException, NoSuchAlgorithmException {
|
||||||
sendRequest("setNote", recording);
|
sendRequest("setNote", recording);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void pause() throws InvalidKeyException, NoSuchAlgorithmException, IOException {
|
||||||
|
sendRequest("pauseRecorder");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void resume() throws InvalidKeyException, NoSuchAlgorithmException, IOException {
|
||||||
|
sendRequest("resumeRecorder");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -223,6 +223,16 @@ public class RecorderServlet extends AbstractCtbrecServlet {
|
||||||
response = "{\"status\": \"success\"}";
|
response = "{\"status\": \"success\"}";
|
||||||
resp.getWriter().write(response);
|
resp.getWriter().write(response);
|
||||||
break;
|
break;
|
||||||
|
case "pauseRecorder":
|
||||||
|
recorder.pause();
|
||||||
|
response = "{\"status\": \"success\"}";
|
||||||
|
resp.getWriter().write(response);
|
||||||
|
break;
|
||||||
|
case "resumeRecorder":
|
||||||
|
recorder.resume();
|
||||||
|
response = "{\"status\": \"success\"}";
|
||||||
|
resp.getWriter().write(response);
|
||||||
|
break;
|
||||||
default:
|
default:
|
||||||
resp.setStatus(SC_BAD_REQUEST);
|
resp.setStatus(SC_BAD_REQUEST);
|
||||||
response = "{\"status\": \"error\", \"msg\": \"Unknown action ["+request.action+"]\"}";
|
response = "{\"status\": \"error\", \"msg\": \"Unknown action ["+request.action+"]\"}";
|
||||||
|
|
Loading…
Reference in New Issue