forked from j62/ctbrec
Add recording priority for models
Models with high priority will be favored over models with low priority. Recordings for models with low priority might even get stopped to free up a slot for a model with a higher priority
This commit is contained in:
parent
8ae41142d1
commit
4d6e74562c
11
CHANGELOG.md
11
CHANGELOG.md
|
@ -1,3 +1,14 @@
|
|||
3.1.0
|
||||
========================
|
||||
* Added recording priorities for models. If you restrict the number of
|
||||
concurrent downloads, models with high priority will be favored over models
|
||||
with low prio. Running recordings of models with low prio might even get
|
||||
stopped, so that models with higher prio can get recorded.
|
||||
You can adjust the prio on the "Recroding" tab by double-clicking on the
|
||||
value or by using your scroll wheel while holding down CTRL
|
||||
* Added menu entry to open the recording dir of a model
|
||||
|
||||
|
||||
3.0.4
|
||||
========================
|
||||
* MFC now uses DASH again :) You can switch betwenn DASH and HLS in the settings
|
||||
|
|
|
@ -17,6 +17,7 @@ import ctbrec.recorder.download.StreamSource;
|
|||
import ctbrec.sites.Site;
|
||||
import javafx.beans.property.BooleanProperty;
|
||||
import javafx.beans.property.SimpleBooleanProperty;
|
||||
import javafx.beans.property.SimpleIntegerProperty;
|
||||
|
||||
/**
|
||||
* Just a wrapper for Model, which augments it with JavaFX value binding properties, so that UI widgets get updated proeprly
|
||||
|
@ -25,10 +26,12 @@ public class JavaFxModel implements Model {
|
|||
private transient BooleanProperty onlineProperty = new SimpleBooleanProperty();
|
||||
private transient BooleanProperty recordingProperty = new SimpleBooleanProperty();
|
||||
private transient BooleanProperty pausedProperty = new SimpleBooleanProperty();
|
||||
private transient SimpleIntegerProperty priorityProperty = new SimpleIntegerProperty();
|
||||
private Model delegate;
|
||||
|
||||
public JavaFxModel(Model delegate) {
|
||||
this.delegate = delegate;
|
||||
setPriority(delegate.getPriority());
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -103,6 +106,10 @@ public class JavaFxModel implements Model {
|
|||
return pausedProperty;
|
||||
}
|
||||
|
||||
public SimpleIntegerProperty getPriorityProperty() {
|
||||
return priorityProperty;
|
||||
}
|
||||
|
||||
public Model getDelegate() {
|
||||
return delegate;
|
||||
}
|
||||
|
@ -216,6 +223,17 @@ public class JavaFxModel implements Model {
|
|||
delegate.setDisplayName(name);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setPriority(int priority) {
|
||||
delegate.setPriority(priority);
|
||||
priorityProperty.set(priority);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getPriority() {
|
||||
return delegate.getPriority();
|
||||
}
|
||||
|
||||
@Override
|
||||
public int compareTo(Model o) {
|
||||
return delegate.compareTo(o);
|
||||
|
|
|
@ -8,6 +8,7 @@ import java.util.Collections;
|
|||
import java.util.Iterator;
|
||||
import java.util.List;
|
||||
import java.util.Objects;
|
||||
import java.util.Optional;
|
||||
import java.util.concurrent.ExecutionException;
|
||||
import java.util.concurrent.ExecutorService;
|
||||
import java.util.concurrent.Executors;
|
||||
|
@ -38,10 +39,12 @@ import ctbrec.ui.controls.SearchBox;
|
|||
import javafx.application.Platform;
|
||||
import javafx.beans.property.SimpleStringProperty;
|
||||
import javafx.beans.property.StringPropertyBase;
|
||||
import javafx.beans.value.ChangeListener;
|
||||
import javafx.collections.FXCollections;
|
||||
import javafx.collections.ObservableList;
|
||||
import javafx.concurrent.ScheduledService;
|
||||
import javafx.concurrent.Task;
|
||||
import javafx.concurrent.WorkerStateEvent;
|
||||
import javafx.event.ActionEvent;
|
||||
import javafx.geometry.Insets;
|
||||
import javafx.geometry.Pos;
|
||||
|
@ -53,7 +56,9 @@ import javafx.scene.control.MenuItem;
|
|||
import javafx.scene.control.ScrollPane;
|
||||
import javafx.scene.control.SelectionMode;
|
||||
import javafx.scene.control.Tab;
|
||||
import javafx.scene.control.TableCell;
|
||||
import javafx.scene.control.TableColumn;
|
||||
import javafx.scene.control.TableColumn.CellEditEvent;
|
||||
import javafx.scene.control.TableColumn.SortType;
|
||||
import javafx.scene.control.TableRow;
|
||||
import javafx.scene.control.TableView;
|
||||
|
@ -61,6 +66,7 @@ import javafx.scene.control.TextField;
|
|||
import javafx.scene.control.Tooltip;
|
||||
import javafx.scene.control.cell.CheckBoxTableCell;
|
||||
import javafx.scene.control.cell.PropertyValueFactory;
|
||||
import javafx.scene.control.cell.TextFieldTableCell;
|
||||
import javafx.scene.input.Clipboard;
|
||||
import javafx.scene.input.ClipboardContent;
|
||||
import javafx.scene.input.ContextMenuEvent;
|
||||
|
@ -72,7 +78,10 @@ import javafx.scene.layout.BorderPane;
|
|||
import javafx.scene.layout.FlowPane;
|
||||
import javafx.scene.layout.HBox;
|
||||
import javafx.scene.layout.Priority;
|
||||
import javafx.util.Callback;
|
||||
import javafx.util.Duration;
|
||||
import javafx.util.StringConverter;
|
||||
import javafx.util.converter.NumberStringConverter;
|
||||
|
||||
public class RecordedModelsTab extends Tab implements TabSelectionListener {
|
||||
private static final Logger LOG = LoggerFactory.getLogger(RecordedModelsTab.class);
|
||||
|
@ -81,6 +90,7 @@ public class RecordedModelsTab extends Tab implements TabSelectionListener {
|
|||
private ScheduledService<List<JavaFxModel>> updateService;
|
||||
private Recorder recorder;
|
||||
private List<Site> sites;
|
||||
private volatile boolean cellEditing = false;
|
||||
|
||||
FlowPane grid = new FlowPane();
|
||||
ScrollPane scrollPane = new ScrollPane();
|
||||
|
@ -136,9 +146,11 @@ public class RecordedModelsTab extends Tab implements TabSelectionListener {
|
|||
TableColumn<JavaFxModel, String> name = new TableColumn<>("Model");
|
||||
name.setPrefWidth(200);
|
||||
name.setCellValueFactory(new PropertyValueFactory<JavaFxModel, String>("displayName"));
|
||||
name.setCellFactory(new ClickableCellFactory<>());
|
||||
name.setEditable(false);
|
||||
TableColumn<JavaFxModel, String> url = new TableColumn<>("URL");
|
||||
url.setCellValueFactory(new PropertyValueFactory<JavaFxModel, String>("url"));
|
||||
url.setCellFactory(new ClickableCellFactory<>());
|
||||
url.setPrefWidth(400);
|
||||
url.setEditable(false);
|
||||
TableColumn<JavaFxModel, Boolean> online = new TableColumn<>("Online");
|
||||
|
@ -156,6 +168,14 @@ public class RecordedModelsTab extends Tab implements TabSelectionListener {
|
|||
paused.setCellFactory(CheckBoxTableCell.forTableColumn(paused));
|
||||
paused.setPrefWidth(100);
|
||||
paused.setEditable(true);
|
||||
TableColumn<JavaFxModel, Number> priority = new TableColumn<>("Priority");
|
||||
priority.setCellValueFactory(param -> param.getValue().getPriorityProperty());
|
||||
priority.setCellFactory(new PriorityCellFactory());
|
||||
priority.setPrefWidth(90);
|
||||
priority.setEditable(true);
|
||||
priority.setOnEditStart(e -> cellEditing = true);
|
||||
priority.setOnEditCommit(this::updatePriority);
|
||||
priority.setOnEditCancel(e -> cellEditing = false);
|
||||
TableColumn<JavaFxModel, String> notes = new TableColumn<>("Notes");
|
||||
notes.setCellValueFactory(cdf -> {
|
||||
JavaFxModel m = cdf.getValue();
|
||||
|
@ -179,7 +199,7 @@ public class RecordedModelsTab extends Tab implements TabSelectionListener {
|
|||
});
|
||||
notes.setPrefWidth(400);
|
||||
notes.setEditable(false);
|
||||
table.getColumns().addAll(preview, name, url, online, recording, paused, notes);
|
||||
table.getColumns().addAll(preview, name, url, online, recording, paused, priority, notes);
|
||||
table.setItems(observableModels);
|
||||
table.addEventHandler(ContextMenuEvent.CONTEXT_MENU_REQUESTED, event -> {
|
||||
popup = createContextMenu();
|
||||
|
@ -188,14 +208,6 @@ public class RecordedModelsTab extends Tab implements TabSelectionListener {
|
|||
}
|
||||
event.consume();
|
||||
});
|
||||
table.addEventHandler(MouseEvent.MOUSE_CLICKED, event -> {
|
||||
if (event.getButton() == MouseButton.PRIMARY && event.getClickCount() == 2) {
|
||||
JavaFxModel selectedModel = table.getSelectionModel().getSelectedItem();
|
||||
if(selectedModel != null) {
|
||||
new PlayAction(table, selectedModel).execute();
|
||||
}
|
||||
}
|
||||
});
|
||||
table.addEventHandler(MouseEvent.MOUSE_PRESSED, event -> {
|
||||
if (popup != null) {
|
||||
popup.hide();
|
||||
|
@ -212,6 +224,7 @@ public class RecordedModelsTab extends Tab implements TabSelectionListener {
|
|||
pauseRecording(runningModels);
|
||||
}
|
||||
});
|
||||
|
||||
scrollPane.setContent(table);
|
||||
|
||||
HBox addModelBox = new HBox(5);
|
||||
|
@ -264,6 +277,26 @@ public class RecordedModelsTab extends Tab implements TabSelectionListener {
|
|||
restoreState();
|
||||
}
|
||||
|
||||
private void updatePriority(CellEditEvent<JavaFxModel, Number> evt) {
|
||||
try {
|
||||
int prio = Optional.ofNullable(evt.getNewValue()).map(Number::intValue).orElse(-1);
|
||||
if (prio < 0 || prio > 100) {
|
||||
String msg = "Priority has to be between 0 and 100";
|
||||
Dialogs.showError(table.getScene(), "Invalid value", msg, null);
|
||||
} else {
|
||||
evt.getRowValue().setPriority(prio);
|
||||
try {
|
||||
Config.getInstance().save();
|
||||
} catch (IOException e) {
|
||||
LOG.warn("Couldn't save updated priority value {} for {} - {}", evt.getNewValue(), evt.getRowValue().getName(), e.getMessage());
|
||||
}
|
||||
}
|
||||
table.refresh();
|
||||
} finally {
|
||||
cellEditing = false;
|
||||
}
|
||||
}
|
||||
|
||||
private void addModel(ActionEvent e) {
|
||||
String input = model.getText();
|
||||
if (StringUtil.isBlank(input)) {
|
||||
|
@ -333,55 +366,70 @@ public class RecordedModelsTab extends Tab implements TabSelectionListener {
|
|||
void initializeUpdateService() {
|
||||
updateService = createUpdateService();
|
||||
updateService.setPeriod(new Duration(TimeUnit.SECONDS.toMillis(2)));
|
||||
updateService.setOnSucceeded((event) -> {
|
||||
List<JavaFxModel> models = updateService.getValue();
|
||||
if (models == null) {
|
||||
return;
|
||||
}
|
||||
|
||||
lock.lock();
|
||||
try {
|
||||
for (JavaFxModel updatedModel : models) {
|
||||
int index = observableModels.indexOf(updatedModel);
|
||||
if (index == -1) {
|
||||
observableModels.add(updatedModel);
|
||||
updatedModel.getPausedProperty().addListener((obs, oldV, newV) -> {
|
||||
if (newV.booleanValue()) {
|
||||
if(!recorder.isSuspended(updatedModel)) {
|
||||
pauseRecording(Collections.singletonList(updatedModel));
|
||||
}
|
||||
} else {
|
||||
if(recorder.isSuspended(updatedModel)) {
|
||||
resumeRecording(Collections.singletonList(updatedModel));
|
||||
}
|
||||
}
|
||||
});
|
||||
} else {
|
||||
// make sure to update the JavaFX online property, so that the table cell is updated
|
||||
JavaFxModel oldModel = observableModels.get(index);
|
||||
oldModel.setSuspended(updatedModel.isSuspended());
|
||||
oldModel.getOnlineProperty().set(updatedModel.getOnlineProperty().get());
|
||||
oldModel.getRecordingProperty().set(updatedModel.getRecordingProperty().get());
|
||||
}
|
||||
}
|
||||
|
||||
for (Iterator<JavaFxModel> iterator = observableModels.iterator(); iterator.hasNext();) {
|
||||
Model model = iterator.next();
|
||||
if (!models.contains(model)) {
|
||||
iterator.remove();
|
||||
}
|
||||
}
|
||||
} finally {
|
||||
lock.unlock();
|
||||
}
|
||||
|
||||
filteredModels.clear();
|
||||
filter(filter.getText());
|
||||
table.sort();
|
||||
});
|
||||
updateService.setOnSucceeded(this::onUpdateSuccess);
|
||||
updateService.setOnFailed(event -> LOG.info("Couldn't get list of models from recorder", event.getSource().getException()));
|
||||
}
|
||||
|
||||
private void onUpdateSuccess(WorkerStateEvent event) {
|
||||
if (cellEditing) {
|
||||
return;
|
||||
}
|
||||
|
||||
List<JavaFxModel> updatedModels = updateService.getValue();
|
||||
if (updatedModels == null) {
|
||||
return;
|
||||
}
|
||||
|
||||
lock.lock();
|
||||
try {
|
||||
addOrUpdateModels(updatedModels);
|
||||
|
||||
// remove old ones, which are not in the list of updated models
|
||||
for (Iterator<JavaFxModel> iterator = observableModels.iterator(); iterator.hasNext();) {
|
||||
Model oldModel = iterator.next();
|
||||
if (!updatedModels.contains(oldModel)) {
|
||||
iterator.remove();
|
||||
}
|
||||
}
|
||||
} finally {
|
||||
lock.unlock();
|
||||
}
|
||||
|
||||
filteredModels.clear();
|
||||
filter(filter.getText());
|
||||
table.sort();
|
||||
}
|
||||
|
||||
private void addOrUpdateModels(List<JavaFxModel> updatedModels) {
|
||||
for (JavaFxModel updatedModel : updatedModels) {
|
||||
int index = observableModels.indexOf(updatedModel);
|
||||
if (index == -1) {
|
||||
observableModels.add(updatedModel);
|
||||
updatedModel.getPausedProperty().addListener(createPauseListener(updatedModel));
|
||||
} else {
|
||||
// make sure to update the JavaFX online property, so that the table cell is updated
|
||||
JavaFxModel oldModel = observableModels.get(index);
|
||||
oldModel.setSuspended(updatedModel.isSuspended());
|
||||
oldModel.getOnlineProperty().set(updatedModel.getOnlineProperty().get());
|
||||
oldModel.getRecordingProperty().set(updatedModel.getRecordingProperty().get());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private ChangeListener<Boolean> createPauseListener(JavaFxModel updatedModel) {
|
||||
return (obs, oldV, newV) -> {
|
||||
if (newV.booleanValue()) {
|
||||
if(!recorder.isSuspended(updatedModel)) {
|
||||
pauseRecording(Collections.singletonList(updatedModel));
|
||||
}
|
||||
} else {
|
||||
if(recorder.isSuspended(updatedModel)) {
|
||||
resumeRecording(Collections.singletonList(updatedModel));
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
private void filter(String filter) {
|
||||
lock.lock();
|
||||
try {
|
||||
|
@ -398,7 +446,7 @@ public class RecordedModelsTab extends Tab implements TabSelectionListener {
|
|||
StringBuilder sb = new StringBuilder();
|
||||
for (TableColumn<JavaFxModel, ?> tc : table.getColumns()) {
|
||||
Object cellData = tc.getCellData(i);
|
||||
if(cellData != null) {
|
||||
if (cellData != null) {
|
||||
String content = cellData.toString();
|
||||
sb.append(content).append(' ');
|
||||
}
|
||||
|
@ -407,14 +455,14 @@ public class RecordedModelsTab extends Tab implements TabSelectionListener {
|
|||
|
||||
boolean tokensMissing = false;
|
||||
for (String token : tokens) {
|
||||
if(!searchText.toLowerCase().contains(token.toLowerCase())) {
|
||||
if (!searchText.toLowerCase().contains(token.toLowerCase())) {
|
||||
tokensMissing = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if(tokensMissing) {
|
||||
JavaFxModel model = table.getItems().get(i);
|
||||
filteredModels.add(model);
|
||||
if (tokensMissing) {
|
||||
JavaFxModel filteredModel = table.getItems().get(i);
|
||||
filteredModels.add(filteredModel);
|
||||
}
|
||||
}
|
||||
observableModels.removeAll(filteredModels);
|
||||
|
@ -424,7 +472,7 @@ public class RecordedModelsTab extends Tab implements TabSelectionListener {
|
|||
}
|
||||
|
||||
private ScheduledService<List<JavaFxModel>> createUpdateService() {
|
||||
ScheduledService<List<JavaFxModel>> updateService = new ScheduledService<List<JavaFxModel>>() {
|
||||
ScheduledService<List<JavaFxModel>> modelUpdateService = new ScheduledService<List<JavaFxModel>>() {
|
||||
@Override
|
||||
protected Task<List<JavaFxModel>> createTask() {
|
||||
return new Task<List<JavaFxModel>>() {
|
||||
|
@ -464,8 +512,8 @@ public class RecordedModelsTab extends Tab implements TabSelectionListener {
|
|||
t.setName("RecordedModelsTab UpdateService");
|
||||
return t;
|
||||
});
|
||||
updateService.setExecutor(executor);
|
||||
return updateService;
|
||||
modelUpdateService.setExecutor(executor);
|
||||
return modelUpdateService;
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -489,10 +537,10 @@ public class RecordedModelsTab extends Tab implements TabSelectionListener {
|
|||
return null;
|
||||
}
|
||||
MenuItem stop = new MenuItem("Remove Model");
|
||||
stop.setOnAction((e) -> stopAction(selectedModels));
|
||||
stop.setOnAction(e -> stopAction(selectedModels));
|
||||
|
||||
MenuItem copyUrl = new MenuItem("Copy URL");
|
||||
copyUrl.setOnAction((e) -> {
|
||||
copyUrl.setOnAction(e -> {
|
||||
Model selected = selectedModels.get(0);
|
||||
final Clipboard clipboard = Clipboard.getSystemClipboard();
|
||||
final ClipboardContent content = new ClipboardContent();
|
||||
|
@ -645,4 +693,57 @@ public class RecordedModelsTab extends Tab implements TabSelectionListener {
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
private class ClickableCellFactory<S, T> implements Callback<TableColumn<S, T>, TableCell<S, T>> {
|
||||
@Override
|
||||
public TableCell<S, T> call(TableColumn<S, T> param) {
|
||||
TableCell<S, T> cell = new TableCell<>() {
|
||||
@Override
|
||||
protected void updateItem(Object item, boolean empty) {
|
||||
setText(empty ? "" : item.toString());
|
||||
}
|
||||
};
|
||||
|
||||
cell.addEventFilter(MouseEvent.MOUSE_CLICKED, event -> {
|
||||
if (event.getButton() == MouseButton.PRIMARY && event.getClickCount() == 2) {
|
||||
JavaFxModel selectedModel = table.getSelectionModel().getSelectedItem();
|
||||
if(selectedModel != null) {
|
||||
new PlayAction(table, selectedModel).execute();
|
||||
}
|
||||
}
|
||||
});
|
||||
return cell;
|
||||
}
|
||||
}
|
||||
|
||||
private class PriorityCellFactory implements Callback<TableColumn<JavaFxModel, Number>, TableCell<JavaFxModel, Number>> {
|
||||
@Override
|
||||
public TableCell<JavaFxModel, Number> call(TableColumn<JavaFxModel, Number> param) {
|
||||
Callback<TableColumn<JavaFxModel, Number>, TableCell<JavaFxModel, Number>> callback = TextFieldTableCell
|
||||
.<JavaFxModel, Number> forTableColumn((StringConverter<Number>) new NumberStringConverter());
|
||||
TableCell<JavaFxModel, Number> tableCell = callback.call(param);
|
||||
|
||||
tableCell.setOnScroll(event -> {
|
||||
if(event.isControlDown()) {
|
||||
event.consume();
|
||||
JavaFxModel m = tableCell.getTableRow().getItem();
|
||||
int prio = m.getPriority();
|
||||
if(event.getDeltaY() < 0) {
|
||||
prio--;
|
||||
} else {
|
||||
prio++;
|
||||
}
|
||||
prio = Math.min(Math.max(0, prio), 100);
|
||||
m.setPriority(prio);
|
||||
try {
|
||||
Config.getInstance().save();
|
||||
} catch (IOException e) {
|
||||
LOG.warn("Couldn't save updated priority value {} for {} - {}", prio, m.getName(), e.getMessage());
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
return tableCell;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -23,8 +23,9 @@ public abstract class AbstractModel implements Model {
|
|||
private String description;
|
||||
private List<String> tags = new ArrayList<>();
|
||||
private int streamUrlIndex = -1;
|
||||
private int priority = 50;
|
||||
private boolean suspended = false;
|
||||
protected Site site;
|
||||
protected transient Site site;
|
||||
protected State onlineState = State.UNKNOWN;
|
||||
|
||||
@Override
|
||||
|
@ -175,7 +176,7 @@ public abstract class AbstractModel implements Model {
|
|||
@Override
|
||||
public int compareTo(Model o) {
|
||||
String thisName = Optional.ofNullable(getDisplayName()).orElse("").toLowerCase();
|
||||
String otherName = Optional.ofNullable(o).map(m -> m.getDisplayName()).orElse("").toLowerCase();
|
||||
String otherName = Optional.ofNullable(o).map(Model::getDisplayName).orElse("").toLowerCase();
|
||||
return thisName.compareTo(otherName);
|
||||
}
|
||||
|
||||
|
@ -194,6 +195,16 @@ public abstract class AbstractModel implements Model {
|
|||
return site;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getPriority() {
|
||||
return priority;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setPriority(int priority) {
|
||||
this.priority = priority;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Download createDownload() {
|
||||
if(Config.isServerMode()) {
|
||||
|
|
|
@ -112,4 +112,8 @@ public interface Model extends Comparable<Model>, Serializable {
|
|||
|
||||
public Download createDownload();
|
||||
|
||||
public void setPriority(int priority);
|
||||
|
||||
public int getPriority();
|
||||
|
||||
}
|
|
@ -19,7 +19,7 @@ import ctbrec.sites.chaturbate.ChaturbateModel;
|
|||
|
||||
public class ModelJsonAdapter extends JsonAdapter<Model> {
|
||||
|
||||
private static final transient Logger LOG = LoggerFactory.getLogger(ModelJsonAdapter.class);
|
||||
private static final Logger LOG = LoggerFactory.getLogger(ModelJsonAdapter.class);
|
||||
|
||||
private List<Site> sites;
|
||||
|
||||
|
@ -38,6 +38,7 @@ public class ModelJsonAdapter extends JsonAdapter<Model> {
|
|||
String url = null;
|
||||
Object type = null;
|
||||
int streamUrlIndex = -1;
|
||||
int priority;
|
||||
boolean suspended = false;
|
||||
|
||||
Model model = null;
|
||||
|
@ -46,7 +47,11 @@ public class ModelJsonAdapter extends JsonAdapter<Model> {
|
|||
Token token = reader.peek();
|
||||
if(token == Token.NAME) {
|
||||
String key = reader.nextName();
|
||||
if(key.equals("name")) {
|
||||
if(key.equals("type")) {
|
||||
type = reader.readJsonValue();
|
||||
Class<?> modelClass = Class.forName(Optional.ofNullable(type).orElse(ChaturbateModel.class.getName()).toString());
|
||||
model = (Model) modelClass.getDeclaredConstructor().newInstance();
|
||||
} else if(key.equals("name")) {
|
||||
name = reader.nextString();
|
||||
model.setName(name);
|
||||
} else if(key.equals("description")) {
|
||||
|
@ -55,10 +60,9 @@ public class ModelJsonAdapter extends JsonAdapter<Model> {
|
|||
} else if(key.equals("url")) {
|
||||
url = reader.nextString();
|
||||
model.setUrl(url);
|
||||
} else if(key.equals("type")) {
|
||||
type = reader.readJsonValue();
|
||||
Class<?> modelClass = Class.forName(Optional.ofNullable(type).orElse(ChaturbateModel.class.getName()).toString());
|
||||
model = (Model) modelClass.getDeclaredConstructor().newInstance();
|
||||
} else if(key.equals("priority")) {
|
||||
priority = reader.nextInt();
|
||||
model.setPriority(priority);
|
||||
} else if(key.equals("streamUrlIndex")) {
|
||||
streamUrlIndex = reader.nextInt();
|
||||
model.setStreamUrlIndex(streamUrlIndex);
|
||||
|
@ -69,7 +73,7 @@ public class ModelJsonAdapter extends JsonAdapter<Model> {
|
|||
reader.beginObject();
|
||||
try {
|
||||
model.readSiteSpecificData(reader);
|
||||
} catch(Exception e) {
|
||||
} catch (Exception e) {
|
||||
LOG.error("Couldn't read site specific data for model {}", model.getName());
|
||||
throw e;
|
||||
}
|
||||
|
@ -101,6 +105,7 @@ public class ModelJsonAdapter extends JsonAdapter<Model> {
|
|||
writeValueIfSet(writer, "name", model.getName());
|
||||
writeValueIfSet(writer, "description", model.getDescription());
|
||||
writeValueIfSet(writer, "url", model.getUrl());
|
||||
writer.name("priority").value(model.getPriority());
|
||||
writer.name("streamUrlIndex").value(model.getStreamUrlIndex());
|
||||
writer.name("suspended").value(model.isSuspended());
|
||||
writer.name("siteSpecific");
|
||||
|
|
|
@ -237,8 +237,23 @@ public class NextGenLocalRecorder implements Recorder {
|
|||
}
|
||||
|
||||
if (!downloadSlotAvailable()) {
|
||||
LOG.info("The number of downloads is maxed out, not starting recording for {}", model);
|
||||
return;
|
||||
long now = System.currentTimeMillis();
|
||||
if ((now - lastSpaceMessage) > TimeUnit.MINUTES.toMillis(1)) {
|
||||
LOG.info("The number of downloads is maxed out");
|
||||
}
|
||||
// check, if we can stop a recording for a model with lower priority
|
||||
Optional<Recording> lowerPrioRecordingProcess = recordingProcessWithLowerPrio(model.getPriority());
|
||||
if (lowerPrioRecordingProcess.isPresent()) {
|
||||
Download download = lowerPrioRecordingProcess.get().getDownload();
|
||||
Model lowerPrioModel = download.getModel();
|
||||
LOG.info("Stopping recording for {}. Prio {} < {}", lowerPrioModel.getName(), lowerPrioModel.getPriority(), model.getPriority());
|
||||
stopRecordingProcess(lowerPrioModel);
|
||||
} else {
|
||||
if ((now - lastSpaceMessage) > TimeUnit.MINUTES.toMillis(1)) {
|
||||
LOG.info("Other models have higher prio, not starting recording for {}", model.getName());
|
||||
}
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
LOG.info("Starting recording for model {}", model.getName());
|
||||
|
@ -276,6 +291,20 @@ public class NextGenLocalRecorder implements Recorder {
|
|||
}
|
||||
}
|
||||
|
||||
private Optional<Recording> recordingProcessWithLowerPrio(int priority) {
|
||||
Model lowest = null;
|
||||
for (Model m : recordingProcesses.keySet()) {
|
||||
if (lowest == null || m.getPriority() < lowest.getPriority()) {
|
||||
lowest = m;
|
||||
}
|
||||
}
|
||||
if (lowest != null && lowest.getPriority() < priority) {
|
||||
return Optional.of(recordingProcesses.get(lowest));
|
||||
} else {
|
||||
return Optional.empty();
|
||||
}
|
||||
}
|
||||
|
||||
private boolean deleteIfEmpty(Recording rec) throws IOException, InvalidKeyException, NoSuchAlgorithmException {
|
||||
rec.refresh();
|
||||
long sizeInByte = rec.getSizeInByte();
|
||||
|
|
Loading…
Reference in New Issue