forked from j62/ctbrec
1
0
Fork 0

Add Event and EventReaction classes

This commit is contained in:
0xboobface 2018-12-06 17:39:33 +01:00
parent b50df194a0
commit 2dc5fd4581
34 changed files with 440 additions and 162 deletions

View File

@ -1,8 +1,8 @@
package ctbrec.ui;
import static ctbrec.EventBusHolder.*;
import static ctbrec.EventBusHolder.EVENT_TYPE.*;
import static ctbrec.Model.STATUS.*;
import static ctbrec.Model.State.*;
import static ctbrec.event.Event.Type.*;
import java.io.BufferedReader;
import java.io.File;
@ -14,7 +14,6 @@ import java.lang.reflect.Type;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import org.slf4j.Logger;
@ -26,11 +25,14 @@ import com.squareup.moshi.Moshi;
import com.squareup.moshi.Types;
import ctbrec.Config;
import ctbrec.EventBusHolder;
import ctbrec.Model;
import ctbrec.OS;
import ctbrec.StringUtil;
import ctbrec.Version;
import ctbrec.event.Event;
import ctbrec.event.EventBusHolder;
import ctbrec.event.LogReaction;
import ctbrec.event.ModelStateChangedEvent;
import ctbrec.io.HttpClient;
import ctbrec.recorder.LocalRecorder;
import ctbrec.recorder.OnlineMonitor;
@ -42,6 +44,7 @@ import ctbrec.sites.cam4.Cam4;
import ctbrec.sites.camsoda.Camsoda;
import ctbrec.sites.chaturbate.Chaturbate;
import ctbrec.sites.mfc.MyFreeCams;
import ctbrec.ui.settings.SettingsTab;
import javafx.application.Application;
import javafx.application.HostServices;
import javafx.application.Platform;
@ -143,7 +146,7 @@ public class CamrecApplication extends Application {
loadStyleSheet(primaryStage, "color.css");
}
loadStyleSheet(primaryStage, "style.css");
primaryStage.getScene().getStylesheets().add("/ctbrec/ui/ColorSettingsPane.css");
primaryStage.getScene().getStylesheets().add("/ctbrec/ui/settings/ColorSettingsPane.css");
primaryStage.getScene().getStylesheets().add("/ctbrec/ui/ThumbCell.css");
primaryStage.getScene().getStylesheets().add("/ctbrec/ui/controls/SearchBox.css");
primaryStage.getScene().getStylesheets().add("/ctbrec/ui/controls/Popover.css");
@ -212,40 +215,43 @@ public class CamrecApplication extends Application {
}
private void registerAlertSystem() {
new Thread(() -> {
// try {
// // don't register before 1 minute has passed, because directly after
// // the start of ctbrec, an event for every online model would be fired,
// // which is annoying as f
// Thread.sleep(TimeUnit.MINUTES.toMillis(1));
// } catch (InterruptedException e) {
// e.printStackTrace();
// }
LOG.debug("Alert System registered");
Platform.runLater(() -> {
EventBusHolder.BUS.register(new Object() {
@Subscribe
public void modelEvent(Map<String, Object> e) {
try {
if (Objects.equals(e.get(EVENT), MODEL_STATUS_CHANGED)) {
LOG.debug("Alert: {}", e);
Model.STATUS status = (Model.STATUS) e.get(STATUS);
Model model = (Model) e.get(MODEL);
if (status == ONLINE) {
Platform.runLater(() -> {
String header = "Model Online";
String msg = model.getDisplayName() + " is now online";
OS.notification(primaryStage.getTitle(), header, msg);
});
}
}
} catch (Exception e1) {
e1.printStackTrace();
// try {
// // don't register before 1 minute has passed, because directly after
// // the start of ctbrec, an event for every online model would be fired,
// // which is annoying as f
// Thread.sleep(TimeUnit.MINUTES.toMillis(1));
// } catch (InterruptedException e) {
// e.printStackTrace();
// }
EventBusHolder.BUS.register(new Object() {
@Subscribe
public void modelEvent(Event e) {
try {
if (e.getType() == MODEL_STATUS_CHANGED) {
ModelStateChangedEvent evt = (ModelStateChangedEvent) e;
Model model = evt.getModel();
if (evt.getNewState() == ONLINE) {
String header = "Model Online";
String msg = model.getDisplayName() + " is now online";
OS.notification(primaryStage.getTitle(), header, msg);
}
}
});
});
}).start();
} catch (Exception e1) {
LOG.error("Couldn't show notification", e1);
}
}
});
EventBusHolder.BUS.register(new Object() {
LogReaction reaction = new LogReaction();
@Subscribe
public void modelEvent(Event e) {
reaction.reactToEvent(e);
}
});
LOG.debug("Alert System registered");
}
private void writeColorSchemeStyleSheet(Stage primaryStage) {

View File

@ -110,7 +110,7 @@ public class JavaFxModel implements Model {
}
@Override
public STATUS getOnlineState(boolean failFast) throws IOException, ExecutionException {
public State getOnlineState(boolean failFast) throws IOException, ExecutionException {
return delegate.getOnlineState(failFast);
}

View File

@ -43,7 +43,7 @@ public class JavaFxRecording extends Recording {
}
@Override
public STATUS getStatus() {
public State getStatus() {
return delegate.getStatus();
}
@ -52,7 +52,7 @@ public class JavaFxRecording extends Recording {
}
@Override
public void setStatus(STATUS status) {
public void setStatus(State status) {
delegate.setStatus(status);
switch(status) {
case RECORDING:
@ -121,7 +121,7 @@ public class JavaFxRecording extends Recording {
public void update(Recording updated) {
if(!Config.getInstance().getSettings().localRecording) {
if(getStatus() == STATUS.DOWNLOADING && updated.getStatus() != STATUS.DOWNLOADING) {
if(getStatus() == State.DOWNLOADING && updated.getStatus() != State.DOWNLOADING) {
// ignore, because the the status coming from the server is FINISHED and we are
// overriding it with DOWNLOADING
return;

View File

@ -369,7 +369,7 @@ public class RecordedModelsTab extends Tab implements TabSelectionListener {
.map(m -> new JavaFxModel(m))
.peek(fxm -> {
for (Recording recording : recordings) {
if(recording.getStatus() == Recording.STATUS.RECORDING &&
if(recording.getStatus() == Recording.State.RECORDING &&
recording.getModelName().equals(fxm.getName()))
{
fxm.getRecordingProperty().set(true);

View File

@ -1,5 +1,6 @@
package ctbrec.ui;
import static ctbrec.Recording.State.*;
import static javafx.scene.control.ButtonType.*;
import java.io.File;
@ -34,7 +35,7 @@ import com.iheartradio.m3u8.PlaylistException;
import ctbrec.Config;
import ctbrec.Recording;
import ctbrec.Recording.STATUS;
import ctbrec.Recording.State;
import ctbrec.StringUtil;
import ctbrec.recorder.Recorder;
import ctbrec.recorder.download.MergedHlsDownload;
@ -172,7 +173,7 @@ public class RecordingsTab extends Tab implements TabSelectionListener {
if(Objects.equals(System.getenv("CTBREC_DEV"), "1")) {
int row = this.getTableRow().getIndex();
JavaFxRecording rec = tableViewProperty().get().getItems().get(row);
if(!rec.valueChanged() && rec.getStatus() == STATUS.RECORDING) {
if(!rec.valueChanged() && rec.getStatus() == State.RECORDING) {
setStyle("-fx-alignment: CENTER-RIGHT; -fx-background-color: red");
}
}
@ -212,11 +213,11 @@ public class RecordingsTab extends Tab implements TabSelectionListener {
List<JavaFxRecording> recordings = table.getSelectionModel().getSelectedItems();
if (recordings != null && !recordings.isEmpty()) {
if (event.getCode() == KeyCode.DELETE) {
if(recordings.size() > 1 || recordings.get(0).getStatus() == STATUS.FINISHED) {
if(recordings.size() > 1 || recordings.get(0).getStatus() == State.FINISHED) {
delete(recordings);
}
} else if (event.getCode() == KeyCode.ENTER) {
if(recordings.get(0).getStatus() == STATUS.FINISHED) {
if(recordings.get(0).getStatus() == State.FINISHED) {
play(recordings.get(0));
}
}
@ -376,7 +377,7 @@ public class RecordingsTab extends Tab implements TabSelectionListener {
openInPlayer.setOnAction((e) -> {
play(recordings.get(0));
});
if(recordings.get(0).getStatus() == STATUS.FINISHED || Config.getInstance().getSettings().localRecording) {
if(recordings.get(0).getStatus() == State.FINISHED || Config.getInstance().getSettings().localRecording) {
contextMenu.getItems().add(openInPlayer);
}
@ -398,7 +399,7 @@ public class RecordingsTab extends Tab implements TabSelectionListener {
deleteRecording.setOnAction((e) -> {
delete(recordings);
});
if(recordings.get(0).getStatus() == STATUS.FINISHED || recordings.size() > 1) {
if(recordings.get(0).getStatus() == State.FINISHED || recordings.size() > 1) {
contextMenu.getItems().add(deleteRecording);
}
@ -424,7 +425,7 @@ public class RecordingsTab extends Tab implements TabSelectionListener {
LOG.error("Error while downloading recording", e1);
}
});
if (!Config.getInstance().getSettings().localRecording && recordings.get(0).getStatus() == STATUS.FINISHED) {
if (!Config.getInstance().getSettings().localRecording && recordings.get(0).getStatus() == State.FINISHED) {
contextMenu.getItems().add(downloadRecording);
}
@ -463,11 +464,11 @@ public class RecordingsTab extends Tab implements TabSelectionListener {
download.start(url.toString(), target, (progress) -> {
Platform.runLater(() -> {
if (progress == 100) {
recording.setStatus(STATUS.FINISHED);
recording.setStatus(FINISHED);
recording.setProgress(-1);
LOG.debug("Download finished for recording {}", recording.getPath());
} else {
recording.setStatus(STATUS.DOWNLOADING);
recording.setStatus(DOWNLOADING);
recording.setProgress(progress);
}
});
@ -482,7 +483,7 @@ public class RecordingsTab extends Tab implements TabSelectionListener {
Platform.runLater(new Runnable() {
@Override
public void run() {
recording.setStatus(STATUS.FINISHED);
recording.setStatus(FINISHED);
recording.setProgress(-1);
}
});
@ -493,7 +494,7 @@ public class RecordingsTab extends Tab implements TabSelectionListener {
t.setName("Download Thread " + recording.getPath());
t.start();
recording.setStatus(STATUS.DOWNLOADING);
recording.setStatus(State.DOWNLOADING);
recording.setProgress(0);
}
}
@ -563,7 +564,7 @@ public class RecordingsTab extends Tab implements TabSelectionListener {
List<Recording> deleted = new ArrayList<>();
for (Iterator<JavaFxRecording> iterator = recordings.iterator(); iterator.hasNext();) {
JavaFxRecording r = iterator.next();
if(r.getStatus() != STATUS.FINISHED) {
if(r.getStatus() != FINISHED) {
continue;
}
try {

View File

@ -25,8 +25,8 @@ import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import ctbrec.Config;
import ctbrec.EventBusHolder;
import ctbrec.Model;
import ctbrec.event.EventBusHolder;
import ctbrec.recorder.Recorder;
import ctbrec.sites.Site;
import ctbrec.sites.mfc.MyFreeCamsClient;

View File

@ -9,7 +9,7 @@ import org.slf4j.LoggerFactory;
import com.google.common.eventbus.Subscribe;
import ctbrec.EventBusHolder;
import ctbrec.event.EventBusHolder;
import ctbrec.sites.Site;
import javafx.application.Platform;
import javafx.concurrent.Task;

View File

@ -0,0 +1,30 @@
package ctbrec.ui.settings;
import ctbrec.event.Event.Type;
import javafx.scene.control.Button;
import javafx.scene.control.Label;
import javafx.scene.control.TitledPane;
import javafx.scene.layout.GridPane;
public class ActionSettingsPanel extends TitledPane {
public ActionSettingsPanel(SettingsTab settingsTab) {
setText("Actions");
setExpanded(true);
setCollapsible(false);
createGui();
}
private void createGui() {
GridPane mainLayout = SettingsTab.createGridLayout();
setContent(mainLayout);
int row = 0;
for (Type type : Type.values()) {
Label l = new Label(type.name());
mainLayout.add(l, 0, row);
Button b = new Button("Configure");
mainLayout.add(b, 1, row++);
}
}
}

View File

@ -1,6 +1,6 @@
package ctbrec.ui.sites.bonga;
import static ctbrec.Model.STATUS.*;
import static ctbrec.Model.State.*;
import java.io.IOException;
import java.util.ArrayList;

View File

@ -1,6 +1,6 @@
package ctbrec.ui.sites.camsoda;
import static ctbrec.Model.STATUS.*;
import static ctbrec.Model.State.*;
import java.io.IOException;
import java.util.ArrayList;

View File

@ -21,7 +21,7 @@ public abstract class AbstractModel implements Model {
private int streamUrlIndex = -1;
private boolean suspended = false;
protected Site site;
protected STATUS onlineState = STATUS.UNKNOWN;
protected State onlineState = State.UNKNOWN;
@Override
public boolean isOnline() throws IOException, ExecutionException, InterruptedException {
@ -123,11 +123,11 @@ public abstract class AbstractModel implements Model {
}
@Override
public STATUS getOnlineState(boolean failFast) throws IOException, ExecutionException {
public State getOnlineState(boolean failFast) throws IOException, ExecutionException {
return onlineState;
}
public void setOnlineState(STATUS status) {
public void setOnlineState(State status) {
this.onlineState = status;
}

View File

@ -14,7 +14,7 @@ import ctbrec.sites.Site;
public interface Model {
public static enum STATUS {
public static enum State {
ONLINE("online"),
OFFLINE("offline"),
AWAY("away"),
@ -23,7 +23,7 @@ public interface Model {
UNKNOWN("unknown");
String display;
STATUS(String display) {
State(String display) {
this.display = display;
}
@ -65,7 +65,7 @@ public interface Model {
public boolean isOnline(boolean ignoreCache) throws IOException, ExecutionException, InterruptedException;
public STATUS getOnlineState(boolean failFast) throws IOException, ExecutionException;
public State getOnlineState(boolean failFast) throws IOException, ExecutionException;
public List<StreamSource> getStreamSources() throws IOException, ExecutionException, ParseException, PlaylistException;

View File

@ -10,11 +10,11 @@ public class Recording {
private Instant startDate;
private String path;
private boolean hasPlaylist;
private STATUS status = STATUS.UNKNOWN;
private State status = State.UNKNOWN;
private int progress = -1;
private long sizeInByte;
public static enum STATUS {
public static enum State {
RECORDING,
GENERATING_PLAYLIST,
STOPPED,
@ -50,11 +50,11 @@ public class Recording {
this.startDate = startDate;
}
public STATUS getStatus() {
public State getStatus() {
return status;
}
public void setStatus(STATUS status) {
public void setStatus(State status) {
this.status = status;
}

View File

@ -0,0 +1,16 @@
package ctbrec.event;
import ctbrec.Model;
public abstract class AbstractModelEvent extends Event {
protected Model model;
public Model getModel() {
return model;
}
public void setModel(Model model) {
this.model = model;
}
}

View File

@ -0,0 +1,28 @@
package ctbrec.event;
public abstract class Event {
public static enum Type {
/**
* This event is fired every time the OnlineMonitor sees a model online
* It is also fired, if the model was online before. You can see it as a "still online ping".
*/
MODEL_ONLINE,
/**
* This event is fired whenever the model's online state (Model.STATUS) changes.
*/
MODEL_STATUS_CHANGED,
/**
* This event is fired whenever the state of a recording changes.
*/
RECORDING_STATUS_CHANGED
}
public abstract Type getType();
public abstract String getName();
public abstract String getDescription();
public abstract String[] getExecutionParams();
}

View File

@ -1,4 +1,4 @@
package ctbrec;
package ctbrec.event;
import java.util.concurrent.Executors;
@ -12,24 +12,5 @@ public class EventBusHolder {
public static final String STATUS = "status";
public static final String MODEL = "model";
public static enum EVENT_TYPE {
/**
* This event is fired every time the OnlineMonitor sees a model online
* It is also fired, if the model was online before. You can see it as a "still online ping".
*/
MODEL_ONLINE,
/**
* This event is fired whenever the model's online state (Model.STATUS) changes.
*/
MODEL_STATUS_CHANGED,
/**
* This event is fired whenever the state of a recording changes.
*/
RECORDING_STATUS_CHANGED
}
public static final EventBus BUS = new AsyncEventBus(Executors.newSingleThreadExecutor());
}

View File

@ -0,0 +1,32 @@
package ctbrec.event;
import java.util.ArrayList;
import java.util.List;
import java.util.function.Consumer;
import java.util.function.Predicate;
public class EventReaction {
private List<Predicate<Event>> predicates = new ArrayList<>();
private Consumer<Event> action;
@SafeVarargs
public EventReaction(Consumer<Event> action, Predicate<Event>... predicates) {
this.action = action;
for (Predicate<Event> predicate : predicates) {
this.predicates.add(predicate);
}
}
public void reactToEvent(Event evt) {
boolean matches = true;
for (Predicate<Event> predicate : predicates) {
if(!predicate.test(evt)) {
matches = false;
}
}
if(matches) {
action.accept(evt);
}
}
}

View File

@ -0,0 +1,15 @@
package ctbrec.event;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
public class LogReaction extends EventReaction {
private static final transient Logger LOG = LoggerFactory.getLogger(LogReaction.class);
public LogReaction() {
super(evt -> {
LOG.debug("LogReaction: {}", evt);
}, TypePredicate.of(Event.Type.RECORDING_STATUS_CHANGED));
}
}

View File

@ -0,0 +1,36 @@
package ctbrec.event;
import ctbrec.Model;
public class ModelIsOnlineEvent extends AbstractModelEvent {
public ModelIsOnlineEvent(Model model) {
super.model = model;
}
@Override
public Type getType() {
return Event.Type.MODEL_ONLINE;
}
@Override
public String getName() {
return "Model is online";
}
@Override
public String getDescription() {
return "Repeatedly fired when a model is online";
}
@Override
public String[] getExecutionParams() {
return new String[] {
getType().toString(),
model.getDisplayName(),
model.getUrl(),
model.getSite().getName()
};
}
}

View File

@ -0,0 +1,59 @@
package ctbrec.event;
import ctbrec.Model;
import ctbrec.Model.State;
public class ModelStateChangedEvent extends AbstractModelEvent {
private State oldState;
private State newState;
public ModelStateChangedEvent(Model model, Model.State oldState, Model.State newState) {
super.model = model;
this.oldState = oldState;
this.newState = newState;
}
@Override
public Type getType() {
return Event.Type.MODEL_STATUS_CHANGED;
}
@Override
public String getName() {
return "Model state changed";
}
@Override
public String getDescription() {
return "Fired when a model state changed. E.g. from OFFLINE to ONLINE";
}
@Override
public String[] getExecutionParams() {
return new String[] {
getType().toString(),
model.getDisplayName(),
model.getUrl(),
model.getSite().getName(),
oldState.toString(),
newState.toString()
};
}
public State getOldState() {
return oldState;
}
public void setOldState(State oldState) {
this.oldState = oldState;
}
public State getNewState() {
return newState;
}
public void setNewState(State newState) {
this.newState = newState;
}
}

View File

@ -0,0 +1,55 @@
package ctbrec.event;
import java.io.File;
import java.time.Instant;
import ctbrec.Model;
import ctbrec.Recording.State;
public class RecordingStateChangedEvent extends AbstractModelEvent {
private File path;
private State newState;
private Instant startTime;
public RecordingStateChangedEvent(File recording, State newState, Model model, Instant startTime) {
super.model = model;
this.path = recording;
this.newState = newState;
this.startTime = startTime;
}
@Override
public Type getType() {
return Event.Type.RECORDING_STATUS_CHANGED;
}
@Override
public String getName() {
return "Recording state changed";
}
@Override
public String getDescription() {
return "Fired when a recording state changed. E.g. from RECORDING to STOPPED";
}
@Override
public String[] getExecutionParams() {
return new String[] {
getType().toString(),
path.getAbsolutePath(),
newState.toString(),
model.getDisplayName(),
model.getSite().getName(),
model.getUrl(),
Long.toString(startTime.getEpochSecond())
};
}
@Override
public String toString() {
return "RecordingStateChanged[" + newState + "," + model.getDisplayName() + "," + path + "]";
}
}

View File

@ -0,0 +1,23 @@
package ctbrec.event;
import java.util.function.Predicate;
import ctbrec.event.Event.Type;
public class TypePredicate implements Predicate<Event> {
private Type type;
private TypePredicate(Type type) {
this.type = type;
}
@Override
public boolean test(Event evt) {
return evt.getType() == type;
}
public static TypePredicate of(Type type) {
return new TypePredicate(type);
}
}

View File

@ -26,7 +26,7 @@ public class StreamRedirectThread implements Runnable {
while(in != null && (length = in.read(buffer)) >= 0) {
out.write(buffer, 0, length);
}
LOG.debug("Stream redirect thread ended");
LOG.trace("Stream redirect thread ended");
} catch(Exception e) {
LOG.error("Couldn't redirect stream: {}", e.getLocalizedMessage());
}

View File

@ -1,8 +1,7 @@
package ctbrec.recorder;
import static ctbrec.EventBusHolder.*;
import static ctbrec.EventBusHolder.EVENT_TYPE.*;
import static ctbrec.Recording.STATUS.*;
import static ctbrec.Recording.State.*;
import static ctbrec.event.Event.Type.*;
import java.io.File;
import java.io.FilenameFilter;
@ -24,7 +23,6 @@ import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import java.util.NoSuchElementException;
import java.util.Objects;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.locks.ReentrantLock;
@ -38,11 +36,14 @@ import com.iheartradio.m3u8.ParseException;
import com.iheartradio.m3u8.PlaylistException;
import ctbrec.Config;
import ctbrec.EventBusHolder;
import ctbrec.Model;
import ctbrec.OS;
import ctbrec.Recording;
import ctbrec.Recording.STATUS;
import ctbrec.Recording.State;
import ctbrec.event.Event;
import ctbrec.event.EventBusHolder;
import ctbrec.event.ModelIsOnlineEvent;
import ctbrec.event.RecordingStateChangedEvent;
import ctbrec.io.HttpClient;
import ctbrec.io.StreamRedirectThread;
import ctbrec.recorder.PlaylistGenerator.InvalidPlaylistException;
@ -97,10 +98,11 @@ public class LocalRecorder implements Recorder {
private void registerEventBusListener() {
EventBusHolder.BUS.register(new Object() {
@Subscribe
public void modelEvent(Map<String, Object> e) {
public void modelEvent(Event e) {
try {
if (Objects.equals(e.get(EVENT), MODEL_ONLINE)) {
Model model = (Model) e.get(MODEL);
if (e.getType() == MODEL_ONLINE) {
ModelIsOnlineEvent evt = (ModelIsOnlineEvent) e;
Model model = evt.getModel();
if(!isSuspended(model) && !recordingProcesses.containsKey(model)) {
startRecordingProcess(model);
}
@ -198,7 +200,6 @@ public class LocalRecorder implements Recorder {
}
}
}.start();
fireRecordingStateChanged(model, RECORDING);
}
private void stopRecordingProcess(Model model) {
@ -208,7 +209,7 @@ public class LocalRecorder implements Recorder {
if(!Config.isServerMode()) {
postprocess(download);
}
fireRecordingStateChanged(model, FINISHED);
fireRecordingStateChanged(download.getTarget(), FINISHED, model, download.getStartTime());
}
private void postprocess(Download download) {
@ -388,7 +389,7 @@ public class LocalRecorder implements Recorder {
} else {
postprocess(d);
}
fireRecordingStateChanged(m, FINISHED); // TODO fire all the events
fireRecordingStateChanged(d.getTarget(), FINISHED, m, d.getStartTime()); // TODO fire all the events
}
}
for (Model m : restart) {
@ -439,13 +440,9 @@ public class LocalRecorder implements Recorder {
}
}
private void fireRecordingStateChanged(Model model, Recording.STATUS status) {
Map<String, Object> evt = new HashMap<>();
evt.put(EVENT, RECORDING_STATUS_CHANGED);
evt.put(STATUS, status);
evt.put(MODEL, model);
private void fireRecordingStateChanged(File path, Recording.State newState, Model model, Instant startTime) {
RecordingStateChangedEvent evt = new RecordingStateChangedEvent(path, newState, model, startTime);
EventBusHolder.BUS.post(evt);
LOG.debug("Event fired {}", evt);
}
private class PostProcessingTrigger extends Thread {
@ -532,7 +529,7 @@ public class LocalRecorder implements Recorder {
return recordings;
}
private STATUS getStatus(Recording recording) {
private State getStatus(Recording recording) {
File absolutePath = new File(Config.getInstance().getSettings().recordingsDir, recording.getPath());
PlaylistGenerator playlistGenerator = playlistGenerators.get(absolutePath);

View File

@ -1,8 +1,6 @@
package ctbrec.recorder;
import static ctbrec.EventBusHolder.*;
import static ctbrec.EventBusHolder.EVENT_TYPE.*;
import static ctbrec.Model.STATUS.*;
import static ctbrec.Model.State.*;
import java.io.InterruptedIOException;
import java.net.SocketTimeoutException;
@ -18,9 +16,10 @@ import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import ctbrec.Config;
import ctbrec.EventBusHolder;
import ctbrec.Model;
import ctbrec.Model.STATUS;
import ctbrec.event.EventBusHolder;
import ctbrec.event.ModelIsOnlineEvent;
import ctbrec.event.ModelStateChangedEvent;
import ctbrec.io.HttpException;
public class OnlineMonitor extends Thread {
@ -30,7 +29,7 @@ public class OnlineMonitor extends Thread {
private volatile boolean running = false;
private Recorder recorder;
private Map<Model, STATUS> states = new HashMap<>();
private Map<Model, Model.State> states = new HashMap<>();
public OnlineMonitor(Recorder recorder) {
this.recorder = recorder;
@ -57,13 +56,13 @@ public class OnlineMonitor extends Thread {
for (Model model : models) {
try {
if(model.isOnline(IGNORE_CACHE)) {
fireModelOnline(model);
EventBusHolder.BUS.post(new ModelIsOnlineEvent(model));
}
STATUS state = model.getOnlineState(false);
STATUS oldState = states.getOrDefault(model, UNKNOWN);
Model.State state = model.getOnlineState(false);
Model.State oldState = states.getOrDefault(model, UNKNOWN);
states.put(model, state);
if(state != oldState) {
fireModelOnlineStateChanged(model, oldState, state);
EventBusHolder.BUS.post(new ModelStateChangedEvent(model, oldState, state));
}
} catch (HttpException e) {
LOG.error("Couldn't check if model {} is online. HTTP Response: {} - {}",
@ -98,22 +97,6 @@ public class OnlineMonitor extends Thread {
LOG.debug(getName() + " terminated");
}
private void fireModelOnline(Model model) {
Map<String, Object> evt = new HashMap<>();
evt.put(EVENT, MODEL_ONLINE);
evt.put(MODEL, model);
EventBusHolder.BUS.post(evt);
}
private void fireModelOnlineStateChanged(Model model, STATUS oldStatus, STATUS newStatus) {
Map<String, Object> evt = new HashMap<>();
evt.put(EVENT, MODEL_STATUS_CHANGED);
evt.put(STATUS, newStatus);
evt.put(OLD, oldStatus);
evt.put(MODEL, model);
EventBusHolder.BUS.post(evt);
}
public void shutdown() {
running = false;
interrupt();

View File

@ -18,10 +18,10 @@ import com.squareup.moshi.JsonAdapter;
import com.squareup.moshi.Moshi;
import ctbrec.Config;
import ctbrec.EventBusHolder;
import ctbrec.Hmac;
import ctbrec.Model;
import ctbrec.Recording;
import ctbrec.event.EventBusHolder;
import ctbrec.io.HttpClient;
import ctbrec.io.HttpException;
import ctbrec.io.InstantJsonAdapter;

View File

@ -1,5 +1,7 @@
package ctbrec.recorder.download;
import static ctbrec.Recording.State.*;
import java.io.EOFException;
import java.io.File;
import java.io.FileNotFoundException;
@ -24,6 +26,8 @@ import com.iheartradio.m3u8.PlaylistException;
import ctbrec.Config;
import ctbrec.Model;
import ctbrec.event.EventBusHolder;
import ctbrec.event.RecordingStateChangedEvent;
import ctbrec.io.HttpClient;
import ctbrec.io.HttpException;
import okhttp3.Request;
@ -54,6 +58,10 @@ public class HlsDownload extends AbstractHlsDownload {
throw new IOException(model.getName() +"'s room is not public");
}
// let the world know, that we are recording now
RecordingStateChangedEvent evt = new RecordingStateChangedEvent(getTarget(), RECORDING, model, getStartTime());
EventBusHolder.BUS.post(evt);
String segments = getSegmentPlaylistUrl(model);
if(segments != null) {
if (!Files.exists(downloadDir, LinkOption.NOFOLLOW_LINKS)) {

View File

@ -1,5 +1,6 @@
package ctbrec.recorder.download;
import static ctbrec.Recording.State.*;
import static java.nio.file.StandardOpenOption.*;
import java.io.ByteArrayInputStream;
@ -44,6 +45,8 @@ import com.iheartradio.m3u8.PlaylistException;
import ctbrec.Config;
import ctbrec.Hmac;
import ctbrec.Model;
import ctbrec.event.EventBusHolder;
import ctbrec.event.RecordingStateChangedEvent;
import ctbrec.io.HttpClient;
import ctbrec.io.HttpException;
import ctbrec.recorder.ProgressListener;
@ -126,6 +129,11 @@ public class MergedHlsDownload extends AbstractHlsDownload {
splitRecStartTime = ZonedDateTime.now();
super.model = model;
targetFile = Config.getInstance().getFileForRecording(model);
// let the world know, that we are recording now
RecordingStateChangedEvent evt = new RecordingStateChangedEvent(getTarget(), RECORDING, model, getStartTime());
EventBusHolder.BUS.post(evt);
String segments = getSegmentPlaylistUrl(model);
mergeThread = createMergeThread(targetFile, null, true);
mergeThread.start();

View File

@ -1,6 +1,6 @@
package ctbrec.sites.bonga;
import static ctbrec.Model.STATUS.*;
import static ctbrec.Model.State.*;
import java.io.IOException;
import java.io.InputStream;
@ -85,7 +85,7 @@ public class BongaCamsModel extends AbstractModel {
}
@Override
public STATUS getOnlineState(boolean failFast) throws IOException, ExecutionException {
public State getOnlineState(boolean failFast) throws IOException, ExecutionException {
if(failFast) {
return onlineState;
} else {
@ -97,7 +97,7 @@ public class BongaCamsModel extends AbstractModel {
}
@Override
public void setOnlineState(STATUS onlineState) {
public void setOnlineState(State onlineState) {
this.onlineState = onlineState;
}

View File

@ -1,6 +1,6 @@
package ctbrec.sites.cam4;
import static ctbrec.Model.STATUS.*;
import static ctbrec.Model.State.*;
import java.io.IOException;
import java.io.InputStream;
@ -109,7 +109,7 @@ public class Cam4Model extends AbstractModel {
}
@Override
public STATUS getOnlineState(boolean failFast) throws IOException, ExecutionException {
public State getOnlineState(boolean failFast) throws IOException, ExecutionException {
if(failFast) {
return onlineState;
} else {

View File

@ -1,6 +1,6 @@
package ctbrec.sites.camsoda;
import static ctbrec.Model.STATUS.*;
import static ctbrec.Model.State.*;
import java.io.IOException;
import java.io.InputStream;
@ -102,7 +102,7 @@ public class CamsodaModel extends AbstractModel {
}
@Override
public STATUS getOnlineState(boolean failFast) throws IOException, ExecutionException {
public State getOnlineState(boolean failFast) throws IOException, ExecutionException {
if(failFast) {
return onlineState;
} else {

View File

@ -1,6 +1,6 @@
package ctbrec.sites.chaturbate;
import static ctbrec.Model.STATUS.*;
import static ctbrec.Model.State.*;
import java.io.IOException;
import java.util.ArrayList;
@ -76,12 +76,12 @@ public class ChaturbateModel extends AbstractModel {
getChaturbate().streamInfoCache.invalidate(getName());
}
public STATUS getOnlineState() throws IOException, ExecutionException {
public State getOnlineState() throws IOException, ExecutionException {
return getOnlineState(false);
}
@Override
public STATUS getOnlineState(boolean failFast) throws IOException, ExecutionException {
public State getOnlineState(boolean failFast) throws IOException, ExecutionException {
if(failFast) {
StreamInfo info = getChaturbate().streamInfoCache.getIfPresent(getName());
setOnlineStateByRoomStatus(info.room_status);
@ -109,11 +109,11 @@ public class ChaturbateModel extends AbstractModel {
onlineState = AWAY;
break;
case "group":
onlineState = STATUS.GROUP;
onlineState = State.GROUP;
break;
default:
LOG.debug("Unknown show type {}", room_status);
onlineState = STATUS.UNKNOWN;
onlineState = State.UNKNOWN;
}
}
}

View File

@ -601,7 +601,7 @@ public class MyFreeCamsClient {
String name = json.getString("nm");
MyFreeCamsModel model = mfc.createModel(name);
model.setUid(json.getInt("uid"));
model.setState(State.of(json.getInt("vs")));
model.setMfcState(State.of(json.getInt("vs")));
String uid = Integer.toString(model.getUid());
String uidStart = uid.substring(0, 3);
String previewUrl = "https://img.mfcimg.com/photos2/"+uidStart+'/'+uid+"/avatar.90x90.jpg";

View File

@ -46,7 +46,7 @@ public class MyFreeCamsModel extends AbstractModel {
private String hlsUrl;
private double camScore;
private int viewerCount;
private State state;
private ctbrec.sites.mfc.State state;
private int resolution[] = new int[2];
/**
@ -61,7 +61,7 @@ public class MyFreeCamsModel extends AbstractModel {
@Override
public boolean isOnline() throws IOException, ExecutionException, InterruptedException {
MyFreeCamsClient.getInstance().update(this);
return state == State.ONLINE;
return state == ctbrec.sites.mfc.State.ONLINE;
}
@Override
@ -70,27 +70,27 @@ public class MyFreeCamsModel extends AbstractModel {
}
@Override
public STATUS getOnlineState(boolean failFast) throws IOException, ExecutionException {
public State getOnlineState(boolean failFast) throws IOException, ExecutionException {
if(state == null) {
return STATUS.UNKNOWN;
return State.UNKNOWN;
}
switch(state) {
case ONLINE:
case RECORDING:
return ctbrec.Model.STATUS.ONLINE;
return ctbrec.Model.State.ONLINE;
case AWAY:
return ctbrec.Model.STATUS.AWAY;
return ctbrec.Model.State.AWAY;
case PRIVATE:
return ctbrec.Model.STATUS.PRIVATE;
return ctbrec.Model.State.PRIVATE;
case GROUP_SHOW:
return ctbrec.Model.STATUS.GROUP;
return ctbrec.Model.State.GROUP;
case OFFLINE:
case CAMOFF:
return ctbrec.Model.STATUS.OFFLINE;
return ctbrec.Model.State.OFFLINE;
default:
LOG.debug("State {} is not mapped", this.state);
return ctbrec.Model.STATUS.UNKNOWN;
return ctbrec.Model.State.UNKNOWN;
}
}
@ -233,7 +233,7 @@ public class MyFreeCamsModel extends AbstractModel {
this.camScore = camScore;
}
public void setState(State state) {
public void setMfcState(ctbrec.sites.mfc.State state) {
this.state = state;
}
@ -249,7 +249,7 @@ public class MyFreeCamsModel extends AbstractModel {
public void update(SessionState state, String streamUrl) {
uid = Integer.parseInt(state.getUid().toString());
setName(state.getNm());
setState(State.of(state.getVs()));
setMfcState(ctbrec.sites.mfc.State.of(state.getVs()));
setStreamUrl(streamUrl);
Optional<Double> camScore = Optional.ofNullable(state.getM()).map(m -> m.getCamscore());
setCamScore(camScore.orElse(0.0));
@ -258,7 +258,7 @@ public class MyFreeCamsModel extends AbstractModel {
String uid = state.getUid().toString();
String uidStart = uid.substring(0, 3);
String previewUrl = "https://img.mfcimg.com/photos2/"+uidStart+'/'+uid+"/avatar.300x300.jpg";
if(MyFreeCamsModel.this.state == State.ONLINE) {
if(MyFreeCamsModel.this.state == ctbrec.sites.mfc.State.ONLINE) {
try {
previewUrl = getLivePreviewUrl(state);
} catch(Exception e) {