diff --git a/src/app/CMakeLists.txt b/src/app/CMakeLists.txt
index 72c7adc..7c38cc7 100644
--- a/src/app/CMakeLists.txt
+++ b/src/app/CMakeLists.txt
@@ -16,6 +16,7 @@ add_executable(rascapp
     cpp/main.cpp
     cpp/main-window.cpp
     cpp/camera-drawing-area.cpp
+    cpp/service-locator.cpp
 )
 
 # Add folder with all headers:
diff --git a/src/app/cpp/camera-drawing-area.cpp b/src/app/cpp/camera-drawing-area.cpp
index 5648929..021d8b1 100644
--- a/src/app/cpp/camera-drawing-area.cpp
+++ b/src/app/cpp/camera-drawing-area.cpp
@@ -1,12 +1,25 @@
+#define _USE_MATH_DEFINES
+
 #include "camera-drawing-area.hpp"
+
+#include "service-locator.hpp"
 #include "system-helper.hpp"
 
 #include <opencv2/imgproc.hpp>
 
+#include <math.h>
+
 CameraDrawingArea::CameraDrawingArea():
-dispatchInvalidate() {
+dispatchInvalidate(),
+movieMaker(ServiceLocator::getMovieMaker()),
+captureImageFromCamera(ServiceLocator::getCaptureImageFromCamera()){
+
+    fontDescription.set_family("Monospace");
+    fontDescription.set_weight(Pango::WEIGHT_BOLD);
+    fontDescription.set_size(10 * Pango::SCALE);
+
     dispatchInvalidate.
-        connect(sigc::mem_fun(*this, 
+        connect(sigc::mem_fun(*this,
                     &CameraDrawingArea::doInvalidate));
     eventBus.subscribe(this);
 }
@@ -17,7 +30,11 @@ CameraDrawingArea::~CameraDrawingArea() {
 
 void CameraDrawingArea::receive(EventOrangeDetected e) {
     if (width > 0 && height > 0) {
-        resize(e.getCapturedImage(), output, cv::Size(width, height), 0, 0, cv::INTER_LINEAR);
+        // Resize captured image without changing its aspect:
+        cv::Mat capturedImage = e.getCapturedImage();
+        double capturedImageWidth = capturedImage.size().width;
+        double scale = width / capturedImageWidth;
+        resize(capturedImage, output, cv::Size(), scale, scale, cv::INTER_LINEAR);
 
         // Initializes a pixbuf sharing the same data as the mat:
         std::lock_guard<std::mutex> guard(pixbufMutex);
@@ -29,7 +46,10 @@ void CameraDrawingArea::receive(EventOrangeDetected e) {
                 output.cols,
                 output.rows,
                 (int) output.step);
-
+        
+        // Remember the event for later.
+        lastDetectedOrange = e;
+        
         // Invalidate the window, but for that we need to be in the GUI thread.
         dispatchInvalidate.emit();
 	}
@@ -49,9 +69,73 @@ bool CameraDrawingArea::on_draw(const Cairo::RefPtr<Cairo::Context>& cr) {
         cr->paint();
     }
 
+    if (movieMaker->isRecording()) {
+        displayRec(cr);
+    }
+
+    highlightOrange(cr);
+    displayCaptureRate(cr, captureImageFromCamera->getCaptureRate());
+    displayFrameRate(cr, captureImageFromCamera->getFrameRate());
+
     return true;
 }
 
+void CameraDrawingArea::highlightOrange(const Cairo::RefPtr<Cairo::Context>& cr) {
+    if (lastDetectedOrange.hasDetectedSomething()) {
+        double radius = lastDetectedOrange.getRadius() * width;
+        double x = lastDetectedOrange.getBallPosition().x * width;
+        double y = lastDetectedOrange.getBallPosition().y * width;
+        cr->set_source_rgb(1.0, 0.5, 0.1);
+        cr->arc(x, y, radius, 0, 2 * M_PI);
+        cr->set_line_width(5);
+        cr->stroke();
+    }
+}
+
+void CameraDrawingArea::displayRec(const Cairo::RefPtr<Cairo::Context>& cr) {
+    double radius = 7;
+    double x = width / 2;
+    double y = height - radius;
+    cr->set_source_rgb(1.0, 0.1, 0.1);
+    cr->arc(x, y, radius, 0, 2 * M_PI);
+    cr->fill();
+    cr->stroke();
+}
+
+void CameraDrawingArea::displayCaptureRate(const Cairo::RefPtr<Cairo::Context> &cr, double captureRate) {
+
+    char text[30];
+    sprintf(text, "CR %.1f fps", captureRate);
+
+    auto layout = create_pango_layout(text);
+    layout->set_font_description(fontDescription);
+
+    int textWidth, textHeight;
+    layout->get_pixel_size(textWidth, textHeight);
+
+    cr->move_to(0, height - textHeight);
+
+    cr->set_source_rgb(1.0, 1.0, 1.0);
+    layout->show_in_cairo_context(cr);
+}
+
+void CameraDrawingArea::displayFrameRate(const Cairo::RefPtr<Cairo::Context> &cr, double frameRate) {
+
+    char text[30];
+    sprintf(text, "FR %.1f fps", frameRate);
+
+    auto layout = create_pango_layout(text);
+    layout->set_font_description(fontDescription);
+
+    int textWidth, textHeight;
+    layout->get_pixel_size(textWidth, textHeight);
+
+    cr->move_to(width - textWidth, height - textHeight);
+
+    cr->set_source_rgb(1.0, 1.0, 1.0);
+    layout->show_in_cairo_context(cr);
+}
+
 void CameraDrawingArea::on_size_allocate (Gtk::Allocation& allocation) {
     DrawingArea::on_size_allocate(allocation);
 
diff --git a/src/app/cpp/main-window.cpp b/src/app/cpp/main-window.cpp
index c82d59f..f95e0b5 100644
--- a/src/app/cpp/main-window.cpp
+++ b/src/app/cpp/main-window.cpp
@@ -1,45 +1,25 @@
 #include "main-window.hpp"
 
+#include "service-locator.hpp"
+
 #include <iostream>
 
 MainWindow::MainWindow(int width, int height):
 probablyInFullScreen(false),
-m_button("Hello World"),
-m_box(Gtk::ORIENTATION_VERTICAL),
-m_label1("First Label") {
+movieMaker(ServiceLocator::getMovieMaker()){
     // Configure this window:
     this->set_default_size(width, height);
 
-    // Connect the 'click' signal and make the button visible:
-    m_button.signal_clicked().connect(
-            sigc::mem_fun(*this, &MainWindow::buttonClick));
-    m_button.show();
-
-    // Make the first label visible:
-    m_label1.show();
-
     // Make the second label visible:
     cameraDrawingArea.show();
 
-    // Pack all elements in the box:
-    m_box.pack_start(m_button, Gtk::PACK_SHRINK);
-    m_box.pack_start(m_label1, Gtk::PACK_SHRINK);
-    m_box.pack_start(cameraDrawingArea, Gtk::PACK_EXPAND_WIDGET);
-
     // Add the box in this window:
-    add(m_box);
-
-    // Make the box visible:
-    m_box.show();
+    add(cameraDrawingArea);
 
     // Activate Key-Press events
     add_events(Gdk::KEY_PRESS_MASK);
 }
 
-void MainWindow::buttonClick() {
-    std::cout << "Hello World" << std::endl;
-}
-
 bool MainWindow::on_key_press_event(GdkEventKey* event) {
     switch (event->keyval) {
         // Ctrl + C: Ends the application:
@@ -49,7 +29,13 @@ bool MainWindow::on_key_press_event(GdkEventKey* event) {
                 get_application()->quit();
             }
             return true;
-
+            
+        // [P] Toggles the record pause:
+        case GDK_KEY_P:
+        case GDK_KEY_p:
+            movieMaker->toggleRecording();
+            return true;
+            
         // [F] toggles full screen mode:
         case GDK_KEY_F:
         case GDK_KEY_f:
diff --git a/src/app/cpp/main.cpp b/src/app/cpp/main.cpp
index 99b1a4d..b800cfb 100644
--- a/src/app/cpp/main.cpp
+++ b/src/app/cpp/main.cpp
@@ -1,20 +1,12 @@
 #include "main-window.hpp"
 
-#include "capture-image-from-camera.hpp"
-#include "event-bus.hpp"
-#include "movie-maker.hpp"
-#include "orange-ball-detector.hpp"
-#include "system-helper.hpp"
+#include "service-locator.hpp"
 
-int main (int argc, char *argv[]) {
-    CaptureImageFromCamera captureImageFromCamera;
-    OrangeBallDetector orangeBallDetector;
-    MovieMaker movieMaker(obtainPathToDesktopFolder().append("/live.avi"), 20.0);
 
-    EventBus<EventImageCaptured> eventImageBus;
-    eventImageBus.subscribe(&orangeBallDetector);
-    eventImageBus.subscribe(&movieMaker);
+int main (int argc, char *argv[]) {
 
+    ServiceLocator::startUp();
+    
     auto app = Gtk::Application::create(
             argc, 
             argv, 
diff --git a/src/app/cpp/service-locator.cpp b/src/app/cpp/service-locator.cpp
new file mode 100644
index 0000000..c46382b
--- /dev/null
+++ b/src/app/cpp/service-locator.cpp
@@ -0,0 +1,38 @@
+#include "service-locator.hpp"
+
+#include "system-helper.hpp"
+
+void ServiceLocator::startUp() {
+    getInstance();
+}
+
+ServiceLocator * ServiceLocator::getInstance() {
+    static ServiceLocator serviceLocator;
+    return &serviceLocator;
+}
+
+ServiceLocator::ServiceLocator():
+movieMaker(obtainPathToDesktopFolder().append("/live.avi"), 20.0),
+captureImageFromCamera(),
+orangeBallDetector(),
+eventImageBus() {
+    eventImageBus.subscribe(&orangeBallDetector);
+    eventImageBus.subscribe(&movieMaker);
+}
+
+ServiceLocator::~ServiceLocator() {
+    eventImageBus.unsubscribe(&orangeBallDetector);
+    eventImageBus.unsubscribe(&movieMaker);
+}
+
+MovieMaker * ServiceLocator::getMovieMaker() {
+    return & getInstance()->movieMaker;
+}
+
+CaptureImageFromCamera * ServiceLocator::getCaptureImageFromCamera() {
+    return & getInstance()->captureImageFromCamera;
+}
+
+OrangeBallDetector * ServiceLocator::getOrangeBallDetector() {
+    return & getInstance()->orangeBallDetector;
+}
diff --git a/src/app/hpp/camera-drawing-area.hpp b/src/app/hpp/camera-drawing-area.hpp
index 8dcdca0..182b047 100644
--- a/src/app/hpp/camera-drawing-area.hpp
+++ b/src/app/hpp/camera-drawing-area.hpp
@@ -1,6 +1,7 @@
 #ifndef CAMERA_DRAWING_AREA_HPP
 #define CAMERA_DRAWING_AREA_HPP
 
+#include "capture-image-from-camera.hpp"
 #include "movie-maker.hpp"
 #include "orange-ball-detector.hpp"
 
@@ -22,10 +23,18 @@ public Subscriptor<EventOrangeDetected> {
 private:
     Glib::Dispatcher dispatchInvalidate;
     void doInvalidate();
-    cv::Mat output;
-    Glib::RefPtr<Gdk::Pixbuf> pixbuf;
+	cv::Mat output;
+	int width, height;
+	EventBus<EventOrangeDetected> eventBus;
+    MovieMaker * movieMaker;
+    CaptureImageFromCamera * captureImageFromCamera;
     std::mutex pixbufMutex;
-    int width, height;
-    EventBus<EventOrangeDetected> eventBus;
+    Glib::RefPtr<Gdk::Pixbuf> pixbuf;
+    Pango::FontDescription fontDescription;
+    EventOrangeDetected lastDetectedOrange;
+    void highlightOrange(const Cairo::RefPtr<Cairo::Context>& cr);
+    void displayRec(const Cairo::RefPtr<Cairo::Context>& cr);
+    void displayCaptureRate(const Cairo::RefPtr<Cairo::Context>& cr, double captureRate);
+    void displayFrameRate(const Cairo::RefPtr<Cairo::Context>& cr, double captureRate);
 };
 #endif
diff --git a/src/app/hpp/main-window.hpp b/src/app/hpp/main-window.hpp
index 5331f9a..237caf6 100644
--- a/src/app/hpp/main-window.hpp
+++ b/src/app/hpp/main-window.hpp
@@ -14,12 +14,9 @@ class MainWindow : public Gtk::Window {
     bool on_key_press_event(GdkEventKey* event) override;
 
 private:
-    void buttonClick();
     bool probablyInFullScreen;
-    Gtk::Button m_button;
-    Gtk::Box m_box;
-    Gtk::Label m_label1;
     CameraDrawingArea cameraDrawingArea;
+    MovieMaker * movieMaker;
 };
 
 #endif
diff --git a/src/app/hpp/service-locator.hpp b/src/app/hpp/service-locator.hpp
new file mode 100644
index 0000000..3eba748
--- /dev/null
+++ b/src/app/hpp/service-locator.hpp
@@ -0,0 +1,33 @@
+#ifndef SERVICE_LOCATOR_HPP
+#define SERVICE_LOCATOR_HPP
+
+#include "movie-maker.hpp"
+#include "capture-image-from-camera.hpp"
+#include "orange-ball-detector.hpp"
+
+class ServiceLocator {
+public:
+    virtual ~ServiceLocator();
+
+    static void startUp();
+    static ServiceLocator * getInstance();
+    static MovieMaker * getMovieMaker();
+    static CaptureImageFromCamera * getCaptureImageFromCamera();
+    static OrangeBallDetector * getOrangeBallDetector();
+
+    // Don't copy a singleton.
+    ServiceLocator(const ServiceLocator &) = delete;
+    // Don't copy a singleton.
+    ServiceLocator& operator= (const ServiceLocator &) = delete;
+
+private:
+    MovieMaker movieMaker;
+    CaptureImageFromCamera captureImageFromCamera;
+    OrangeBallDetector orangeBallDetector;
+    EventBus<EventImageCaptured> eventImageBus;
+    
+    // Don't instantiate a singleton.
+    ServiceLocator();
+};
+
+#endif
diff --git a/src/lib/CMakeLists.txt b/src/lib/CMakeLists.txt
index 4236268..606ec3e 100644
--- a/src/lib/CMakeLists.txt
+++ b/src/lib/CMakeLists.txt
@@ -8,6 +8,7 @@ set(RASCLIB_SOURCES
 	cpp/orange-ball-detector
 	cpp/movie-maker
 	cpp/capture-image-from-camera
+	cpp/rate-meter
 )
 
 if (WIN32)
@@ -39,4 +40,4 @@ target_link_libraries(rasclib ${RASCLIB_LIBRARIES})
 export(TARGETS rasclib FILE rasclib.cmake)
 
 # Let's have unit tests:
-add_subdirectory(tst)
\ No newline at end of file
+add_subdirectory(tst)
diff --git a/src/lib/cpp/capture-image-from-camera.cpp b/src/lib/cpp/capture-image-from-camera.cpp
index 31b8c77..e5b253a 100644
--- a/src/lib/cpp/capture-image-from-camera.cpp
+++ b/src/lib/cpp/capture-image-from-camera.cpp
@@ -37,15 +37,32 @@ void CaptureImageFromCamera::stopCapturing() {
 void CaptureImageFromCamera::doCapture() {
     do {
         videoCapture.grab();
+        frameRate.updateRate();
+
         videoCapture.grab();
+        frameRate.updateRate();
+
         videoCapture.grab();
+        frameRate.updateRate();
+
         videoCapture.read(webcam);
+        frameRate.updateRate();
+        captureRate.updateRate();
+
         if (!webcam.empty()) {
             doPropagate();
         }
     } while (keepCapturing);
 }
 
+double CaptureImageFromCamera::getFrameRate() {
+    return frameRate.getRate();
+}
+
+double CaptureImageFromCamera::getCaptureRate() {
+    return captureRate.getRate();
+}
+
 void CaptureImageFromCamera::doPropagate() {
     if (propagateThread) {
         propagateThread->join();
diff --git a/src/lib/cpp/movie-maker.cpp b/src/lib/cpp/movie-maker.cpp
index dd72718..b192cd6 100644
--- a/src/lib/cpp/movie-maker.cpp
+++ b/src/lib/cpp/movie-maker.cpp
@@ -6,6 +6,7 @@ using namespace cv;
 MovieMaker::MovieMaker(string filename, double fps):
 videoWriter(),
 isMovieStarted(false),
+recording(true),
 filename(filename),
 fps(fps) {
     // Nothing to do.
@@ -15,17 +16,27 @@ MovieMaker::~MovieMaker() {
     endMovie();
 }
 
+bool MovieMaker::isRecording() {
+    return recording;
+}
+
+void MovieMaker::toggleRecording() {
+    recording = !recording;
+}
+
 void MovieMaker::receive(EventImageCaptured e) {
     addPhotogram(e.getCapturedImage());
 }
 
 void MovieMaker::addPhotogram(Mat photogram) {
-    if (!photogram.empty()) {
-        if (!isMovieStarted) {
-            startMovie(photogram);
-            isMovieStarted = true;
+    if (recording) {
+        if (!photogram.empty()) {
+            if (!isMovieStarted) {
+                startMovie(photogram);
+                isMovieStarted = true;
+            }
+            videoWriter.write(photogram);
         }
-        videoWriter.write(photogram);
     }
 }
 
diff --git a/src/lib/cpp/orange-ball-detector.cpp b/src/lib/cpp/orange-ball-detector.cpp
index 13e20ff..9d6b777 100644
--- a/src/lib/cpp/orange-ball-detector.cpp
+++ b/src/lib/cpp/orange-ball-detector.cpp
@@ -2,6 +2,8 @@
 
 #include <opencv2/imgproc.hpp>
 
+#define ORANGE_BALL_DETECTOR_IMAGE_WIDTH 600
+
 void OrangeBallDetector::receive(EventImageCaptured e) {
     detect(e.getCapturedImage());
 }
@@ -16,7 +18,7 @@ void OrangeBallDetector::detect(cv::Mat image) {
 
     // Make the image of a reasonable size:
     double width = image.size().width;
-    double scale = 600 / width;
+    double scale = ORANGE_BALL_DETECTOR_IMAGE_WIDTH / width;
     resize(image, resizedImage, cv::Size(), scale, scale, cv::INTER_LINEAR);
     showIfDebug(resizedImage);
 
@@ -59,14 +61,12 @@ void OrangeBallDetector::detect(cv::Mat image) {
         // Assuming that biggest contour is a circle,
         // determine its center and size:
         cv::minEnclosingCircle(maxContour, ballPosition, radius);
-
-        // Draw the circle:
-        if (radius > 20) {
-            cv::circle(resizedImage, ballPosition, radius, cv::Scalar(0, 255, 0), 3);
-        }
         showIfDebug(resizedImage);
     }
-    eventBus.propagate(EventOrangeDetected(resizedImage, ballPosition, radius));
+    eventBus.propagate(EventOrangeDetected(
+            resizedImage,
+            ballPosition / ORANGE_BALL_DETECTOR_IMAGE_WIDTH,
+            radius / ORANGE_BALL_DETECTOR_IMAGE_WIDTH));
 }
 
 void OrangeBallDetector::setDebug(bool d) {
@@ -75,6 +75,9 @@ void OrangeBallDetector::setDebug(bool d) {
 
 void OrangeBallDetector::showIfDebug(cv::Mat m) {
     if (debug) {
+        if (radius > 20) {
+            cv::circle(m, ballPosition, radius, cv::Scalar(0, 255, 0), 3);
+        }
         imshow("orange-ball-detector", m);
         cv::waitKey(0);
     }
@@ -122,5 +125,5 @@ float EventOrangeDetected::getRadius() {
 }
 
 bool EventOrangeDetected::hasDetectedSomething() {
-    return radius > 10;
+    return radius > 10 / ORANGE_BALL_DETECTOR_IMAGE_WIDTH;
 }
diff --git a/src/lib/cpp/rate-meter.cpp b/src/lib/cpp/rate-meter.cpp
new file mode 100644
index 0000000..21d7e44
--- /dev/null
+++ b/src/lib/cpp/rate-meter.cpp
@@ -0,0 +1,25 @@
+#include "rate-meter.hpp"
+
+using namespace std::chrono;
+
+RateMeter::RateMeter():
+rate(0),
+lastSampleSystemClock(high_resolution_clock::now()) {
+}
+
+void RateMeter::updateRate() {
+    time_point<high_resolution_clock> now = high_resolution_clock::now();
+    std::chrono::duration<double> difference = now - lastSampleSystemClock;
+    lastSampleSystemClock = now;
+
+    double count = difference.count();
+    if (count == 0) {
+        rate = 0;
+    } else {
+        rate = 1 / difference.count();
+    }
+}
+
+double RateMeter::getRate() {
+    return rate;
+}
diff --git a/src/lib/hpp/capture-image-from-camera.hpp b/src/lib/hpp/capture-image-from-camera.hpp
index c903b75..f4ba67a 100644
--- a/src/lib/hpp/capture-image-from-camera.hpp
+++ b/src/lib/hpp/capture-image-from-camera.hpp
@@ -2,6 +2,7 @@
 #define CAPTURE_IMAGE_FROM_CAMERA_HPP
 
 #include "event-bus.hpp"
+#include "rate-meter.hpp"
 
 #include <opencv2/highgui.hpp>
 
@@ -22,12 +23,15 @@ class CaptureImageFromCamera {
 	virtual ~CaptureImageFromCamera();
 	void startCapturing();
 	void stopCapturing();
+    double getFrameRate();
+    double getCaptureRate();
 private:
 	bool keepCapturing;
-	void doCapture();
+	void doCapture();
 	void doPropagate();
-	std::thread* captureThread;
-	std::thread* propagateThread;
+    std::thread * captureThread;
+    std::thread * propagateThread;
+    RateMeter frameRate, captureRate;
 	cv::VideoCapture videoCapture;
 	cv::Mat webcam;
 	EventBus<EventImageCaptured> eventBus;
diff --git a/src/lib/hpp/movie-maker.hpp b/src/lib/hpp/movie-maker.hpp
index c30225c..9087715 100644
--- a/src/lib/hpp/movie-maker.hpp
+++ b/src/lib/hpp/movie-maker.hpp
@@ -13,9 +13,12 @@ class MovieMaker: public Subscriptor<EventImageCaptured> {
     void endMovie();
     void addPhotogram(cv::Mat photogram);
     void receive(EventImageCaptured e);
+    void toggleRecording();
+    bool isRecording();
 private:
     cv::VideoWriter videoWriter;
     bool isMovieStarted;
+    bool recording;
     std::string filename;
     double fps;
     
diff --git a/src/lib/hpp/rate-meter.hpp b/src/lib/hpp/rate-meter.hpp
new file mode 100644
index 0000000..c695be6
--- /dev/null
+++ b/src/lib/hpp/rate-meter.hpp
@@ -0,0 +1,19 @@
+#ifndef RATE_METER_HPP
+#define RATE_METER_HPP
+
+#include <chrono>
+
+using namespace std::chrono;
+
+class RateMeter {
+public:
+    RateMeter();
+    void updateRate();
+    double getRate();
+    
+private:
+    double rate;
+    time_point<high_resolution_clock> lastSampleSystemClock;
+};
+
+#endif
diff --git a/src/lib/tst/CMakeLists.txt b/src/lib/tst/CMakeLists.txt
index d8054f7..0cd0c67 100644
--- a/src/lib/tst/CMakeLists.txt
+++ b/src/lib/tst/CMakeLists.txt
@@ -19,6 +19,7 @@ add_executable(rasctest
 	movie-maker-test
 	event-bus-test
 	system-helper-test
+	rate-meter-test
 )
 
 target_include_directories(rasctest PRIVATE ${PROJECT_BINARY_DIR})
@@ -30,4 +31,4 @@ target_link_libraries(rasctest
 )
 
 # Adds the executable to the test goal:
-add_test(test rasctest)
\ No newline at end of file
+add_test(test rasctest)
diff --git a/src/lib/tst/movie-maker-test.cpp b/src/lib/tst/movie-maker-test.cpp
index e542b7d..136646c 100644
--- a/src/lib/tst/movie-maker-test.cpp
+++ b/src/lib/tst/movie-maker-test.cpp
@@ -8,41 +8,62 @@
 using namespace std;
 using namespace cv;
 
+int nonEmptyFrames(string movieFileName) {
+    cv::Mat mat;
+    cv::VideoCapture movieReader(movieFileName);
+    int n = 0;
+    while(1) {
+        movieReader.read(mat);
+        if (mat.empty()) {
+            break;
+        }
+        n++;
+        REQUIRE(mat.size().width == 640);
+        REQUIRE(mat.size().height == 400);
+    }
+    return n;
+}
+
 SCENARIO("Can make a movie") {
-    GIVEN( "An initialized movie maker") {
-        string filename("./live.avi");
+    
+    string filename("./live.avi");
+    EventBus<EventImageCaptured> capturedImageEventBus;
+
+    Mat mat1, mat2, mat3;
+    mat1 = imread(string(PATH_TO_TEST_DATA).append("/abc-a.png"));
+    mat2 = imread(string(PATH_TO_TEST_DATA).append("/abc-b.png"));
+    mat3 = imread(string(PATH_TO_TEST_DATA).append("/abc-c.png"));
 
-        EventBus<EventImageCaptured> capturedImageEventBus;
+    GIVEN( "An initialized movie maker") {
         MovieMaker movieMaker(filename, 10.0);
         capturedImageEventBus.subscribe(&movieMaker);
         
         WHEN( "Fed with images") {
-            Mat mat;
-            mat = imread(string(PATH_TO_TEST_DATA).append("/abc-a.png"));
-            capturedImageEventBus.propagate(EventImageCaptured(mat));
-            mat = imread(string(PATH_TO_TEST_DATA).append("/abc-b.png"));
-            capturedImageEventBus.propagate(EventImageCaptured(mat));
-            mat = imread(string(PATH_TO_TEST_DATA).append("/abc-c.png"));
-            capturedImageEventBus.propagate(EventImageCaptured(mat));
+            capturedImageEventBus.propagate(EventImageCaptured(mat1));
+            capturedImageEventBus.propagate(EventImageCaptured(mat2));
+            capturedImageEventBus.propagate(EventImageCaptured(mat3));
 
             movieMaker.endMovie();
             
             THEN ( "Can make a movie") {
-                cv::VideoCapture movieReader(filename);
-                int n = 0;
-                while(1) {
-                    movieReader.read(mat);
-                    if (mat.empty()) {
-                        break;
-                    }
-                    n++;
-                    REQUIRE(mat.size().width == 640);
-                    REQUIRE(mat.size().height == 400);
-                }
-                REQUIRE( n == 3);
+                REQUIRE( nonEmptyFrames(filename) == 3);
+            }
+        }
+        WHEN( "Toggling the recording") {
+            capturedImageEventBus.propagate(EventImageCaptured(mat1));
+            
+            movieMaker.toggleRecording();
+            capturedImageEventBus.propagate(EventImageCaptured(mat2));
+            movieMaker.toggleRecording();
+            
+            capturedImageEventBus.propagate(EventImageCaptured(mat3));
+            
+            movieMaker.endMovie();
+            
+            THEN ( "Skips the images propagated during pause") {
+                REQUIRE( nonEmptyFrames(filename) == 2);
             }
         }
         capturedImageEventBus.unsubscribe(&movieMaker);
     }
 }
-
diff --git a/src/lib/tst/orange-ball-detector-test.cpp b/src/lib/tst/orange-ball-detector-test.cpp
index ffbb2f1..b953457 100644
--- a/src/lib/tst/orange-ball-detector-test.cpp
+++ b/src/lib/tst/orange-ball-detector-test.cpp
@@ -46,7 +46,7 @@ SCENARIO("Can detect orange balls in an image") {
             THEN ( "Can find the orange") {
                 EventOrangeDetected e = receiver.getEvent();
                 REQUIRE(e.hasDetectedSomething() );
-                REQUIRE_THAT(e.getBallPosition().x, WithinAbs(435, 10));
+                REQUIRE_THAT(e.getBallPosition().x, WithinAbs(0.728, 0.01));
             }
         }
 
@@ -59,7 +59,7 @@ SCENARIO("Can detect orange balls in an image") {
             THEN ( "Can find the orange (2)") {
                 EventOrangeDetected e = receiver.getEvent();
                 REQUIRE(e.hasDetectedSomething());
-                REQUIRE_THAT(e.getBallPosition().x, WithinAbs(240, 10));
+                REQUIRE_THAT(e.getBallPosition().x, WithinAbs(0.401, 0.01));
             }
         }
 
@@ -72,7 +72,7 @@ SCENARIO("Can detect orange balls in an image") {
             THEN ( "Can find the ball") {
                 EventOrangeDetected e = receiver.getEvent();
                 REQUIRE(e.hasDetectedSomething());
-                REQUIRE_THAT(e.getBallPosition().x, WithinAbs(360, 10));
+                REQUIRE_THAT(e.getBallPosition().x, WithinAbs(0.599, 0.01));
             }
         }
 
@@ -85,7 +85,7 @@ SCENARIO("Can detect orange balls in an image") {
             THEN ( "Sadly, misses the orange") {
                 EventOrangeDetected e = receiver.getEvent();
                 REQUIRE(e.hasDetectedSomething());
-                REQUIRE_THAT(e.getBallPosition().x, WithinAbs(215, 10));
+                REQUIRE_THAT(e.getBallPosition().x, WithinAbs(0.355, 0.01));
             }
         }
 
@@ -99,7 +99,7 @@ SCENARIO("Can detect orange balls in an image") {
             THEN ( "Can find the ball") {
                 EventOrangeDetected e = receiver.getEvent();
                 REQUIRE(e.hasDetectedSomething());
-                REQUIRE_THAT( e.getBallPosition().x, WithinAbs(360, 10));
+                REQUIRE_THAT( e.getBallPosition().x, WithinAbs(0.613, 0.01));
             }
         }
         WHEN( "Shown with a broccoli") {
diff --git a/src/lib/tst/rate-meter-test.cpp b/src/lib/tst/rate-meter-test.cpp
new file mode 100644
index 0000000..fe54f3f
--- /dev/null
+++ b/src/lib/tst/rate-meter-test.cpp
@@ -0,0 +1,52 @@
+#include "rate-meter.hpp"
+
+#include "catch.hpp"
+
+void wait(int c) {
+    for (int n = 0; n < c; n++) {
+        for (int m = 0; m < 10000; m++);
+    }
+}
+
+SCENARIO("Measure rates") {
+    GIVEN( "An initialized rate meter") {
+        WHEN("Calling it once") {
+            RateMeter rateMeter;
+            wait(1000);
+            rateMeter.updateRate();
+            THEN("It measures rate between creation and update") {
+                REQUIRE(rateMeter.getRate() > 0);
+            }
+        }
+        WHEN("Calling it repeatedly") {
+            RateMeter rateMeter;
+            wait(1000);
+            rateMeter.updateRate();
+            wait(1000);
+            rateMeter.updateRate();
+            THEN("Measures rate between updates") {
+                REQUIRE(rateMeter.getRate() > 0);
+            }
+        }
+
+        WHEN("Calling at different frequencies") {
+            RateMeter rateMeter1, rateMeter2, rateMeter3;
+
+            for (int n = 0; n < 10; n++) {
+                wait(1000);
+                rateMeter1.updateRate();
+                if (n % 2 == 0) {
+                    rateMeter2.updateRate();
+                }
+                if (n % 3 == 0) {
+                    rateMeter3.updateRate();
+                }
+            }
+
+            THEN("Rates reflect frequency") {
+                REQUIRE(rateMeter1.getRate() > rateMeter2.getRate());
+                REQUIRE(rateMeter2.getRate() > rateMeter3.getRate());
+            }
+        }
+    }
+}
