Rest of 2016 vision code.

Vision2016Debug:
  - Added live debug (debug_reciever);
  - Added file replay (blob_stream_replay).
  - Add gtk event code.
  - Updated code and fixed compile errors after rebase.
  - Added useful tools for reference. As per Austins directions.

Change-Id: I7c5e7df01eb09057178bcb99dd3e302ca274ac76
diff --git a/aos/vision/events/BUILD b/aos/vision/events/BUILD
index e003dc9..2b5b9e7 100644
--- a/aos/vision/events/BUILD
+++ b/aos/vision/events/BUILD
@@ -1,3 +1,4 @@
+load('/tools/build_rules/gtk_dependent', 'gtk_dependent_cc_binary', 'gtk_dependent_cc_library')
 package(default_visibility = ["//visibility:public"])
 
 cc_library(
@@ -56,3 +57,12 @@
     '//aos/testing:googletest',
   ],
 )
+
+gtk_dependent_cc_library(
+  name = "gtk_event",
+  srcs = ["gtk_event.cc"],
+  deps = [
+    ":epoll_events",
+    '@usr_repo//:gtk+-3.0',
+  ],
+)
diff --git a/aos/vision/events/epoll_events.cc b/aos/vision/events/epoll_events.cc
index f191259..e4f789f 100644
--- a/aos/vision/events/epoll_events.cc
+++ b/aos/vision/events/epoll_events.cc
@@ -42,17 +42,10 @@
       }
       event->ReadEvent();
     }
-
-    for (EpollWatcher *watcher : watchers_) {
-      watcher->Wake();
-    }
   }
 }
 
 void EpollLoop::AddWait(EpollWait *wait) { waits_.push_back(wait); }
-void EpollLoop::AddWatcher(EpollWatcher *watcher) {
-  watchers_.push_back(watcher);
-}
 
 // Calculates the new timeout value to pass to epoll_wait.
 int EpollLoop::CalculateTimeout() {
diff --git a/aos/vision/events/epoll_events.h b/aos/vision/events/epoll_events.h
index d7574f9..ee288c4 100644
--- a/aos/vision/events/epoll_events.h
+++ b/aos/vision/events/epoll_events.h
@@ -17,6 +17,7 @@
 // Performs an asychronous wait using an EpollLoop.
 //
 // Note: this does not have very high resolution (sub-millisecond).
+// TODO(parker): This is mostly broken.
 class EpollWait {
  public:
   virtual ~EpollWait() {}
@@ -37,10 +38,15 @@
   int Recalculate(const monotonic_clock::time_point now) {
     if (time_ < monotonic_clock::epoch()) return -1;
     if (time_ <= now) {
-      Done();
       time_ = monotonic_clock::time_point(::std::chrono::seconds(-1));
-      return -1;
+      Done();
     }
+    // Duplicate above to allow Done to change itself.
+    if (time_ < monotonic_clock::epoch()) return -1;
+    if (time_ <= now) {
+      return -1;// Recalculate(now);
+    }
+
     if (time_ - now > ::std::chrono::milliseconds(INT_MAX)) {
       return INT_MAX;
     } else {
@@ -75,17 +81,6 @@
   EpollLoop *loop_ = nullptr;
 };
 
-// Provides a way for code to be notified every time after events are handled by
-// an EpollLoop. This is mainly a hack for the GTK integration and testing;
-// think very carefully before using it anywhere else.
-class EpollWatcher {
- public:
-  virtual ~EpollWatcher() {}
-
-  // Called after events have been processed each time the event loop wakes up.
-  virtual void Wake() = 0;
-};
-
 // A file descriptor based event loop implemented with epoll.
 class EpollLoop {
  public:
@@ -95,7 +90,6 @@
   // None of these take ownership of the passed-in objects.
   void AddWait(EpollWait *wait);
   void Add(EpollEvent *event);
-  void AddWatcher(EpollWatcher *watcher);
 
   // Delete event. Note that there are caveats here as this is
   // not idiot proof.
@@ -111,6 +105,10 @@
   // Loops forever, handling events.
   void Run();
 
+  // Fuses with gtk_main().
+  // Note that the dep for this is separate: //aos/vision/events:gtk_event
+  void RunWithGtkMain();
+
  private:
   int epoll_fd() { return epoll_fd_.get(); }
 
@@ -118,7 +116,6 @@
 
   ::aos::ScopedFD epoll_fd_;
   ::std::vector<EpollWait *> waits_;
-  ::std::vector<EpollWatcher *> watchers_;
 };
 
 }  // namespace events
diff --git a/aos/vision/events/gtk_event.cc b/aos/vision/events/gtk_event.cc
new file mode 100644
index 0000000..e8b43aa
--- /dev/null
+++ b/aos/vision/events/gtk_event.cc
@@ -0,0 +1,68 @@
+#include <gtk/gtk.h>
+#include <gdk/gdk.h>
+#include <thread>
+#include <sys/epoll.h>
+#include <mutex>
+#include <condition_variable>
+
+#include "aos/vision/events/epoll_events.h"
+
+namespace aos {
+namespace events {
+
+void EpollLoop::RunWithGtkMain() {
+  int timeout;
+  static constexpr size_t kNumberOfEvents = 64;
+  epoll_event events[kNumberOfEvents];
+  int number_events = 0;
+
+  std::mutex m;
+  std::condition_variable cv;
+  bool all_events_handled = false;
+  auto handle_cb = [&]() {
+    {
+      std::unique_lock<std::mutex> lk(m);
+
+      for (int i = 0; i < number_events; i++) {
+        EpollEvent *event = static_cast<EpollEvent *>(events[i].data.ptr);
+        if ((events[i].events & ~(EPOLLIN | EPOLLPRI)) != 0) {
+          LOG(FATAL, "unexpected epoll events set in %x on %d\n",
+              events[i].events, event->fd());
+        }
+        event->ReadEvent();
+      }
+      timeout = CalculateTimeout();
+
+      all_events_handled = true;
+    }
+    cv.notify_one();
+  };
+  handle_cb();
+  using HandleCBType = decltype(handle_cb);
+
+  std::thread t([&]() {
+    std::unique_lock<std::mutex> lk(m);
+    while (true) {
+      cv.wait(lk, [&all_events_handled]{return all_events_handled;});
+      // Wait for handle_cb to be done.
+      number_events = PCHECK(epoll_wait(epoll_fd(), events, kNumberOfEvents, timeout));
+      all_events_handled = false;
+      // Trigger handle_cb on main_thread to avoid concurrency.
+      gdk_threads_add_idle(+[](gpointer user_data) -> gboolean {
+        auto& handle_cb = *reinterpret_cast<HandleCBType*>(user_data);
+        handle_cb();
+        return G_SOURCE_REMOVE;
+      }, &handle_cb);
+    }
+  });
+  gtk_main();
+
+  // TODO(parker): Allow concurrent proxy onto the normal thread just like Gtk
+  // in order to allow event loop fusion, and make event addition thread-safe.
+
+  // Avoid stack destructors (explicitly shutting down of the thread.)
+  exit(EXIT_SUCCESS);
+}
+
+}  // namespace events
+}  // namespace aos
diff --git a/aos/vision/events/tcp_client.h b/aos/vision/events/tcp_client.h
index e7b80a6..7ce01f7 100644
--- a/aos/vision/events/tcp_client.h
+++ b/aos/vision/events/tcp_client.h
@@ -1,5 +1,5 @@
-#ifndef _AOS_VISION_DEBUG_TCP_SERVER_H_
-#define _AOS_VISION_DEBUG_TCP_SERVER_H_
+#ifndef _AOS_VISION_DEBUG_TCP_CLIENT_H_
+#define _AOS_VISION_DEBUG_TCP_CLIENT_H_
 
 #include "aos/vision/events/epoll_events.h"
 
@@ -19,4 +19,4 @@
 }  // namespace events
 }  // namespace aos
 
-#endif  // _AOS_VISION_DEBUG_TCP_SERVER_H_
+#endif  // _AOS_VISION_DEBUG_TCP_CLIENT_H_