aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMauro Carvalho Chehab <mchehab+samsung@kernel.org>2018-09-19 14:26:01 -0300
committerMauro Carvalho Chehab <mchehab+samsung@kernel.org>2018-09-21 06:34:58 -0300
commitf85679e6c08c5ed1c8bee595bb15805d1e9ec081 (patch)
tree6cfeee80ab0756013e06a18765c21ef6f791a852
parent6087e0f3b3b2cfd57bf5eb173eaa0d4dd34ba9a4 (diff)
Add a dialog to optionally select the video device
The first time camorama is started, or if it doesn't find the previously used camera, it will now open a dialog allowing the user to choose the camera. Signed-off-by: Mauro Carvalho Chehab <mchehab+samsung@kernel.org>
-rw-r--r--data/camorama-gtk2.ui80
-rw-r--r--data/camorama-gtk3.ui82
-rw-r--r--data/camorama-gtk4.ui72
-rw-r--r--src/camorama-window.c2
-rw-r--r--src/main.c125
-rw-r--r--src/v4l.c8
-rw-r--r--src/v4l.h2
7 files changed, 349 insertions, 22 deletions
diff --git a/data/camorama-gtk2.ui b/data/camorama-gtk2.ui
index 8a19cbe..e32d438 100644
--- a/data/camorama-gtk2.ui
+++ b/data/camorama-gtk2.ui
@@ -1194,7 +1194,6 @@
<property name="pixbuf">snap-icon-small.xpm</property>
</object>
<object class="GtkWindow" id="main_window">
- <property name="visible">True</property>
<property name="can_focus">False</property>
<property name="title" translatable="yes">Camorama-libglade</property>
<accel-groups>
@@ -1810,4 +1809,83 @@
</object>
</child>
</object>
+ <object class="GtkDialog" id="videodev_window">
+ <property name="can_focus">False</property>
+ <property name="border_width">5</property>
+ <property name="type_hint">dialog</property>
+ <child internal-child="vbox">
+ <object class="GtkVBox" id="videodev_vbox4">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="spacing">2</property>
+ <child internal-child="action_area">
+ <object class="GtkHButtonBox" id="dialog-action_area4">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="layout_style">end</property>
+ <child>
+ <placeholder/>
+ </child>
+ <child>
+ <object class="GtkButton" id="videodev_ok">
+ <property name="label">gtk-ok</property>
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="receives_default">True</property>
+ <property name="use_underline">True</property>
+ <property name="use_stock">True</property>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">False</property>
+ <property name="position">1</property>
+ </packing>
+ </child>
+ </object>
+ <packing>
+ <property name="expand">True</property>
+ <property name="fill">True</property>
+ <property name="position">0</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkVBox" id="videodev_vbox">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <child>
+ <object class="GtkLabel" id="videodev_label">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="label" translatable="yes">Select a video device to be used</property>
+ </object>
+ <packing>
+ <property name="expand">True</property>
+ <property name="fill">True</property>
+ <property name="position">0</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkComboBoxText" id="videodev_combo">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ </object>
+ <packing>
+ <property name="expand">True</property>
+ <property name="fill">True</property>
+ <property name="position">1</property>
+ </packing>
+ </child>
+ </object>
+ <packing>
+ <property name="expand">True</property>
+ <property name="fill">True</property>
+ <property name="position">1</property>
+ </packing>
+ </child>
+ </object>
+ </child>
+ <action-widgets>
+ <action-widget response="0">videodev_ok</action-widget>
+ </action-widgets>
+ </object>
</interface>
diff --git a/data/camorama-gtk3.ui b/data/camorama-gtk3.ui
index 05520e7..3b74bfe 100644
--- a/data/camorama-gtk3.ui
+++ b/data/camorama-gtk3.ui
@@ -36,7 +36,6 @@
<property name="pixbuf">snap-icon-small.xpm</property>
</object>
<object class="GtkWindow" id="main_window">
- <property name="visible">True</property>
<property name="can_focus">False</property>
<property name="title" translatable="yes">Camorama-libglade</property>
<accel-groups>
@@ -1773,4 +1772,85 @@
<placeholder/>
</child>
</object>
+ <object class="GtkDialog" id="videodev_window">
+ <property name="can_focus">False</property>
+ <property name="modal">True</property>
+ <property name="window_position">center</property>
+ <property name="destroy_with_parent">True</property>
+ <property name="type_hint">dialog</property>
+ <property name="transient_for">main_window</property>
+ <child internal-child="vbox">
+ <object class="GtkBox">
+ <property name="can_focus">False</property>
+ <property name="orientation">vertical</property>
+ <property name="spacing">2</property>
+ <child internal-child="action_area">
+ <object class="GtkButtonBox">
+ <property name="can_focus">False</property>
+ <property name="layout_style">end</property>
+ <child>
+ <placeholder/>
+ </child>
+ <child>
+ <object class="GtkButton" id="videodev_ok">
+ <property name="label">gtk-ok</property>
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="receives_default">True</property>
+ <property name="use_stock">True</property>
+ </object>
+ <packing>
+ <property name="expand">True</property>
+ <property name="fill">True</property>
+ <property name="position">1</property>
+ </packing>
+ </child>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">False</property>
+ <property name="position">0</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkBox">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="orientation">vertical</property>
+ <child>
+ <object class="GtkLabel">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="label" translatable="yes">Select a video device to be used</property>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">True</property>
+ <property name="position">0</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkComboBoxText" id="videodev_combo">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">True</property>
+ <property name="position">1</property>
+ </packing>
+ </child>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">True</property>
+ <property name="position">1</property>
+ </packing>
+ </child>
+ </object>
+ </child>
+ <child type="titlebar">
+ <placeholder/>
+ </child>
+ </object>
</interface>
diff --git a/data/camorama-gtk4.ui b/data/camorama-gtk4.ui
index 7acb03f..ac2a5dd 100644
--- a/data/camorama-gtk4.ui
+++ b/data/camorama-gtk4.ui
@@ -24,7 +24,6 @@
<property name="step_increment">1</property>
</object>
<object class="GtkWindow" id="main_window">
- <property name="visible">True</property>
<property name="can_focus">False</property>
<property name="title" translatable="yes">Camorama-libglade</property>
<accel-groups>
@@ -1565,4 +1564,75 @@
<placeholder/>
</child>
</object>
+ <object class="GtkDialog" id="videodev_window">
+ <property name="can_focus">False</property>
+ <property name="modal">True</property>
+ <property name="window_position">center</property>
+ <property name="destroy_with_parent">True</property>
+ <property name="type_hint">dialog</property>
+ <property name="transient_for">main_window</property>
+ <child internal-child="vbox">
+ <object class="GtkBox">
+ <property name="can_focus">False</property>
+ <property name="orientation">vertical</property>
+ <property name="spacing">2</property>
+ <child internal-child="action_area">
+ <object class="GtkButtonBox">
+ <property name="can_focus">False</property>
+ <property name="layout_style">end</property>
+ <child>
+ <placeholder/>
+ </child>
+ <child>
+ <object class="GtkButton" id="videodev_ok">
+ <property name="label">_Ok</property>
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="receives_default">True</property>
+ <property name="use_underline">True</property>
+ </object>
+ <packing>
+ <property name="position">1</property>
+ </packing>
+ </child>
+ </object>
+ <packing>
+ <property name="position">0</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkBox">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="orientation">vertical</property>
+ <child>
+ <object class="GtkLabel">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="label" translatable="yes">Select a video device to be used</property>
+ </object>
+ <packing>
+ <property name="position">0</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkComboBoxText" id="videodev_combo">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ </object>
+ <packing>
+ <property name="position">1</property>
+ </packing>
+ </child>
+ </object>
+ <packing>
+ <property name="position">1</property>
+ </packing>
+ </child>
+ </object>
+ </child>
+ <child type="titlebar">
+ <placeholder/>
+ </child>
+ </object>
</interface>
diff --git a/src/camorama-window.c b/src/camorama-window.c
index 33fd847..c8595a9 100644
--- a/src/camorama-window.c
+++ b/src/camorama-window.c
@@ -205,6 +205,8 @@ void load_interface(cam_t *cam)
gtk_application_add_window(cam->app, GTK_WINDOW(window));
#endif
+ gtk_widget_show(window);
+
prefswindow = GTK_WIDGET(gtk_builder_get_object(cam->xml, "prefswindow"));
menu_item_filter_type = g_quark_from_static_string("camorama-menu-item-filter-type");
diff --git a/src/main.c b/src/main.c
index 6d4a6f0..d61e7e9 100644
--- a/src/main.c
+++ b/src/main.c
@@ -228,6 +228,73 @@ static int sort_devices(const void *__a, const void *__b)
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
@@ -239,6 +306,7 @@ 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;
@@ -305,6 +373,31 @@ 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)
@@ -312,11 +405,19 @@ static void activate(GtkApplication *app)
/* Not found, or doesn't work. 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].fname);
+ char *msg;
+
+ if (n_valid_devices == 1)
+ msg = g_strdup_printf(_("%s not found. Falling back to %s"),
+ cam->video_dev, devices[0].fname);
+ else
+ msg = g_strdup_printf(_("%s not found."),
+ cam->video_dev);
error_dialog(msg);
g_free(msg);
- cam->video_dev = devices[0].fname;
+
+ /* Ask user or get the only one device, if it is the case */
+ select_video_dev(cam);
}
} else {
cam->video_dev = devices[0].fname;
@@ -375,7 +476,9 @@ static void activate(GtkApplication *app)
else
cam->dev = v4l2_open(cam->video_dev, O_RDWR | O_NONBLOCK);
- camera_cap(cam);
+ if (camera_cap(cam))
+ exit(-1);
+
get_win_info(cam);
set_win_info(cam);
@@ -384,6 +487,9 @@ static void activate(GtkApplication *app)
/* get picture attributes */
get_pic_info(cam);
+ /* Only store the device name after being able to successfully use it */
+ g_settings_set_string(cam->gc, CAM_SETTINGS_DEVICE, cam->video_dev);
+
bufsize = cam->max_width * cam->max_height * cam->bpp / 8;
cam->pic_buf = malloc(bufsize);
cam->tmp = malloc(bufsize);
@@ -398,17 +504,6 @@ static void activate(GtkApplication *app)
else
printf("using read()\n");
- 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);
- }
-
- g_settings_set_string(cam->gc, CAM_SETTINGS_DEVICE, cam->video_dev);
-
load_interface(cam);
widget = GTK_WIDGET(gtk_builder_get_object(cam->xml, "da"));
diff --git a/src/v4l.c b/src/v4l.c
index 7cea990..d8732c6 100644
--- a/src/v4l.c
+++ b/src/v4l.c
@@ -129,7 +129,7 @@ void get_supported_resolutions(cam_t *cam)
qsort(cam->res, cam->n_res, sizeof(struct resolutions), sort_func);
}
-void camera_cap(cam_t *cam)
+int camera_cap(cam_t *cam)
{
char *msg;
int i;
@@ -145,7 +145,7 @@ void camera_cap(cam_t *cam)
cam->video_dev, errno);
error_dialog(msg);
g_free(msg);
- exit(0);
+ return 1;
}
/* Query supported resolutions */
@@ -247,7 +247,7 @@ void camera_cap(cam_t *cam)
cam->video_dev);
error_dialog(msg);
g_free(msg);
- exit(0);
+ return 1;
}
if (!(vid_cap.device_caps & V4L2_CAP_STREAMING))
@@ -265,6 +265,8 @@ void camera_cap(cam_t *cam)
printf("min width = %d\n", cam->min_width);
printf("min height = %d\n", cam->min_height);
}
+
+ return 0;
}
void get_pic_info(cam_t *cam)
diff --git a/src/v4l.h b/src/v4l.h
index 2fc706e..69df548 100644
--- a/src/v4l.h
+++ b/src/v4l.h
@@ -102,7 +102,7 @@ typedef struct camera {
} *buffers;
} cam_t;
-void camera_cap(cam_t *);
+int camera_cap(cam_t *);
void print_cam(cam_t *);
void try_set_win_info(cam_t *cam, unsigned int *x, unsigned int *y);
void set_win_info(cam_t *cam);

Privacy Policy