aboutsummaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorMauro Carvalho Chehab <mchehab+samsung@kernel.org>2018-09-21 06:57:52 -0300
committerMauro Carvalho Chehab <mchehab+samsung@kernel.org>2018-09-21 06:57:52 -0300
commitc17f7baf89a3ef65c4eb866adc1df65729ac548b (patch)
treea22c96cdc1ee5507f6bffb9aa9a2a0558a76f92c /src
parentf85679e6c08c5ed1c8bee595bb15805d1e9ec081 (diff)
Move the select device dialog logit to callbacks.c
As we intend to be able to select another device anytime, via a callback, move the logic associated with device selection to the callbacks.c. As a side effect, it makes the main.c cleaner. Signed-off-by: Mauro Carvalho Chehab <mchehab+samsung@kernel.org>
Diffstat (limited to 'src')
-rw-r--r--src/callbacks.c236
-rw-r--r--src/callbacks.h11
-rw-r--r--src/main.c243
3 files changed, 256 insertions, 234 deletions
diff --git a/src/callbacks.c b/src/callbacks.c
index 703d010..15fd1ce 100644
--- a/src/callbacks.c
+++ b/src/callbacks.c
@@ -2,10 +2,14 @@
#include "interface.h"
#include "support.h"
#include "filter.h"
+
+#include <assert.h>
+#include <ftw.h>
#include <glib/gi18n.h>
#include <config.h>
#include <pthread.h>
#include <libv4l2.h>
+#include <sys/sysmacros.h>
#define GPL_LICENSE \
"GPL version 2.\n\n" \
@@ -769,3 +773,235 @@ void wb_change(GtkScale *sc1, cam_t *cam)
cam->whiteness = 256 * (int)gtk_range_get_value((GtkRange *) sc1);
v4l2_set_control(cam->dev, V4L2_CID_WHITENESS, cam->whiteness);
}
+
+/*
+ * Video device selection
+ */
+
+unsigned int n_devices = 0, n_valid_devices = 0;
+struct devnodes *devices = NULL;
+
+static int handle_video_devs(const char *file,
+ const struct stat *st,
+ int flag)
+{
+ int dev_minor, first_device = -1, fd;
+ unsigned int i;
+ struct v4l2_capability vid_cap = { 0 };
+
+
+ /* Discard devices that can't be a videodev */
+ if (!S_ISCHR(st->st_mode) || major(st->st_rdev) != 81)
+ return 0;
+
+ dev_minor = minor(st->st_rdev);
+
+ /* check if it is an already existing device */
+ if (devices) {
+ for (i = 0; i < n_devices; i++) {
+ if (dev_minor == devices[i].minor) {
+ first_device = i;
+ break;
+ }
+ }
+ }
+
+ devices = realloc(devices, (n_devices + 1) * sizeof(struct devnodes));
+ if (!devices) {
+ char *msg = g_strdup_printf(_("Can't allocate memory to store devices"));
+ error_dialog(msg);
+ g_free(msg);
+ exit(0);
+ }
+ memset(&devices[n_devices], 0, sizeof(struct devnodes));
+
+ if (first_device < 0) {
+ fd = v4l2_open(file, O_RDWR);
+ if (fd < 0) {
+ devices[n_devices].is_valid = FALSE;
+ } else {
+ if (v4l2_ioctl(fd, VIDIOC_QUERYCAP, &vid_cap) == -1) {
+ devices[n_devices].is_valid = FALSE;
+ } else if (!(vid_cap.device_caps & V4L2_CAP_VIDEO_CAPTURE)) {
+ devices[n_devices].is_valid = FALSE;
+ } else {
+ n_valid_devices++;
+ devices[n_devices].is_valid = TRUE;
+ }
+ }
+
+ v4l2_close(fd);
+ } else {
+ devices[n_devices].is_valid = devices[first_device].is_valid;
+ }
+
+ devices[n_devices].fname = g_strdup(file);
+ devices[n_devices].minor = dev_minor;
+ n_devices++;
+
+ return(0);
+}
+
+/*
+ * Sort order:
+ *
+ * - Valid devices comes first
+ * - Lowest minors comes first
+ *
+ * For devnode names, it sorts on this order:
+ * - custom udev given names
+ * - /dev/v4l/by-id/
+ * - /dev/v4l/by-path/
+ * - /dev/video
+ * - /dev/char/
+ *
+ * - Device name is sorted alphabetically if follows same pattern
+ */
+static int sort_devices(const void *__a, const void *__b)
+{
+ const struct devnodes *a = __a;
+ const struct devnodes *b = __b;
+ int val_a, val_b;
+
+ if (a->is_valid != b->is_valid)
+ return !a->is_valid - !b->is_valid;
+
+ if (a->minor != b->minor)
+ return a->minor - b->minor;
+
+ /* Ensure that /dev/video* devices will stay at the top */
+
+ if (strstr(a->fname, "by-id"))
+ val_a = 1;
+ if (strstr(a->fname, "by-path"))
+ val_a = 2;
+ else if (strstr(a->fname, "/dev/video"))
+ val_a = 3;
+ else if (strstr(a->fname, "char"))
+ val_a = 4;
+ else /* Customized names comes first */
+ val_a = 0;
+
+ if (strstr(b->fname, "by-id"))
+ val_b = 1;
+ if (strstr(b->fname, "by-path"))
+ val_b = 2;
+ else if (strstr(b->fname, "/dev/video"))
+ val_b = 3;
+ else if (strstr(b->fname, "char"))
+ val_b = 4;
+ else /* Customized names comes first */
+ val_b = 0;
+
+ if (val_a != val_b)
+ return val_a - val_b;
+
+ /* Finally, just use alphabetic order */
+ return strcmp(a->fname, b->fname);
+}
+
+static void videodev_response(GtkDialog *dialog,
+ cam_t *cam)
+{
+ GtkWidget *widget;
+
+ widget = GTK_WIDGET(gtk_builder_get_object(cam->xml, "videodev_window"));
+ gtk_widget_hide(widget);
+}
+
+void retrieve_video_dev(cam_t *cam)
+{
+ int last_minor = -1;
+ unsigned int i;
+ GtkWidget *widget;
+
+ /* This function is not meant to be called more than once */
+ assert (n_devices == 0);
+
+ /* Get all video devices */
+ if (ftw("/dev", handle_video_devs, 4) || !n_devices) {
+ char *msg = g_strdup_printf(_("Didn't find any camera"));
+ error_dialog(msg);
+ g_free(msg);
+ exit(0);
+ }
+ qsort(devices, n_devices, sizeof(struct devnodes), sort_devices);
+
+ if (cam->debug)
+ for (i = 0; i < n_devices; i++)
+ printf("Device[%d]: %s (%s)\n", i, devices[i].fname,
+ devices[i].is_valid ? "OK" : "NOK");
+
+ /* While we have Gtk 2 support, should be aligned with select_video_dev() */
+ widget = GTK_WIDGET(gtk_builder_get_object(cam->xml, "videodev_combo"));
+ for (i = 0; i < n_devices; i++) {
+ if (devices[i].is_valid) {
+ if (devices[i].minor == last_minor)
+ continue;
+ gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(widget),
+ devices[i].fname);
+ last_minor = devices[i].minor;
+ }
+ }
+
+ widget = GTK_WIDGET(gtk_builder_get_object(cam->xml, "videodev_ok"));
+ g_signal_connect(G_OBJECT(widget), "clicked",
+ G_CALLBACK(videodev_response), cam);
+}
+
+int select_video_dev(cam_t *cam)
+{
+ GtkWidget *window, *widget;
+ int ret;
+#if GTK_MAJOR_VERSION < 3
+ unsigned int i;
+ int index, last_minor = -1, p = 0;
+#endif
+
+ /* Only ask if there are multiple cameras */
+ if (n_valid_devices == 1) {
+ cam->video_dev = devices[0].fname;
+ return 0;
+ }
+
+ /* There are multiple devices. Ask the user */
+
+ window = GTK_WIDGET(gtk_builder_get_object(cam->xml, "videodev_window"));
+ widget = GTK_WIDGET(gtk_builder_get_object(cam->xml, "videodev_combo"));
+
+ gtk_combo_box_set_active(GTK_COMBO_BOX(widget), 0);
+
+ gtk_widget_show(window);
+
+ ret = gtk_dialog_run(GTK_DIALOG(window));
+
+#if GTK_MAJOR_VERSION >= 3
+ cam->video_dev = gtk_combo_box_text_get_active_text(GTK_COMBO_BOX_TEXT(widget));
+#else
+ /*
+ * For whatever weird reason, gtk_combo_box_text_get_active_text()
+ * is not work with Gtk 2.24. We might implement a map, but, as we'll
+ * probably drop support for it in the future, better to use the more
+ * optimized way for Gtk 3 and Gtk 4.
+ */
+
+ index = gtk_combo_box_get_active(GTK_COMBO_BOX(widget));
+
+ /* Should be aligned with the similar logic at retrieve_video_dev() */
+ for (i = 0; i < n_devices; i++) {
+ if (devices[i].is_valid) {
+ if (devices[i].minor == last_minor)
+ continue;
+ if (p == index)
+ break;
+ last_minor = devices[i].minor;
+ p++;
+ }
+ }
+ if (i < n_devices)
+ cam->video_dev = devices[i].fname;
+#endif
+
+ gtk_widget_hide(window);
+ return ret;
+}
diff --git a/src/callbacks.h b/src/callbacks.h
index f85e9ac..1ea424f 100644
--- a/src/callbacks.h
+++ b/src/callbacks.h
@@ -4,6 +4,15 @@
#include "v4l.h"
#include "fileio.h"
+struct devnodes {
+ char *fname;
+ int minor;
+ gboolean is_valid;
+};
+
+extern unsigned int n_devices, n_valid_devices;
+extern struct devnodes *devices;
+
G_BEGIN_DECLS
void on_change_size_activate(GtkWidget * widget, cam_t *cam);
@@ -62,6 +71,8 @@ void wb_change(GtkScale *, cam_t *);
gboolean on_drawingarea_expose_event(GtkWidget *, GdkEventExpose *,
cam_t *);
void set_image_scale(cam_t *cam);
+void retrieve_video_dev(cam_t *cam);
+int select_video_dev(cam_t *cam);
G_END_DECLS
diff --git a/src/main.c b/src/main.c
index d61e7e9..02ce378 100644
--- a/src/main.c
+++ b/src/main.c
@@ -7,13 +7,11 @@
#include "support.h"
#include <config.h>
-#include <ftw.h>
#include <gdk/gdkx.h>
#include <glib/gi18n.h>
#include <locale.h>
#include <libv4l2.h>
#include <stdlib.h>
-#include <sys/sysmacros.h>
static int ver = 0, max = 0, min;
static int half = 0, use_read = 0, debug = 0;
@@ -100,201 +98,6 @@ static void close_app(GtkWidget* widget, cam_t *cam)
#endif
}
-struct devnodes {
- char *fname;
- int minor;
- gboolean is_valid;
-};
-
-static unsigned int n_devices = 0, n_valid_devices = 0;
-static struct devnodes *devices = NULL;
-
-static int retrieve_video_devs(const char *file,
- const struct stat *st,
- int flag)
-{
- int dev_minor, first_device = -1, fd;
- unsigned int i;
- struct v4l2_capability vid_cap = { 0 };
-
-
- /* Discard devices that can't be a videodev */
- if (!S_ISCHR(st->st_mode) || major(st->st_rdev) != 81)
- return 0;
-
- dev_minor = minor(st->st_rdev);
-
- /* check if it is an already existing device */
- if (devices) {
- for (i = 0; i < n_devices; i++) {
- if (dev_minor == devices[i].minor) {
- first_device = i;
- break;
- }
- }
- }
-
- devices = realloc(devices, (n_devices + 1) * sizeof(struct devnodes));
- if (!devices) {
- char *msg = g_strdup_printf(_("Can't allocate memory to store devices"));
- error_dialog(msg);
- g_free(msg);
- exit(0);
- }
- memset(&devices[n_devices], 0, sizeof(struct devnodes));
-
- if (first_device < 0) {
- fd = v4l2_open(file, O_RDWR);
- if (fd < 0) {
- devices[n_devices].is_valid = False;
- } else {
- if (v4l2_ioctl(fd, VIDIOC_QUERYCAP, &vid_cap) == -1) {
- devices[n_devices].is_valid = False;
- } else if (!(vid_cap.device_caps & V4L2_CAP_VIDEO_CAPTURE)) {
- devices[n_devices].is_valid = False;
- } else {
- n_valid_devices++;
- devices[n_devices].is_valid = True;
- }
- }
-
- v4l2_close(fd);
- } else {
- devices[n_devices].is_valid = devices[first_device].is_valid;
- }
-
- devices[n_devices].fname = g_strdup(file);
- devices[n_devices].minor = dev_minor;
- n_devices++;
-
- return(0);
-}
-
-/*
- * Sort order:
- *
- * - Valid devices comes first
- * - Lowest minors comes first
- *
- * For devnode names, it sorts on this order:
- * - custom udev given names
- * - /dev/v4l/by-id/
- * - /dev/v4l/by-path/
- * - /dev/video
- * - /dev/char/
- *
- * - Device name is sorted alphabetically if follows same pattern
- */
-static int sort_devices(const void *__a, const void *__b)
-{
- const struct devnodes *a = __a;
- const struct devnodes *b = __b;
- int val_a, val_b;
-
- if (a->is_valid != b->is_valid)
- return !a->is_valid - !b->is_valid;
-
- if (a->minor != b->minor)
- return a->minor - b->minor;
-
- /* Ensure that /dev/video* devices will stay at the top */
-
- if (strstr(a->fname, "by-id"))
- val_a = 1;
- if (strstr(a->fname, "by-path"))
- val_a = 2;
- else if (strstr(a->fname, "/dev/video"))
- val_a = 3;
- else if (strstr(a->fname, "char"))
- val_a = 4;
- else /* Customized names comes first */
- val_a = 0;
-
- if (strstr(b->fname, "by-id"))
- val_b = 1;
- if (strstr(b->fname, "by-path"))
- val_b = 2;
- else if (strstr(b->fname, "/dev/video"))
- val_b = 3;
- else if (strstr(b->fname, "char"))
- val_b = 4;
- else /* Customized names comes first */
- val_b = 0;
-
- if (val_a != val_b)
- return val_a - val_b;
-
- /* Finally, just use alphabetic order */
- return strcmp(a->fname, b->fname);
-}
-
-static void videodev_response(GtkDialog *dialog,
- cam_t *cam)
-{
- GtkWidget *widget;
-
- widget = GTK_WIDGET(gtk_builder_get_object(cam->xml, "videodev_window"));
- gtk_widget_hide(widget);
-}
-
-static int select_video_dev(cam_t *cam)
-{
- GtkWidget *window, *widget;
- int ret;
-#if GTK_MAJOR_VERSION < 3
- unsigned int i;
- int index, last_minor = -1, p = 0;
-#endif
-
- /* Only ask if there are multiple cameras */
- if (n_valid_devices == 1) {
- cam->video_dev = devices[0].fname;
- return 0;
- }
-
- /* There are multiple devices. Ask the user */
-
- window = GTK_WIDGET(gtk_builder_get_object(cam->xml, "videodev_window"));
- widget = GTK_WIDGET(gtk_builder_get_object(cam->xml, "videodev_combo"));
-
- gtk_combo_box_set_active(GTK_COMBO_BOX(widget), 0);
-
- gtk_widget_show(window);
-
- ret = gtk_dialog_run(GTK_DIALOG(window));
-
-#if GTK_MAJOR_VERSION >= 3
- cam->video_dev = gtk_combo_box_text_get_active_text(GTK_COMBO_BOX_TEXT(widget));
-#else
- /*
- * For whatever weird reason, gtk_combo_box_text_get_active_text()
- * is not work with Gtk 2.24. We might implement a map, but, as we'll
- * probably drop support for it in the future, better to use the more
- * optimized way for Gtk 3 and Gtk 4.
- */
-
- index = gtk_combo_box_get_active(GTK_COMBO_BOX(widget));
- printf("index = %d\n", index);
-
- /* Should be aligned with the similar logic at activate() */
- for (i = 0; i < n_devices; i++) {
- if (devices[i].is_valid) {
- if (devices[i].minor == last_minor)
- continue;
- if (p == index)
- break;
- last_minor = devices[i].minor;
- p++;
- }
- }
- if (i < n_devices)
- cam->video_dev = devices[i].fname;
-#endif
-
- gtk_widget_hide(window);
- return ret;
-}
-
static cam_t cam_object = { 0 };
#if GTK_MAJOR_VERSION < 3
@@ -306,7 +109,6 @@ static void activate(GtkApplication *app)
cam_t *cam = &cam_object;
GtkWidget *widget, *window;
unsigned int bufsize, i;
- int last_minor = -1;
/* set some default values */
cam->frame_number = 0;
@@ -346,19 +148,17 @@ static void activate(GtkApplication *app)
printf("Forcing read mode\n");
cam->read = TRUE;
}
- /* Get all video devices */
- if (ftw("/dev", retrieve_video_devs, 4) || !n_devices) {
- char *msg = g_strdup_printf(_("Didn't find any camera"));
- error_dialog(msg);
- g_free(msg);
- exit(0);
+
+ cam->xml = gtk_builder_new();
+
+ if (!gtk_builder_add_from_file(cam->xml,
+ PACKAGE_DATA_DIR "/camorama/" CAMORAMA_UI,
+ NULL)) {
+ error_dialog(_("Couldn't load builder file"));
+ exit(1);
}
- qsort(devices, n_devices, sizeof(struct devnodes), sort_devices);
- if (cam->debug)
- for (i = 0; i < n_devices; i++)
- printf("Device[%d]: %s (%s)\n", i, devices[i].fname,
- devices[i].is_valid ? "OK" : "NOK");
+ retrieve_video_dev(cam);
cam->gc = g_settings_new(CAM_SETTINGS_SCHEMA);
@@ -373,31 +173,6 @@ static void activate(GtkApplication *app)
cam->video_dev = g_strdup(video_dev);
}
- cam->xml = gtk_builder_new();
-
- if (!gtk_builder_add_from_file(cam->xml,
- PACKAGE_DATA_DIR "/camorama/" CAMORAMA_UI,
- NULL)) {
- error_dialog(_("Couldn't load builder file"));
- exit(1);
- }
-
- widget = GTK_WIDGET(gtk_builder_get_object(cam->xml, "videodev_ok"));
- g_signal_connect(G_OBJECT(widget), "clicked",
- G_CALLBACK(videodev_response), cam);
-
- /* While we have Gtk 2 support, should be aligned with select_video_dev() */
- widget = GTK_WIDGET(gtk_builder_get_object(cam->xml, "videodev_combo"));
- for (i = 0; i < n_devices; i++) {
- if (devices[i].is_valid) {
- if (devices[i].minor == last_minor)
- continue;
- gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(widget),
- devices[i].fname);
- last_minor = devices[i].minor;
- }
- }
-
if (cam->video_dev) {
for (i = 0; i < n_devices; i++)
if (!strcmp(cam->video_dev, devices[i].fname) && devices[i].is_valid)

Privacy Policy