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,41 +366,28 @@ 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) {
|
||||
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 {
|
||||
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());
|
||||
}
|
||||
}
|
||||
addOrUpdateModels(updatedModels);
|
||||
|
||||
// remove old ones, which are not in the list of updated models
|
||||
for (Iterator<JavaFxModel> iterator = observableModels.iterator(); iterator.hasNext();) {
|
||||
Model model = iterator.next();
|
||||
if (!models.contains(model)) {
|
||||
Model oldModel = iterator.next();
|
||||
if (!updatedModels.contains(oldModel)) {
|
||||
iterator.remove();
|
||||
}
|
||||
}
|
||||
|
@ -378,8 +398,36 @@ public class RecordedModelsTab extends Tab implements TabSelectionListener {
|
|||
filteredModels.clear();
|
||||
filter(filter.getText());
|
||||
table.sort();
|
||||
});
|
||||
updateService.setOnFailed(event -> LOG.info("Couldn't get list of models from recorder", event.getSource().getException()));
|
||||
}
|
||||
|
||||
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) {
|
||||
|
@ -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,9 +237,24 @@ public class NextGenLocalRecorder implements Recorder {
|
|||
}
|
||||
|
||||
if (!downloadSlotAvailable()) {
|
||||
LOG.info("The number of downloads is maxed out, not starting recording for {}", model);
|
||||
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());
|
||||
Download download = model.createDownload();
|
||||
|
@ -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