Skip to content

Commit 12be42b

Browse files
committed
Fixes Up Source Refactor according to CodeReview
1 parent af47ce7 commit 12be42b

30 files changed

+682
-434
lines changed

build.gradle

Lines changed: 2 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -50,11 +50,8 @@ allprojects {
5050
// Turn on test results
5151
test {
5252
testLogging {
53-
afterSuite { desc, result ->
54-
if (!desc.parent && project.hasProperty('printTestResults')) {
55-
println "Test results: ${result.resultType} (${result.testCount} tests, ${result.successfulTestCount} passed, ${result.failedTestCount} failed, ${result.skippedTestCount} skipped)"
56-
}
57-
}
53+
events "failed"
54+
exceptionFormat "full"
5855
}
5956
}
6057
}
Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
package edu.wpi.grip.core;
2+
3+
4+
/**
5+
* An Object that can switch its value.
6+
*/
7+
public interface PreviousNext {
8+
9+
/**
10+
* Perform the next action on this object.
11+
*/
12+
void next();
13+
14+
/**
15+
* Perform the previous action on this object.
16+
*/
17+
void previous();
18+
19+
}
Lines changed: 49 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,49 @@
1+
package edu.wpi.grip.core;
2+
3+
4+
import com.google.common.eventbus.EventBus;
5+
6+
import java.io.IOException;
7+
import java.util.concurrent.TimeoutException;
8+
9+
/**
10+
* An Object that can be stopped and started multiple times.
11+
*/
12+
public interface StartStoppable {
13+
14+
/**
15+
* Starts this StartStoppable
16+
*
17+
* @return Itself
18+
* @throws IOException If cleaning up some system resource fails
19+
*/
20+
default <T extends StartStoppable> T start(EventBus eventBus) throws IOException {
21+
start();
22+
eventBus.register(this);
23+
return (T) this;
24+
}
25+
26+
/**
27+
* Any method that overrides this method should post a {@link edu.wpi.grip.core.events.StartedStoppedEvent}
28+
* to the {@link EventBus} if is successfully starts.
29+
*
30+
* @throws IOException If cleaning up some system resource fails
31+
*/
32+
void start() throws IOException;
33+
34+
/**
35+
* Any method that overrides this method should post a {@link edu.wpi.grip.core.events.StartedStoppedEvent}
36+
* to the {@link EventBus} if is successfully stops.
37+
*
38+
* @throws TimeoutException If the thread fails to stop in a timely manner
39+
* @throws IOException If cleaning up some system resource fails.
40+
*/
41+
void stop() throws TimeoutException, IOException;
42+
43+
/**
44+
* Used to indicate if the source is running or stopped
45+
*
46+
* @return true if this source is running
47+
*/
48+
boolean isStarted();
49+
}

core/src/main/java/edu/wpi/grip/core/StopStartSource.java

Lines changed: 0 additions & 52 deletions
This file was deleted.

core/src/main/java/edu/wpi/grip/core/SwitchableSource.java

Lines changed: 0 additions & 23 deletions
This file was deleted.

core/src/main/java/edu/wpi/grip/core/events/SourceStartedEvent.java

Lines changed: 0 additions & 19 deletions
This file was deleted.

core/src/main/java/edu/wpi/grip/core/events/SourceStoppedEvent.java

Lines changed: 0 additions & 18 deletions
This file was deleted.
Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
package edu.wpi.grip.core.events;
2+
3+
4+
import edu.wpi.grip.core.StartStoppable;
5+
6+
/**
7+
* An event that occurs when a {@link StartStoppable StartStoppable's} state changes.
8+
*/
9+
public class StartedStoppedEvent {
10+
private final StartStoppable startStoppable;
11+
12+
public StartedStoppedEvent(StartStoppable startStoppable) {
13+
this.startStoppable = startStoppable;
14+
}
15+
16+
public StartStoppable getStartStoppable() {
17+
return this.startStoppable;
18+
}
19+
}

core/src/main/java/edu/wpi/grip/core/sources/CameraSource.java

Lines changed: 24 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -5,14 +5,10 @@
55
import com.google.common.eventbus.EventBus;
66
import com.google.common.eventbus.Subscribe;
77
import com.thoughtworks.xstream.annotations.XStreamAlias;
8-
import edu.wpi.grip.core.OutputSocket;
9-
import edu.wpi.grip.core.SocketHint;
10-
import edu.wpi.grip.core.SocketHints;
11-
import edu.wpi.grip.core.events.UnexpectedThrowableEvent;
12-
import edu.wpi.grip.core.StopStartSource;
8+
import edu.wpi.grip.core.*;
139
import edu.wpi.grip.core.events.SourceRemovedEvent;
14-
import edu.wpi.grip.core.events.SourceStartedEvent;
15-
import edu.wpi.grip.core.events.SourceStoppedEvent;
10+
import edu.wpi.grip.core.events.StartedStoppedEvent;
11+
import edu.wpi.grip.core.events.UnexpectedThrowableEvent;
1612
import org.bytedeco.javacpp.opencv_core.Mat;
1713
import org.bytedeco.javacv.*;
1814

@@ -29,7 +25,7 @@
2925
* Provides a way to generate a constantly updated {@link Mat} from a camera
3026
*/
3127
@XStreamAlias(value = "grip:Camera")
32-
public class CameraSource extends StopStartSource {
28+
public final class CameraSource extends Source implements StartStoppable {
3329

3430
private final static String DEVICE_NUMBER_PROPERTY = "deviceNumber";
3531
private final static String ADDRESS_PROPERTY = "address";
@@ -126,9 +122,9 @@ public void createFromProperties(EventBus eventBus, Properties properties) throw
126122
}
127123

128124
/**
129-
* Starts the video capture from the source device
125+
* Starts the video capture from this frame grabber.
130126
*/
131-
protected void start() throws IOException, IllegalStateException {
127+
public void start() throws IOException, IllegalStateException {
132128
final OpenCVFrameConverter.ToMat convertToMat = new OpenCVFrameConverter.ToMat();
133129
synchronized (this) {
134130
if (this.frameThread.isPresent()) {
@@ -166,28 +162,33 @@ protected void start() throws IOException, IllegalStateException {
166162

167163
frameExecutor.setUncaughtExceptionHandler(
168164
(thread, exception) -> {
165+
// TODO: This should use the ExceptionWitness once that has a UI component added for it
169166
eventBus.post(new UnexpectedThrowableEvent(exception, "Camera Frame Grabber Thread crashed with uncaught exception"));
170167
try {
171168
stop();
172169
} catch (TimeoutException e) {
170+
// TODO: This should use the ExceptionWitness once that has a UI component added for it
173171
eventBus.post(new UnexpectedThrowableEvent(e, "Camera Frame Grabber could not be stopped!"));
174172
}
175173
}
176174
);
177175
frameExecutor.setDaemon(true);
178176
frameExecutor.start();
179177
this.frameThread = Optional.of(frameExecutor);
178+
// This should only be posted now that it is running
179+
eventBus.post(new StartedStoppedEvent(this));
180180
}
181-
eventBus.post(new SourceStartedEvent(this));
182181
}
183182

184183
/**
185-
* Stops the video feed from updating the output socket.
184+
* Stops this source.
185+
* This will stop the source publishing new socket values after this method returns.
186186
*
187-
* @throws TimeoutException If the thread running the Webcam fails to join this one after a timeout.
188-
* @throws IllegalStateException If the camera was already stopped
187+
* @return The source that was stopped
188+
* @throws TimeoutException if the thread running the source fails to stop.
189+
* @throws IOException If there is a problem stopping the Source
189190
*/
190-
public void stop() throws TimeoutException, IllegalStateException {
191+
public final void stop() throws TimeoutException, IllegalStateException {
191192
synchronized (this) {
192193
if (frameThread.isPresent()) {
193194
final Thread ex = frameThread.get();
@@ -197,16 +198,17 @@ public void stop() throws TimeoutException, IllegalStateException {
197198
if (ex.isAlive()) {
198199
throw new TimeoutException("Unable to terminate video feed from Web Camera");
199200
}
201+
// This should only be removed if the thread is successfully killed off
202+
frameThread = Optional.empty();
200203
} catch (InterruptedException e) {
201204
Thread.currentThread().interrupt();
202205
//TODO: Move this into a logging framework
203-
System.out.println("Caught Exception:");
206+
System.err.println("Caught Exception:");
204207
e.printStackTrace();
205208
} finally {
206-
// Clean up this resource as you can't restart a stopped thread
207-
this.frameThread = Optional.empty();
208209
// This will always run even if a timeout exception occurs
209210
try {
211+
// Calling this multiple times will have no effect
210212
grabber.stop();
211213
} catch (FrameGrabber.Exception e) {
212214
throw new IllegalStateException("A problem occurred trying to stop the frame grabber", e);
@@ -216,22 +218,20 @@ public void stop() throws TimeoutException, IllegalStateException {
216218
throw new IllegalStateException("Tried to stop a Webcam that is already stopped.");
217219
}
218220
}
219-
eventBus.post(new SourceStoppedEvent(this));
221+
eventBus.post(new StartedStoppedEvent(this));
220222
frameRateOutputSocket.setValue(0);
221223
}
222224

223225
@Override
224-
public boolean isRunning() {
225-
synchronized (this) {
226-
return this.frameThread.isPresent() && this.frameThread.get().isAlive();
227-
}
226+
public synchronized boolean isStarted() {
227+
return this.frameThread.isPresent() && this.frameThread.get().isAlive();
228228
}
229229

230230
@Subscribe
231231
public void onSourceRemovedEvent(SourceRemovedEvent event) throws TimeoutException {
232232
if (event.getSource() == this) {
233233
try {
234-
if (this.isRunning()) this.stop();
234+
if (this.isStarted()) this.stop();
235235
} finally {
236236
this.eventBus.unregister(this);
237237
}

core/src/main/java/edu/wpi/grip/core/sources/ImageFileSource.java

Lines changed: 3 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -7,8 +7,7 @@
77
import edu.wpi.grip.core.SocketHint;
88
import edu.wpi.grip.core.SocketHints;
99
import edu.wpi.grip.core.Source;
10-
import edu.wpi.grip.core.events.SourceStartedEvent;
11-
import edu.wpi.grip.core.util.OpenCVUtility;
10+
import edu.wpi.grip.core.util.ImageLoadingUtility;
1211
import org.bytedeco.javacpp.opencv_core.Mat;
1312
import org.bytedeco.javacpp.opencv_imgcodecs;
1413

@@ -25,7 +24,7 @@
2524
* Provides a way to generate a {@link Mat} from an image on the filesystem.
2625
*/
2726
@XStreamAlias(value = "grip:ImageFile")
28-
public class ImageFileSource extends Source {
27+
public final class ImageFileSource extends Source {
2928

3029
private final String PATH_PROPERTY = "path";
3130

@@ -96,8 +95,7 @@ private void loadImage(String path) throws IOException {
9695

9796

9897
private void loadImage(String path, final int flags) throws IOException {
99-
OpenCVUtility.loadImage(path, flags, this.outputSocket.getValue().get());
98+
ImageLoadingUtility.loadImage(path, flags, this.outputSocket.getValue().get());
10099
this.outputSocket.setValue(this.outputSocket.getValue().get());
101-
this.eventBus.post(new SourceStartedEvent(this));
102100
}
103101
}

0 commit comments

Comments
 (0)