kee

Offline IOU signer with QR as transport
git clone https://holbrook.no/src/kee
Info | Log | Files | Refs | README | LICENSE

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:
Msrc/context.c | 3++-
Msrc/context.h | 4++--
Msrc/gtk/main.c | 21++++++++++++---------
Msrc/gtk/menu.h | 4++--
Msrc/gtk/scan.c | 106++++++++++++-------------------------------------------------------------------
Msrc/gtk/scan.h | 5++++-
Msrc/gtk/ui.c | 18++++++++++++++----
Msrc/gtk/ui.h | 4+++-
Msrc/settings.c | 15+++++++++++++++
Msrc/settings.h | 4++++
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, + }; /**