commit dc057e8038f66bf9f82ba527b7ce81c8f1a87494
parent ceb1f6b91c628390be9360939f35643d209789e4
Author: lash <dev@holbrook.no>
Date: Sun, 10 Mar 2024 16:03:53 +0000
Make video device settable by environment variable
Diffstat:
10 files changed, 74 insertions(+), 110 deletions(-)
diff --git a/src/context.c b/src/context.c
@@ -2,10 +2,11 @@
#include "context.h"
#include "settings.h"
-void kee_context_new(struct kee_context *ctx, void *front) {
+void kee_context_new(struct kee_context *ctx, void *front, struct kee_settings *settings) {
memset(ctx, 0, sizeof(struct kee_context));
ctx->front = front;
ctx->state = 1;
+ ctx->settings = settings;
}
int kee_context_state(struct kee_context *ctx) {
diff --git a/src/context.h b/src/context.h
@@ -6,12 +6,12 @@
struct kee_context {
void *front;
- struct kee_settings settings;
+ struct kee_settings *settings;
struct db_ctx db;
int state;
};
-void kee_context_new(struct kee_context *ctx, void *front);
+void kee_context_new(struct kee_context *ctx, void *front, struct kee_settings *settings);
int kee_context_state(struct kee_context *ctx);
#endif // _KEE_CONTEXT
diff --git a/src/gtk/main.c b/src/gtk/main.c
@@ -9,12 +9,12 @@
#include "settings.h"
-static void startup(GtkApplication *app, gpointer user_data) {
- menu_setup(user_data);
+static void startup(GtkApplication *app, KeeUicontext *ctx) {
+ menu_setup(ctx);
}
-static void activate(GtkApplication *app, gpointer user_data) {
- ui_build(app, user_data);
+static void activate(GtkApplication *app, struct ui_container *ui) {
+ ui_build(app, ui);
}
static void deactivate(GtkApplication *app, gpointer user_data) {
@@ -25,6 +25,7 @@ static void deactivate(GtkApplication *app, gpointer user_data) {
int main(int argc, char **argv) {
int r;
KeeUicontext *uctx;
+ struct kee_settings settings;
struct kee_context ctx;
struct ui_container ui;
@@ -33,17 +34,19 @@ int main(int argc, char **argv) {
return r;
}
- kee_context_new(&ctx, &ui);
- uctx = g_object_new(KEE_TYPE_UICONTEXT, "ui_container", &ui, "core_context", &ctx, NULL);
+ //settings_new_from_xdg(&ctx.settings);
+ settings_new_from_xdg(&settings);
+ //settings_init(&ctx.settings);
+ settings_init(&settings);
- settings_new_from_xdg(&ctx.settings);
- settings_init(&ctx.settings);
+ kee_context_new(&ctx, &ui, &settings);
+ uctx = g_object_new(KEE_TYPE_UICONTEXT, "ui_container", &ui, "core_context", &ctx, NULL);
db_connect(&ctx.db, "./testdata_mdb");
g_signal_connect (ui.gapp, "startup", G_CALLBACK (startup), uctx);
g_signal_connect (ui.gapp, "activate", G_CALLBACK (activate), &ui);
g_signal_connect (ui.gapp, "shutdown", G_CALLBACK (deactivate), uctx);
- g_signal_connect (uctx, "scan_want", G_CALLBACK( ui_handle_scan) , &ui);
+ g_signal_connect (uctx, "scan_want", G_CALLBACK( ui_handle_scan) , &ctx);
r = g_application_run (G_APPLICATION (ui.gapp), argc, argv);
diff --git a/src/gtk/menu.h b/src/gtk/menu.h
@@ -1,8 +1,8 @@
#ifndef _KEE_GTK_MENU_H
#define _KEE_GTK_MENU_H
-#include "ui.h"
+#include "kee-uicontext.h"
-void menu_setup(struct ui_container *ui);
+void menu_setup(KeeUicontext *ctx);
#endif // _KEE_GTK_MENU_H
diff --git a/src/gtk/scan.c b/src/gtk/scan.c
@@ -1,96 +1,23 @@
+#include <stdlib.h>
+#include <string.h>
#include <gtk/gtk.h>
#include <gst/gst.h>
#include "scan.h"
#include "err.h"
-//gboolean msg_func(GstBus *bus, GstMessage *msg, gpointer user_data) {
-// GError *err;
-// gchar *debug_info;
-// GstState oldstate;
-// GstState newstate;
-// GstState pendingstate;
-// //struct _gst_data *data;
-// //GstStateChangeReturn rsc;
-//
-// //data = (struct _gst_data*)user_data;
-//
-// switch (GST_MESSAGE_TYPE (msg)) {
-// case GST_MESSAGE_ERROR:
-// gst_message_parse_error(msg, &err, &debug_info);
-// g_log(G_LOG_DOMAIN, G_LOG_LEVEL_WARNING, "logg %s: %s", GST_OBJECT_NAME(msg->src), err->message);
-// g_log(G_LOG_DOMAIN, G_LOG_LEVEL_WARNING, "debug %s", debug_info ? debug_info : "none");
-// g_clear_error(&err);
-// g_free(debug_info);
-// break;
-// case GST_MESSAGE_EOS:
-// g_log(G_LOG_DOMAIN, G_LOG_LEVEL_INFO, "eos");
-// break;
-// case GST_MESSAGE_STATE_CHANGED:
-// gst_message_parse_state_changed(msg, &oldstate, &newstate, &pendingstate);
-// g_log(G_LOG_DOMAIN, G_LOG_LEVEL_INFO, "state change: %s -> %s", gst_element_state_get_name(oldstate), gst_element_state_get_name(newstate));
-// break;
-// default:
-// g_log(G_LOG_DOMAIN, G_LOG_LEVEL_ERROR, "unknown message (ext %d): %s", GST_MESSAGE_TYPE_IS_EXTENDED(msg), GST_MESSAGE_TYPE_NAME(msg));
-// }
-//
-// return false;
-//}
-
-//int scan_init(struct kee_scanner *scan) {
-// GdkPaintable *img;
-// GstCaps *caps;
-// GstElement *convert;
-// GstElement *filter;
-// GstStateChangeReturn rsc;
-// gchar *txt;
-//
-// memset(scan, 0, sizeof(struct kee_scanner));
-//
-// scan->pipeline = gst_pipeline_new("kee-qr-scan");
-// scan->source = gst_element_factory_make("v4l2src", "v4l2src");
-// scan->video_sink = gst_element_factory_make("gtk4paintablesink", "gtk4paintablesink");
-// if (scan->video_sink == NULL) {
-// g_log(G_LOG_DOMAIN, G_LOG_LEVEL_WARNING, "cant create gl sinks");
-// return 1;
-// }
-// //g_object_set(G_OBJECT(scan->source), "device", "/dev/video0", NULL);
-// g_object_set(G_OBJECT(scan->source), "device", "/dev/video4", NULL);
-//
-// g_object_get(scan->video_sink, "paintable", &img, NULL);
-// if (!img) {
-// g_log(G_LOG_DOMAIN, G_LOG_LEVEL_WARNING, "failed getting paintable");
-// return 1;
-// }
-//
-// g_object_get(scan->source, "device", &txt, NULL);
-// g_log(G_LOG_DOMAIN, G_LOG_LEVEL_INFO, "using video device: %s", txt);
-//
-// filter = gst_element_factory_make("capsfilter", "capsfilter");
-// convert = gst_element_factory_make("videoconvert", "videoconvert");
-// caps = gst_caps_new_simple("video/x-raw", "format", G_TYPE_STRING, "RGB", "width", G_TYPE_INT, 640, "height", G_TYPE_INT, 480, "framerate", GST_TYPE_FRACTION, 30, 1, "pixel-aspect-ratio", GST_TYPE_FRACTION, 1, 1, NULL);
-// g_object_set(G_OBJECT(filter), "caps", caps, NULL);
-// scan->video_view = GTK_PICTURE(gtk_picture_new_for_paintable(img));
-// gtk_picture_set_content_fit(scan->video_view, GTK_CONTENT_FIT_CONTAIN);
-// gst_bin_add_many(GST_BIN(scan->pipeline), scan->source, convert, filter, scan->video_sink, NULL);
-//
-// if (gst_element_link_many(scan->source, convert, filter, scan->video_sink, NULL) != TRUE) {
-// g_log(G_LOG_DOMAIN, G_LOG_LEVEL_ERROR, "gst pipeline link fail");
-// gst_object_unref(scan->pipeline);
-// return 1;
-// }
-//
-// rsc = gst_element_set_state(scan->pipeline, GST_STATE_PLAYING);
-// if (rsc == GST_STATE_CHANGE_FAILURE) {
-// g_log(G_LOG_DOMAIN, G_LOG_LEVEL_ERROR, "fail set pipeline to pause");
-// gst_object_unref(scan->pipeline);
-// return 1;
-// }
-//
-// return ERR_OK;
-//}
-
-int scan_init(struct kee_scanner *scan) {
+
+void scan_init(struct kee_scanner *scan, const char *device) {
+ memset(scan, 0, sizeof(struct kee_scanner));
+ scan->device = malloc(strlen(device) + 1);
+ strcpy(scan->device, device);
+}
+
+void scan_free(struct kee_scanner *scan) {
+ free(scan->device);
+}
+
+int scan_begin(struct kee_scanner *scan) {
GstElement *tee;
GstElement *zbar;
GstElement *queue_display;
@@ -107,8 +34,7 @@ int scan_init(struct kee_scanner *scan) {
GstCaps *caps;
GdkPaintable *img;
- g_log(G_LOG_DOMAIN, G_LOG_LEVEL_DEBUG, "camera setup");
- memset(scan, 0, sizeof(struct kee_scanner));
+ g_log(G_LOG_DOMAIN, G_LOG_LEVEL_INFO, "starting scan with video device %s", scan->device);
scan->pipeline = gst_pipeline_new("webcam-zbar");
scan->source = gst_element_factory_make("v4l2src", "v4l2src");
@@ -151,7 +77,7 @@ int scan_init(struct kee_scanner *scan) {
queue_scan_pad = gst_element_get_static_pad(queue_scan, "sink");
g_log(G_LOG_DOMAIN, G_LOG_LEVEL_DEBUG, "scan queue linked with %s", gst_pad_get_name(tee_scan));
- g_object_set(G_OBJECT(scan->source), "device", "/dev/video4", NULL);
+ g_object_set(G_OBJECT(scan->source), "device", scan->device, NULL);
g_object_get(scan->video_sink, "paintable", &img, NULL);
if (!img) {
g_log(G_LOG_DOMAIN, G_LOG_LEVEL_WARNING, "failed getting paintable");
diff --git a/src/gtk/scan.h b/src/gtk/scan.h
@@ -10,9 +10,12 @@ struct kee_scanner {
GstElement *source;
GstElement *video_sink;
GtkImage *snap;
+ char *device;
};
-int scan_init(struct kee_scanner *scan);
+void scan_init(struct kee_scanner *scan, const char *device);
+int scan_begin(struct kee_scanner *scan);
+void scan_free(struct kee_scanner *scan);
void scan_set_handler(struct kee_scanner *scan, gboolean(*fn)(GstBus *bus, GstMessage *msg, gpointer user_data));
#endif // _KEE_GTK_SCAN_H
diff --git a/src/gtk/ui.c b/src/gtk/ui.c
@@ -5,6 +5,8 @@
#include "ui.h"
#include "err.h"
#include "scan.h"
+#include "settings.h"
+#include "context.h"
int ui_init(struct ui_container *ui) {
@@ -175,13 +177,14 @@ gboolean ui_scan_code_handler(GstBus *bus, GstMessage *msg, gpointer user_data)
return true;
}
-GtkWidget* ui_build_scan_attach(struct ui_container *ui) {
+GtkWidget* ui_build_scan_attach(struct ui_container *ui, const char *device) {
int r;
struct kee_scanner *scan;
GtkWidget *view;
scan = &ui->scan;
- r = scan_init(scan);
+ scan_init(scan, device);
+ r = scan_begin(scan);
if (r) {
g_log(G_LOG_DOMAIN, G_LOG_LEVEL_ERROR, "fail scan setup");
return NULL;
@@ -192,9 +195,16 @@ GtkWidget* ui_build_scan_attach(struct ui_container *ui) {
return view;
}
-void ui_handle_scan(GtkApplication *app, struct ui_container *ui) {
+//void ui_handle_scan(GtkApplication *app, struct ui_container *ui) {
+void ui_handle_scan(GtkApplication *app, struct kee_context *ctx) {
+ struct ui_container *ui;
+ unsigned char *s;
+
+ ui = (struct ui_container*)ctx->front;
+ s = settings_get(ctx->settings, SETTINGS_VIDEO);
+
if (!(ui->state & KEE_UI_STATE_SCAN_INIT)) {
- ui_build_scan_attach(ui);
+ ui_build_scan_attach(ui, (const char*)s);
}
ui_state_change(ui, KEE_UI_STATE_SCANNING | KEE_UI_STATE_SCAN_INIT, 0);
diff --git a/src/gtk/ui.h b/src/gtk/ui.h
@@ -4,6 +4,7 @@
#include <gtk/gtk.h>
#include "scan.h"
+#include "settings.h"
typedef enum {
@@ -22,6 +23,7 @@ struct ui_container {
GtkListView *front_view;
GtkBox *front_scan;
struct kee_scanner scan;
+ struct kee_context *ctx;
int state;
};
@@ -30,6 +32,6 @@ void ui_build(GtkApplication *app, struct ui_container *ui);
int ui_state_change(struct ui_container *ui, int set, int reset);
void ui_free(struct ui_container *ui);
-void ui_handle_scan(GtkApplication *app, struct ui_container *ui);
+void ui_handle_scan(GtkApplication *app, struct kee_context *ctx);
#endif // _UI_H
diff --git a/src/settings.c b/src/settings.c
@@ -31,6 +31,8 @@ int settings_new_from_xdg(struct kee_settings *z) {
z->run = p;
p += KEE_SETTINGS_ITEM_CAP;
z->locktime = p;
+ p += KEE_SETTINGS_ITEM_CAP;
+ z->video_device = p;
s = xdgDataHome(&xdg);
sprintf((char*)z->data, "%s/%s", s, KEE_SETTINGS_NAME);
@@ -41,9 +43,13 @@ int settings_new_from_xdg(struct kee_settings *z) {
return ERR_OK;
}
+/***
+ * \todo verify default video exists
+ */
int settings_init(struct kee_settings *z) {
int r;
char s[1024];
+ char *ss;
r = mkdir((char*)z->data, S_IRUSR | S_IWUSR);
if (r) {
@@ -55,6 +61,12 @@ int settings_init(struct kee_settings *z) {
sprintf(s, "datadir: %s\nrundir: %s", z->data, z->run);
debug_log(DEBUG_DEBUG, s);
+ ss = getenv("KEE_VIDEO");
+ if (!ss) {
+ ss = "/dev/video0";
+ }
+ strcpy((char*)z->video_device, ss);
+
return ERR_OK;
}
@@ -69,6 +81,9 @@ unsigned char *settings_get(struct kee_settings *z, enum SettingsType typ) {
case SETTINGS_LOCKTIME:
return z->locktime;
break;
+ case SETTINGS_VIDEO:
+ return z->video_device;
+ break;
default:
return (unsigned char*)"";
}
diff --git a/src/settings.h b/src/settings.h
@@ -10,6 +10,7 @@ struct kee_settings {
unsigned char *data;
unsigned char *run;
unsigned char *locktime;
+ unsigned char *video_device;
};
/**
@@ -23,6 +24,9 @@ enum SettingsType {
SETTINGS_RUN = 0x02,
/// Milliseconds a key will stay unlocked since last application use.
SETTINGS_LOCKTIME = 0x10,
+ /// Default video device to use
+ SETTINGS_VIDEO = 0x20,
+
};
/**