aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMauro Carvalho Chehab <mchehab+samsung@kernel.org>2018-09-19 11:58:46 -0300
committerMauro Carvalho Chehab <mchehab+samsung@kernel.org>2018-09-19 12:07:52 -0300
commit8db7a8e712ed7b341914490ec3ed043d0adb9724 (patch)
treeb6f9b98da7480b52eda7a72c6e1371919818ac42
parentc3ded86231683afed4d80022ad18f5329fdc1e94 (diff)
Better handle V4L2 device names
Instead of blindly rely on whatever is passed via command line or stored at GSettings, check against valid media devices, by seeking for them at /dev. Signed-off-by: Mauro Carvalho Chehab <mchehab+samsung@kernel.org>
-rw-r--r--config.h.in8
-rwxr-xr-xconfigure50
-rw-r--r--configure.ac1
-rw-r--r--src/main.c113
4 files changed, 159 insertions, 13 deletions
diff --git a/config.h.in b/config.h.in
index 4c62b29..60df219 100644
--- a/config.h.in
+++ b/config.h.in
@@ -67,6 +67,14 @@
/* Define to 1 if you have the <unistd.h> header file. */
#undef HAVE_UNISTD_H
+/* Define to 1 if `major', `minor', and `makedev' are declared in <mkdev.h>.
+ */
+#undef MAJOR_IN_MKDEV
+
+/* Define to 1 if `major', `minor', and `makedev' are declared in
+ <sysmacros.h>. */
+#undef MAJOR_IN_SYSMACROS
+
/* package name */
#undef PACKAGE
diff --git a/configure b/configure
index d5b78a1..caeceeb 100755
--- a/configure
+++ b/configure
@@ -7982,6 +7982,56 @@ fi
done
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether sys/types.h defines makedev" >&5
+$as_echo_n "checking whether sys/types.h defines makedev... " >&6; }
+if ${ac_cv_header_sys_types_h_makedev+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+#include <sys/types.h>
+int
+main ()
+{
+return makedev(0, 0);
+ ;
+ return 0;
+}
+_ACEOF
+if ac_fn_c_try_link "$LINENO"; then :
+ ac_cv_header_sys_types_h_makedev=yes
+else
+ ac_cv_header_sys_types_h_makedev=no
+fi
+rm -f core conftest.err conftest.$ac_objext \
+ conftest$ac_exeext conftest.$ac_ext
+
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_header_sys_types_h_makedev" >&5
+$as_echo "$ac_cv_header_sys_types_h_makedev" >&6; }
+
+if test $ac_cv_header_sys_types_h_makedev = no; then
+ac_fn_c_check_header_mongrel "$LINENO" "sys/mkdev.h" "ac_cv_header_sys_mkdev_h" "$ac_includes_default"
+if test "x$ac_cv_header_sys_mkdev_h" = xyes; then :
+
+$as_echo "#define MAJOR_IN_MKDEV 1" >>confdefs.h
+
+fi
+
+
+
+ if test $ac_cv_header_sys_mkdev_h = no; then
+ ac_fn_c_check_header_mongrel "$LINENO" "sys/sysmacros.h" "ac_cv_header_sys_sysmacros_h" "$ac_includes_default"
+if test "x$ac_cv_header_sys_sysmacros_h" = xyes; then :
+
+$as_echo "#define MAJOR_IN_SYSMACROS 1" >>confdefs.h
+
+fi
+
+
+ fi
+fi
+
for ac_header in fcntl.h stdlib.h string.h sys/ioctl.h unistd.h linux/videodev.h png.h glade/glade.h
do :
as_ac_Header=`$as_echo "ac_cv_header_$ac_header" | $as_tr_sh`
diff --git a/configure.ac b/configure.ac
index 92bd193..678b89f 100644
--- a/configure.ac
+++ b/configure.ac
@@ -30,6 +30,7 @@ AC_ISC_POSIX
AC_PROG_CC
AM_PROG_CC_STDC
AC_HEADER_STDC
+AC_HEADER_MAJOR
AC_CHECK_HEADERS([fcntl.h stdlib.h string.h sys/ioctl.h unistd.h linux/videodev.h png.h glade/glade.h])
# Don't assume that gcc warnings are errors
diff --git a/src/main.c b/src/main.c
index b38d368..9775f1f 100644
--- a/src/main.c
+++ b/src/main.c
@@ -7,14 +7,17 @@
#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, buggery = 0;
-static gchar *poopoo = NULL;
+static int half = 0, use_read = 0, debug = 0;
+static gchar *video_dev = NULL;
static int x = 0, y = 0;
#pragma GCC diagnostic push
@@ -23,9 +26,9 @@ static int x = 0, y = 0;
static GOptionEntry options[] = {
{"version", 'V', 0, G_OPTION_ARG_NONE, &ver,
N_("show version and exit"), NULL},
- {"device", 'd', 0, G_OPTION_ARG_STRING, &poopoo,
+ {"device", 'd', 0, G_OPTION_ARG_STRING, &video_dev,
N_("v4l device to use"), NULL},
- {"debug", 'D', 0, G_OPTION_ARG_NONE, &buggery,
+ {"debug", 'D', 0, G_OPTION_ARG_NONE, &debug,
N_("enable debugging code"), NULL},
{"width", 'x', 0, G_OPTION_ARG_INT, &x,
N_("capture width"), NULL},
@@ -97,6 +100,58 @@ static void close_app(GtkWidget* widget, cam_t *cam)
#endif
}
+static unsigned int n_devices = 0;
+static char **devices = NULL;
+
+static int retrieve_video_devs(const char *file,
+ const struct stat *st,
+ int flag)
+{
+ /* Discard devices that can't be a videodev */
+ if (!S_ISCHR(st->st_mode) || major(st->st_rdev) != 81)
+ return 0;
+
+ /* discard devices that aren't v4l/by-* or video? */
+ if (!strstr(file, "v4l") && !strstr(file, "video"))
+ return 0;
+
+ devices = realloc(devices, (n_devices + 1) * sizeof(char *));
+ if (!devices) {
+ char *msg = g_strdup_printf(_("Can't allocate memory to store devices"));
+ error_dialog(msg);
+ g_free(msg);
+ exit(0);
+ }
+
+ devices[n_devices++] = g_strdup(file);
+
+ return(0);
+}
+
+static int sort_devices(const void *__a, const void *__b)
+{
+ const char * const *a = __a;
+ const char * const *b = __b;
+ int v0 = 0, v1 = 0;
+
+ /* Ensure that /dev/video* devices will stay at the top */
+
+ if (strstr(*b, "/dev/video"))
+ v1 = 10;
+
+ if (strstr(*a, "/dev/video"))
+ v0 = 10;
+
+ if (v0 && v1)
+ return strcmp(*a, *b);
+ if (v0)
+ return -1;
+ if (v1)
+ return 1;
+
+ return strcmp(*a, *b);
+}
+
static cam_t cam_object = { 0 };
#if GTK_MAJOR_VERSION < 3
@@ -106,9 +161,8 @@ static void activate(GtkApplication *app)
#endif
{
cam_t *cam = &cam_object;
- GSettings *gc;
GtkWidget *widget, *window;
- unsigned int bufsize;
+ unsigned int bufsize, i;
/* set some default values */
cam->frame_number = 0;
@@ -127,7 +181,7 @@ static void activate(GtkApplication *app)
/* gtk is initialized now */
camorama_filters_init();
- cam->debug = buggery;
+ cam->debug = debug;
get_geometry(cam);
@@ -148,19 +202,52 @@ static void activate(GtkApplication *app)
printf("Forcing read mode\n");
cam->read = TRUE;
}
- gc = g_settings_new(CAM_SETTINGS_SCHEMA);
- cam->gc = gc;
+ /* 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);
+ }
+ qsort(devices, n_devices, sizeof(char *), sort_devices);
- if (!poopoo) {
- gchar const *gconf_device = g_settings_get_string(cam->gc, CAM_SETTINGS_DEVICE);
+ if (cam->debug)
+ for (i = 0; i < n_devices; i++)
+ printf("Device[%d]: %s\n", i, devices[i]);
+
+ cam->gc = g_settings_new(CAM_SETTINGS_SCHEMA);
+
+ if (!video_dev) {
+ gchar const *gconf_device = g_settings_get_string(cam->gc,
+ CAM_SETTINGS_DEVICE);
if (gconf_device)
cam->video_dev = g_strdup(gconf_device);
else
- cam->video_dev = g_strdup("/dev/video0");
+ cam->video_dev = NULL;
+ } else {
+ cam->video_dev = g_strdup(video_dev);
+ }
+
+ if (cam->video_dev) {
+ for (i = 0; i < n_devices; i++)
+ if (!strcmp(cam->video_dev, devices[i]))
+ break;
+
+ /* Not found. Falling back to the first device */
+ if (i == n_devices) {
+ char *msg = g_strdup_printf(_("%s not found. Falling back to %s"),
+ cam->video_dev, devices[0]);
+ error_dialog(msg);
+ g_free(msg);
+ cam->video_dev = devices[0];
+ }
} else {
- cam->video_dev = g_strdup(poopoo);
+ cam->video_dev = devices[0];
}
+ if (cam->debug)
+ printf("Using videodev: %s\n", cam->video_dev);
+
#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Wdiscarded-qualifiers"
cam->date_format = "%Y-%m-%d %H:%M:%S";

Privacy Policy