+ shared_ptr<Image> image(new Image{unsigned(frame->width), unsigned(frame->height), move(image_data), last_modified});
+ return image;
+}
+
+// Fire up a thread to update the image every second.
+// We could do inotify, but this is good enough for now.
+void ImageInput::update_thread_func(const std::string &filename, const std::string &pathname, const timespec &first_modified)
+{
+ char thread_name[16];
+ snprintf(thread_name, sizeof(thread_name), "Update_%s", filename.c_str());
+ pthread_setname_np(pthread_self(), thread_name);
+
+ timespec last_modified = first_modified;
+ struct stat buf;
+ for ( ;; ) {
+ {
+ unique_lock<mutex> lock(threads_should_quit_mu);
+ threads_should_quit_modified.wait_for(lock, chrono::seconds(1), []() { return threads_should_quit; });
+ }
+
+ if (threads_should_quit) {
+ return;
+ }
+
+ if (stat(pathname.c_str(), &buf) != 0) {
+ fprintf(stderr, "%s: Couldn't check for new version, leaving the old in place.\n", pathname.c_str());
+ continue;
+ }
+ if (buf.st_mtim.tv_sec == last_modified.tv_sec &&
+ buf.st_mtim.tv_nsec == last_modified.tv_nsec) {
+ // Not changed.
+ continue;
+ }
+ shared_ptr<const Image> image = load_image_raw(pathname);
+ if (image == nullptr) {
+ fprintf(stderr, "Couldn't load image, leaving the old in place.\n");
+ continue;
+ }
+ fprintf(stderr, "Loaded new version of %s from disk.\n", pathname.c_str());
+ unique_lock<mutex> lock(all_images_lock);
+ all_images[pathname] = image;
+ last_modified = image->last_modified;
+ }
+}
+
+void ImageInput::shutdown_updaters()
+{
+ {
+ unique_lock<mutex> lock(threads_should_quit_mu);
+ threads_should_quit = true;
+ threads_should_quit_modified.notify_all();
+ }
+ for (auto &it : update_threads) {
+ it.second.join();
+ }