From 211507d598b67e6e274275ab472d5e81ec1afcec Mon Sep 17 00:00:00 2001
From: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
Date: Wed, 22 Feb 2012 23:27:15 +0100
Subject: Factor event handling code out into events.c

Signed-off-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
---
 Makefile   |   4 +-
 events.c   | 175 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
 events.h   |  50 ++++++++++++++++++
 live.c     | 154 ++++++-----------------------------------------------
 snapshot.c | 153 +++++++----------------------------------------------
 5 files changed, 263 insertions(+), 273 deletions(-)
 create mode 100644 events.c
 create mode 100644 events.h

diff --git a/Makefile b/Makefile
index 849e367..cb7d846 100644
--- a/Makefile
+++ b/Makefile
@@ -6,8 +6,8 @@ CFLAGS	:= -O2 -W -Wall -I$(KDIR)/usr/include
 LDFLAGS	:= -Lisp
 LIBS	:= -lomap3isp -lrt
 
-OBJ_LIVE := live.o videoout.o
-OBJ_SNAP := snapshot.o
+OBJ_LIVE := live.o events.o videoout.o
+OBJ_SNAP := snapshot.o events.o
 
 %.o : %.c
 	$(CC) $(CFLAGS) -c -o $@ $<
diff --git a/events.c b/events.c
new file mode 100644
index 0000000..461e641
--- /dev/null
+++ b/events.c
@@ -0,0 +1,175 @@
+/*
+ * OMAP3 generic events handling
+ *
+ * Copyright (C) 2010-2012 Ideas on board SPRL
+ *
+ * Contact: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the Free
+ * Software Foundation; either version 2 of the License, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+ */
+
+#define _BSD_SOURCE
+#include <errno.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include <sys/select.h>
+
+#include "isp/list.h"
+#include "isp/omap3isp.h"
+#include "isp/tools.h"
+
+#include "events.h"
+
+#define SELECT_TIMEOUT		2000		/* in milliseconds */
+
+struct event_fd {
+	struct list_entry list;
+
+	int fd;
+	enum omap3_isp_event_type type;
+	void (*callback)(void *priv);
+	void *priv;
+};
+
+void events_watch_fd(struct events *events, int fd,
+		     enum omap3_isp_event_type type,
+		     void(*callback)(void *), void *priv)
+{
+	struct event_fd *event;
+
+	event = malloc(sizeof *event);
+	if (event == NULL)
+		return;
+
+	event->fd = fd;
+	event->type = type;
+	event->callback = callback;
+	event->priv = priv;
+
+	switch (event->type) {
+	case OMAP3_ISP_EVENT_READ:
+		FD_SET(fd, &events->rfds);
+		break;
+	case OMAP3_ISP_EVENT_WRITE:
+		FD_SET(fd, &events->wfds);
+		break;
+	}
+
+	events->maxfd = max(events->maxfd, fd);
+
+	list_append(&event->list, &events->events);
+}
+
+void events_unwatch_fd(struct events *events, int fd)
+{
+	struct event_fd *event = NULL;
+	struct event_fd *entry;
+	int maxfd = 0;
+
+	list_for_each_entry(entry, &events->events, list) {
+		if (entry->fd == fd)
+			event = entry;
+		else
+			maxfd = max(maxfd, entry->fd);
+	}
+
+	if (event == NULL)
+		return;
+
+	switch (event->type) {
+	case OMAP3_ISP_EVENT_READ:
+		FD_CLR(fd, &events->rfds);
+		break;
+	case OMAP3_ISP_EVENT_WRITE:
+		FD_CLR(fd, &events->wfds);
+		break;
+	}
+
+	events->maxfd = maxfd;
+
+	list_remove(&event->list);
+	free(event);
+}
+
+static void events_dispatch(struct events *events, const fd_set *rfds,
+			    const fd_set *wfds)
+{
+	struct event_fd *event;
+
+	list_for_each_entry(event, &events->events, list) {
+		if (event->type == OMAP3_ISP_EVENT_READ &&
+		    FD_ISSET(event->fd, rfds))
+			event->callback(event->priv);
+		if (event->type == OMAP3_ISP_EVENT_WRITE &&
+		    FD_ISSET(event->fd, wfds))
+			event->callback(event->priv);
+	}
+}
+
+bool events_loop(struct events *events)
+{
+	while (!events->done) {
+		struct timeval timeout;
+		fd_set rfds;
+		fd_set wfds;
+		int ret;
+
+		timeout.tv_sec = SELECT_TIMEOUT / 1000;
+		timeout.tv_usec = (SELECT_TIMEOUT % 1000) * 1000;
+		rfds = events->rfds;
+		wfds = events->wfds;
+
+		ret = select(events->maxfd + 1, &rfds, &wfds, NULL, &timeout);
+		if (ret < 0) {
+			/* EINTR means that a signal has been received, continue
+			 * to the next iteration in that case.
+			 */
+			if (errno == EINTR)
+				continue;
+
+			printf("error: select failed with %d\n", errno);
+			break;
+		}
+		if (ret == 0) {
+			/* select() should never time out as the ISP is supposed
+			 * to capture images continuously. A timeout is thus
+			 * considered as a fatal error.
+			 */
+			printf("error: select timeout\n");
+			break;
+		}
+
+		events_dispatch(events, &rfds, &wfds);
+	}
+
+	return !events->done;
+}
+
+void events_stop(struct events *events)
+{
+	events->done = true;
+}
+
+void events_init(struct events *events)
+{
+	memset(events, 0, sizeof *events);
+
+	FD_ZERO(&events->rfds);
+	FD_ZERO(&events->wfds);
+	events->maxfd = 0;
+	list_init(&events->events);
+}
diff --git a/events.h b/events.h
new file mode 100644
index 0000000..00a14bf
--- /dev/null
+++ b/events.h
@@ -0,0 +1,50 @@
+/*
+ * OMAP3 generic events handling
+ *
+ * Copyright (C) 2010-2012 Ideas on board SPRL
+ *
+ * Contact: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the Free
+ * Software Foundation; either version 2 of the License, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+ */
+
+#ifndef __EVENTS_H__
+#define __EVENTS_H__
+
+#include <stdbool.h>
+#include <sys/select.h>
+
+#include "isp/list.h"
+
+struct events {
+	struct list_entry events;
+	bool done;
+
+	int maxfd;
+	fd_set rfds;
+	fd_set wfds;
+};
+
+void events_watch_fd(struct events *events, int fd,
+		     enum omap3_isp_event_type type,
+		     void(*callback)(void *), void *priv);
+void events_unwatch_fd(struct events *events, int fd);
+
+bool events_loop(struct events *events);
+void events_stop(struct events *events);
+
+void events_init(struct events *events);
+
+#endif
diff --git a/live.c b/live.c
index 70e4db5..c4d5ffd 100644
--- a/live.c
+++ b/live.c
@@ -37,7 +37,6 @@
 
 #include <sys/ioctl.h>
 #include <sys/mman.h>
-#include <sys/select.h>
 #include <sys/stat.h>
 #include <sys/time.h>
 #include <sys/types.h>
@@ -51,11 +50,11 @@
 #include "isp/v4l2.h"
 #include "isp/v4l2-pool.h"
 
+#include "events.h"
 #include "videoout.h"
 
 #define MEDIA_DEVICE		"/dev/media0"
 #define VIDEOOUT_DEVICE		"/dev/video0"
-#define SELECT_TIMEOUT		2000		/* in milliseconds */
 
 static struct timespec fps_ts = { 0, 0 };
 static unsigned int fps_last = 0;
@@ -67,99 +66,21 @@ static unsigned int frame_skip = 0;
 static struct omap3_isp_device *isp = NULL;
 static struct videoout *vo = NULL;
 
-static bool done = false;
+static struct events events;
 
 /* -----------------------------------------------------------------------------
  * Events
  */
 
-struct event_fd {
-	struct list_entry list;
-
-	int fd;
-	bool write;
-	void (*callback)(void *priv);
-	void *priv;
-};
-
-static struct {
-	struct list_entry events;
-
-	int maxfd;
-	fd_set rfds;
-	fd_set wfds;
-} events;
-
-static void events_watch_fd(int fd, bool write, void(*callback)(void *), void *priv)
-{
-	struct event_fd *event;
-
-	event = malloc(sizeof *event);
-	if (event == NULL)
-		return;
-
-	event->fd = fd;
-	event->write = write;
-	event->callback = callback;
-	event->priv = priv;
-
-	if (write)
-		FD_SET(fd, &events.wfds);
-	else
-		FD_SET(fd, &events.rfds);
-
-	events.maxfd = max(events.maxfd, fd);
-
-	list_append(&event->list, &events.events);
-}
-
-static void events_unwatch_fd(int fd)
-{
-	struct event_fd *event = NULL;
-	struct event_fd *entry;
-	int maxfd = 0;
-
-	list_for_each_entry(entry, &events.events, list) {
-		if (entry->fd == fd)
-			event = entry;
-		else
-			maxfd = max(maxfd, entry->fd);
-	}
-
-	if (event == NULL)
-		return;
-
-	if (event->write)
-		FD_CLR(fd, &events.wfds);
-	else
-		FD_CLR(fd, &events.rfds);
-
-	events.maxfd = maxfd;
-
-	list_remove(&event->list);
-	free(event);
-}
-
-static void events_init(void)
+static void __events_watch_fd(int fd, enum omap3_isp_event_type type,
+			      void(*callback)(void *), void *priv)
 {
-	memset(&events, 0, sizeof events);
-
-	FD_ZERO(&events.rfds);
-	FD_ZERO(&events.wfds);
-	events.maxfd = 0;
-	list_init(&events.events);
+	events_watch_fd(&events, fd, type, callback, priv);
 }
 
-static void events_dispatch(const fd_set *rfds, const fd_set *wfds)
+static void __events_unwatch_fd(int fd)
 {
-	struct event_fd *event;
-
-	list_for_each_entry(event, &events.events, list) {
-		if (!event->write && FD_ISSET(event->fd, rfds))
-			event->callback(event->priv);
-		if (event->write && FD_ISSET(event->fd, wfds))
-			event->callback(event->priv);
-	}
+	events_unwatch_fd(&events, fd);
 }
 
 /* -----------------------------------------------------------------------------
@@ -210,17 +131,10 @@ static void viewfinder_process(struct omap3_isp_device *isp __attribute__((__unu
 		       strerror(-ret), ret);
 }
 
-
-static void events_watch_fd_isp(int fd, enum omap3_isp_event_type type,
-				void (*callback)(void *priv), void *priv)
-{
-	events_watch_fd(fd, type == OMAP3_ISP_EVENT_WRITE, callback, priv);
-}
-
 static struct omap3_isp_operations isp_ops = {
 	.viewfinder_ready = viewfinder_process,
-	.watch_fd = events_watch_fd_isp,
-	.unwatch_fd = events_unwatch_fd,
+	.watch_fd = __events_watch_fd,
+	.unwatch_fd = __events_unwatch_fd,
 };
 
 /* -----------------------------------------------------------------------------
@@ -247,12 +161,12 @@ static void video_out_process(void *priv __attribute__((__unused__)))
 
 static void events_watch_fd_vo(int fd)
 {
-	events_watch_fd(fd, true, video_out_process, NULL);
+	events_watch_fd(&events, fd, OMAP3_ISP_EVENT_WRITE, video_out_process, NULL);
 }
 
 static struct video_out_operations vo_ops = {
 	.watch_fd = events_watch_fd_vo,
-	.unwatch_fd = events_unwatch_fd,
+	.unwatch_fd = __events_unwatch_fd,
 };
 
 static const char *video_out_find(void)
@@ -386,10 +300,8 @@ done:
 
 static void sigint_handler(int signal __attribute__((__unused__)))
 {
-	/* Set the done flag to true when the user presses CTRL-C to interrupt
-	 * the main loop.
-	 */
-	done = true;
+	/* Stop the main loop when the user presses CTRL-C. */
+	events_stop(&events);
 }
 
 static void usage(const char *argv0)
@@ -439,7 +351,7 @@ int main(int argc __attribute__((__unused__)), char *argv[] __attribute__((__unu
 		}
 	}
 
-	events_init();
+	events_init(&events);
 
 	memset(&rect, 0, sizeof rect);
 	ret = fb_init(&rect);
@@ -514,41 +426,9 @@ int main(int argc __attribute__((__unused__)), char *argv[] __attribute__((__unu
 
 	clock_gettime(CLOCK_MONOTONIC, &start);
 
-	/* Main capture loop. Wait for a video buffer using select() and process
-	 * it.
-	 */
-	while (!done) {
-		struct timeval timeout;
-		fd_set rfds;
-		fd_set wfds;
-
-		timeout.tv_sec = SELECT_TIMEOUT / 1000;
-		timeout.tv_usec = (SELECT_TIMEOUT % 1000) * 1000;
-		rfds = events.rfds;
-		wfds = events.wfds;
-
-		ret = select(events.maxfd + 1, &rfds, &wfds, NULL, &timeout);
-		if (ret < 0) {
-			/* EINTR means that a signal has been received, continue
-			 * to the next iteration in that case.
-			 */
-			if (errno == EINTR)
-				continue;
-
-			printf("error: select failed with %d\n", errno);
-			goto cleanup;
-		}
-		if (ret == 0) {
-			/* select() should never time out as the ISP is supposed
-			 * to capture images continuously. A timeout is thus
-			 * considered as a fatal error.
-			 */
-			printf("error: select timeout\n");
-			goto cleanup;
-		}
-
-		events_dispatch(&rfds, &wfds);
-	}
+	/* Main capture loop. */
+	if (events_loop(&events))
+		goto cleanup;
 
 	clock_gettime(CLOCK_MONOTONIC, &end);
 
diff --git a/snapshot.c b/snapshot.c
index bc2b7da..da63b36 100644
--- a/snapshot.c
+++ b/snapshot.c
@@ -46,8 +46,9 @@
 #include "isp/v4l2.h"
 #include "isp/v4l2-pool.h"
 
+#include "events.h"
+
 #define MEDIA_DEVICE		"/dev/media0"
-#define SELECT_TIMEOUT		2000		/* in milliseconds */
 
 #define VIEWFINDER_WIDTH	1024
 #define VIEWFINDER_HEIGHT	768
@@ -55,115 +56,33 @@
 #define SNAPSHOT_HEIGHT		1536
 
 static unsigned int frame_count = 0;
-static bool done = false;
 
 static unsigned int snapshot_interval = 20;
 static struct timespec snapshot_time;
 
+static struct events events;
+
 /* -----------------------------------------------------------------------------
  * Events
  */
 
-struct event_fd {
-	struct list_entry list;
-
-	int fd;
-	enum omap3_isp_event_type type;
-	void (*callback)(void *priv);
-	void *priv;
-};
-
-static struct {
-	struct list_entry events;
-
-	int maxfd;
-	fd_set rfds;
-	fd_set wfds;
-} events;
-
-static void events_watch_fd(int fd, enum omap3_isp_event_type type,
-			    void(*callback)(void *), void *priv)
-{
-	struct event_fd *event;
-
-	event = malloc(sizeof *event);
-	if (event == NULL)
-		return;
-
-	event->fd = fd;
-	event->type = type;
-	event->callback = callback;
-	event->priv = priv;
-
-	if (event->type == OMAP3_ISP_EVENT_READ)
-		FD_SET(fd, &events.rfds);
-	else
-		FD_SET(fd, &events.wfds);
-
-	events.maxfd = max(events.maxfd, fd);
-
-	list_append(&event->list, &events.events);
-}
-
-static void events_unwatch_fd(int fd)
-{
-	struct event_fd *event = NULL;
-	struct event_fd *entry;
-	int maxfd = 0;
-
-	list_for_each_entry(entry, &events.events, list) {
-		if (entry->fd == fd)
-			event = entry;
-		else
-			maxfd = max(maxfd, entry->fd);
-	}
-
-	if (event == NULL)
-		return;
-
-	if (event->type == OMAP3_ISP_EVENT_READ)
-		FD_CLR(fd, &events.rfds);
-	else
-		FD_CLR(fd, &events.wfds);
-
-	events.maxfd = maxfd;
-
-	list_remove(&event->list);
-	free(event);
-}
-
-static void events_init(void)
+static void __events_watch_fd(int fd, enum omap3_isp_event_type type,
+			      void(*callback)(void *), void *priv)
 {
-	memset(&events, 0, sizeof events);
-
-	FD_ZERO(&events.rfds);
-	FD_ZERO(&events.wfds);
-	events.maxfd = 0;
-	list_init(&events.events);
+	events_watch_fd(&events, fd, type, callback, priv);
 }
 
-static void events_dispatch(const fd_set *rfds, const fd_set *wfds)
+static void __events_unwatch_fd(int fd)
 {
-	struct event_fd *event;
-
-	list_for_each_entry(event, &events.events, list) {
-		if (event->type == OMAP3_ISP_EVENT_READ &&
-		    FD_ISSET(event->fd, rfds))
-			event->callback(event->priv);
-		if (event->type == OMAP3_ISP_EVENT_WRITE &&
-		    FD_ISSET(event->fd, wfds))
-			event->callback(event->priv);
-	}
+	events_unwatch_fd(&events, fd);
 }
 
 /* -------------------------------------------------------------------------- */
 
 static void sigint_handler(int signal __attribute__((__unused__)))
 {
-	/* Set the done flag to true when the user presses CTRL-C to interrupt
-	 * the main loop.
-	 */
-	done = true;
+	/* Stop the main loop when the user presses CTRL-C. */
+	events_stop(&events);
 }
 
 static void snapshot_process(struct omap3_isp_device *isp,
@@ -284,7 +203,6 @@ int main(int argc __attribute__((__unused__)), char *argv[] __attribute__((__unu
 	struct omap3_isp_device *isp = NULL;
 	struct omap3_isp_operations ops;
 	struct timespec start, end;
-	unsigned int count = 0;
 	int exit_code = EXIT_FAILURE;
 	float fps;
 	int ret;
@@ -316,7 +234,7 @@ int main(int argc __attribute__((__unused__)), char *argv[] __attribute__((__unu
 		}
 	}
 
-	events_init();
+	events_init(&events);
 
 	/* Register a signal handler for SIGINT, received when the user presses
 	 * CTRL-C. This will allow the main loop to be interrupted, and resources
@@ -328,8 +246,8 @@ int main(int argc __attribute__((__unused__)), char *argv[] __attribute__((__unu
 	memset(&ops, 0, sizeof ops);
 	ops.viewfinder_ready = viewfinder_process;
 	ops.snapshot_ready = snapshot_process;
-	ops.watch_fd = events_watch_fd;
-	ops.unwatch_fd = events_unwatch_fd;
+	ops.watch_fd = __events_watch_fd;
+	ops.unwatch_fd = __events_unwatch_fd;
 
 	isp = omap3_isp_open(MEDIA_DEVICE, &ops);
 	if (isp == NULL) {
@@ -391,42 +309,9 @@ int main(int argc __attribute__((__unused__)), char *argv[] __attribute__((__unu
 
 	clock_gettime(CLOCK_MONOTONIC, &start);
 
-	/* Main capture loop. Wait for a video buffer using select() and process
-	 * it.
-	 */
-	while (!done) {
-		struct timeval timeout;
-		fd_set rfds;
-		fd_set wfds;
-
-		timeout.tv_sec = SELECT_TIMEOUT / 1000;
-		timeout.tv_usec = (SELECT_TIMEOUT % 1000) * 1000;
-		rfds = events.rfds;
-		wfds = events.wfds;
-
-		ret = select(events.maxfd + 1, &rfds, &wfds, NULL, &timeout);
-		if (ret < 0) {
-			/* EINTR means that a signal has been received, continue
-			 * to the next iteration in that case.
-			 */
-			if (errno == EINTR)
-				continue;
-
-			printf("error: select failed with %d\n", errno);
-			goto cleanup;
-		}
-		if (ret == 0) {
-			/* select() should never time out as the ISP is supposed
-			 * to capture images continuously. A timeout is thus
-			 * considered as a fatal error.
-			 */
-			printf("error: select timeout\n");
-			goto cleanup;
-		}
-
-		events_dispatch(&rfds, &wfds);
-		count++;
-	}
+	/* Main capture loop. */
+	if (events_loop(&events))
+		goto cleanup;
 
 	clock_gettime(CLOCK_MONOTONIC, &end);
 
@@ -441,9 +326,9 @@ int main(int argc __attribute__((__unused__)), char *argv[] __attribute__((__unu
 		end.tv_nsec += 1000000000;
 	}
 
-	fps = count / (end.tv_sec + end.tv_nsec / 1000000000.0);
+	fps = frame_count / (end.tv_sec + end.tv_nsec / 1000000000.0);
 
-	printf("%u images processed in %lu.%06lu seconds (%f fps)\n", count,
+	printf("%u images processed in %lu.%06lu seconds (%f fps)\n", frame_count,
 	       end.tv_sec, end.tv_nsec / 1000, fps);
 
 	exit_code = EXIT_SUCCESS;
-- 
cgit v1.2.3