kee

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

commit 2c2c8dbd9abeea9a1e9a2701bc6600b9f9d1c97a
parent ae03e60f074ab0657e3591c570c68faaaa5f3f65
Author: lash <dev@holbrook.no>
Date:   Thu,  7 Mar 2024 15:31:10 +0000

Scanner component, create gobject to connect backend and ui

Diffstat:
MMakefile | 2+-
Msrc/context.c | 5+++++
Msrc/context.h | 2++
Msrc/gtk/Makefile | 8++++----
Asrc/gtk/kee-uicontext.c | 76++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Asrc/gtk/kee-uicontext.h | 27+++++++++++++++++++++++++++
Msrc/gtk/main.c | 13++++++++++++-
Msrc/gtk/menu.c | 4++++
Asrc/gtk/scan.c | 64++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Asrc/gtk/scan.h | 17+++++++++++++++++
Msrc/gtk/ui.c | 5+++++
Msrc/gtk/ui.h | 3+++
12 files changed, 220 insertions(+), 6 deletions(-)

diff --git a/Makefile b/Makefile @@ -17,7 +17,7 @@ clean: make -C src/aux clean run: gtk all - G_MESSAGES_DEBUG=all ./src/gtk/a.out + G_MESSAGES_DEBUG=all ./src/gtk/a.out debug: gtk all G_DEBUG=3 G_MESSAGES_DEBUG=all ./src/gtk/a.out diff --git a/src/context.c b/src/context.c @@ -5,4 +5,9 @@ void kee_context_new(struct kee_context *ctx, void *front) { memset(ctx, 0, sizeof(struct kee_context)); ctx->front = front; + ctx->state = 1; +} + +int kee_context_state(struct kee_context *ctx) { + return ctx->state; } diff --git a/src/context.h b/src/context.h @@ -8,8 +8,10 @@ struct kee_context { void *front; struct kee_settings settings; struct db_ctx db; + int state; }; void kee_context_new(struct kee_context *ctx, void *front); +int kee_context_state(struct kee_context *ctx); #endif // _KEE_CONTEXT diff --git a/src/gtk/Makefile b/src/gtk/Makefile @@ -1,9 +1,9 @@ OBJS := $(patsubst %.c,%.o,$(filter-out main.c,$(wildcard *.c))) LINKOBJS := $(wildcard ../*.o) $(OBJS) ../aux/varint/varint.o -INCLUDES := `pkg-config --cflags gtk4` -I.. -CFLAGS += $(INCLUDES) -g3 -Wall -LIBS := `pkg-config --libs gtk4 zlib lmdb libgcrypt libxdg-basedir` -lb64 -LDFLAGS += $(LIBS) +INCLUDES := -I.. +CFLAGS += `pkg-config --cflags gtk4 gstreamer-1.0` $(INCLUDES) -g3 -Wall +LIBS := `pkg-config --libs gtk4 zlib lmdb libgcrypt libxdg-basedir gstreamer-1.0` -lb64 +LDFLAGS += $(LIBS) all: resource $(OBJS) $(CC) $(CFLAGS) main.c -o a.out $(LINKOBJS) $(LDFLAGS) diff --git a/src/gtk/kee-uicontext.c b/src/gtk/kee-uicontext.c @@ -0,0 +1,76 @@ +#include <glib-object.h> + +#include "kee-uicontext.h" +#include "ui.h" +#include "context.h" + + +typedef struct { +} KeeUicontextPrivate; + +struct _KeeUicontext { + GObject parent; + struct ui_container *ui; + struct kee_context *ctx; +}; + +G_DEFINE_TYPE(KeeUicontext, kee_uicontext, G_TYPE_OBJECT) + +static GParamSpec *kee_props[KEE_N_PROPS] = {NULL,}; +static guint kee_sigs[KEE_N_SIGS] = {0,}; + +static void kee_uicontext_set_property(GObject *oo, guint property_id, const GValue *value, GParamSpec *pspec) { + KeeUicontext *o = KEE_UICONTEXT(oo); + + switch ((enum KEE_PROPS) property_id) { + case CORE_CONTEXT: + o->ctx = g_value_get_pointer(value); + break; + case UI_CONTAINER: + o->ui = g_value_get_pointer(value); + break; + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID(oo, property_id, pspec); + break; + } + +} + +static void kee_uicontext_class_init(KeeUicontextClass *kls) { + GObjectClass *o = G_OBJECT_CLASS(kls); + + kee_sigs[SCAN_WANT] = g_signal_newv("scan_want", + G_TYPE_FROM_CLASS(o), + G_SIGNAL_RUN_LAST | G_SIGNAL_NO_RECURSE | G_SIGNAL_NO_HOOKS, + NULL, + NULL, + NULL, + NULL, + G_TYPE_NONE, + 0, + NULL + ); + + o->set_property = kee_uicontext_set_property; + kee_props[CORE_CONTEXT] = g_param_spec_pointer( + "core_context", + "Core context", + "backend context to connect", + G_PARAM_CONSTRUCT_ONLY | G_PARAM_WRITABLE); + kee_props[UI_CONTAINER] = g_param_spec_pointer( + "ui_container", + "Ui Container", + "UI container to connect", + G_PARAM_CONSTRUCT_ONLY | G_PARAM_WRITABLE); + + g_object_class_install_properties(o, KEE_N_PROPS, kee_props); +} + +static void kee_uicontext_init(KeeUicontext *self) { + //KeeUicontextPrivate *o = kee_uicontext_get_instance_private(self); + +} + +void kee_uicontext_scanstart(KeeUicontext *o) { + g_signal_emit(o, kee_sigs[SCAN_WANT], 0); +} diff --git a/src/gtk/kee-uicontext.h b/src/gtk/kee-uicontext.h @@ -0,0 +1,27 @@ +#ifndef _GTK_KEE_UICONTEXT_H +#define _GTK_KEE_UICONTEXT_H + +#include <glib-object.h> + +G_BEGIN_DECLS + +enum KEE_SIGS { + SCAN_WANT, + KEE_N_SIGS, +}; + +enum KEE_PROPS { + CORE_CONTEXT = 1, + UI_CONTAINER, + KEE_N_PROPS, +}; + +#define KEE_TYPE_UICONTEXT kee_uicontext_get_type() +G_DECLARE_FINAL_TYPE(KeeUicontext, kee_uicontext, KEE, UICONTEXT, GObject) + +KeeUicontext* kee_uicontext_new(void); +void kee_uicontext_scanstart(KeeUicontext *o); + +G_END_DECLS + +#endif diff --git a/src/gtk/main.c b/src/gtk/main.c @@ -1,10 +1,12 @@ #include <string.h> #include <gtk/gtk.h> +#include <glib-object.h> #include "ui.h" #include "context.h" #include "menu.h" #include "settings.h" +#include "kee-uicontext.h" static void startup(GtkApplication *app, gpointer user_data) { @@ -19,18 +21,23 @@ static void deactivate(GtkApplication *app, gpointer user_data) { ui_free(user_data); } +static void tmpscan (KeeUicontext *o, gpointer v) { + g_log(G_LOG_DOMAIN, G_LOG_LEVEL_DEBUG, "foo in scan want"); +} + int main(int argc, char **argv) { int r; + KeeUicontext *uctx; struct kee_context ctx; struct ui_container ui; - r = ui_init(&ui); if (r) { 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_init(&ctx.settings); @@ -39,8 +46,12 @@ int main(int argc, char **argv) { g_signal_connect (ui.gapp, "startup", G_CALLBACK (startup), &ui); g_signal_connect (ui.gapp, "activate", G_CALLBACK (activate), &ui); g_signal_connect (ui.gapp, "shutdown", G_CALLBACK (deactivate), &ui); + g_signal_connect (uctx, "scan_want", G_CALLBACK( tmpscan ), NULL); r = g_application_run (G_APPLICATION (ui.gapp), argc, argv); + + kee_uicontext_scanstart(uctx); + g_object_unref(ui.gapp); return r; } diff --git a/src/gtk/menu.c b/src/gtk/menu.c @@ -4,7 +4,11 @@ static void act_scan(GSimpleAction *act, GVariant *param, GApplication *app) { + //GDBusConnection *conn; + g_log(G_LOG_DOMAIN, G_LOG_LEVEL_DEBUG, "scan clicked"); + //conn = g_application_get_dbus_connection(app); + } static void act_quit(GSimpleAction *act, GVariant *param, GApplication *app) { diff --git a/src/gtk/scan.c b/src/gtk/scan.c @@ -0,0 +1,64 @@ +#include <gtk/gtk.h> +#include <gst/gst.h> + +#include "scan.h" +#include "err.h" + +gboolean msg_func(GstBus *bus, GstMessage *msg, gpointer user_data) { + return false; +} + +int scan_init(struct kee_scanner *scan) { + GdkPaintable *img; + GstCaps *caps; + GstElement *convert; + GstElement *filter; + GstStateChangeReturn rsc; + GstBus *bus; + 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_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)); + 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_PAUSED); + 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; + } + + bus = gst_element_get_bus(scan->pipeline); + gst_bus_add_watch(bus, msg_func, &scan); + + return ERR_OK; +} diff --git a/src/gtk/scan.h b/src/gtk/scan.h @@ -0,0 +1,17 @@ +#ifndef _KEE_GTK_SCAN_H +#define _KEE_GTK_SCAN_H + +#include <gst/gst.h> +#include <gtk/gtk.h> + +struct kee_scanner { + GtkPicture *video_view; + GstElement *pipeline; + GstElement *source; + GstElement *video_sink; + GtkImage *snap; +}; + +int scan_init(struct kee_scanner *scan); + +#endif // _KEE_GTK_SCAN_H diff --git a/src/gtk/ui.c b/src/gtk/ui.c @@ -1,14 +1,19 @@ #include <gtk/gtk.h> +#include <gst/gst.h> #include "ui.h" #include "err.h" +#include "scan.h" int ui_init(struct ui_container *ui) { + gtk_init(); + gst_init(0, NULL); ui->gapp = gtk_application_new ("org.defalsify.Kee", G_APPLICATION_DEFAULT_FLAGS); if (ui->gapp == NULL) { return ERR_FAIL; } + //scan_init(&ui->scan); return ERR_OK; } diff --git a/src/gtk/ui.h b/src/gtk/ui.h @@ -3,12 +3,15 @@ #include <gtk/gtk.h> +#include "scan.h" + struct ui_container { GtkApplication *gapp; GtkApplicationWindow *win; GtkStack *stack; GListModel *front_list; GtkListView *front_view; + struct kee_scanner scan; }; int ui_init(struct ui_container *ui);