aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorTheJackiMonster <thejackimonster@gmail.com>2021-11-14 23:13:01 +0100
committerTheJackiMonster <thejackimonster@gmail.com>2021-11-14 23:13:01 +0100
commit760976b15f400194d9264a5295e27e70b88afb73 (patch)
treeb6117668a8cef01c0a7920c26d5178a04c564916
parentf6e0bb11c86814b5246aa0e03938ade2f4acd2d1 (diff)
downloadmessenger-gtk-760976b15f400194d9264a5295e27e70b88afb73.tar.gz
messenger-gtk-760976b15f400194d9264a5295e27e70b88afb73.zip
Added zbar video input to scan for contacts
Signed-off-by: TheJackiMonster <thejackimonster@gmail.com>
-rw-r--r--Makefile3
-rw-r--r--resources/ui/new_contact.ui131
-rw-r--r--resources/ui/new_platform.ui3
-rw-r--r--src/application.h2
-rw-r--r--src/ui/messenger.c23
-rw-r--r--src/ui/new_contact.c266
-rw-r--r--src/ui/new_contact.h59
-rw-r--r--src/ui/new_platform.c16
-rw-r--r--src/ui/new_platform.h2
9 files changed, 492 insertions, 13 deletions
diff --git a/Makefile b/Makefile
index 7b96219..23bd6bf 100644
--- a/Makefile
+++ b/Makefile
@@ -11,11 +11,12 @@ SOURCES = messenger_gtk.c\
11 ui/chat_entry.c\ 11 ui/chat_entry.c\
12 ui/message.c\ 12 ui/message.c\
13 ui/messenger.c\ 13 ui/messenger.c\
14 ui/new_contact.c\
14 ui/new_platform.c 15 ui/new_platform.c
15 16
16HEADERS = 17HEADERS =
17 18
18LIBRARIES = gnunetchat 19LIBRARIES = gnunetchat zbargtk
19PACKAGES = gnunetutil libhandy-1 gtk+-3.0 libnotify zbar libqrencode 20PACKAGES = gnunetutil libhandy-1 gtk+-3.0 libnotify zbar libqrencode
20 21
21GNU_CC ?= gcc 22GNU_CC ?= gcc
diff --git a/resources/ui/new_contact.ui b/resources/ui/new_contact.ui
new file mode 100644
index 0000000..8788a26
--- /dev/null
+++ b/resources/ui/new_contact.ui
@@ -0,0 +1,131 @@
1<?xml version="1.0" encoding="UTF-8"?>
2<!-- Generated with glade 3.38.2
3
4Copyright (C) 2021 GNUnet e.V.
5
6GNUnet is free software: you can redistribute it and/or modify it
7under the terms of the GNU Affero General Public License as published
8by the Free Software Foundation, either version 3 of the License,
9or (at your option) any later version.
10
11GNUnet is distributed in the hope that it will be useful, but
12WITHOUT ANY WARRANTY; without even the implied warranty of
13MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14Affero General Public License for more details.
15
16You should have received a copy of the GNU Affero General Public License
17along with this program. If not, see <http://www.gnu.org/licenses/>.
18
19SPDX-License-Identifier: AGPL3.0-or-later
20Author: Tobias Frisch
21
22-->
23<interface>
24 <requires lib="gtk+" version="3.24"/>
25 <object class="GtkDialog" id="new_contact_dialog">
26 <property name="can-focus">False</property>
27 <property name="modal">True</property>
28 <property name="window-position">center-on-parent</property>
29 <property name="type-hint">dialog</property>
30 <child internal-child="vbox">
31 <object class="GtkBox">
32 <property name="can-focus">False</property>
33 <property name="orientation">vertical</property>
34 <property name="spacing">2</property>
35 <child internal-child="action_area">
36 <object class="GtkButtonBox">
37 <property name="can-focus">False</property>
38 <property name="layout-style">end</property>
39 <child>
40 <object class="GtkButton" id="cancel_button">
41 <property name="label" translatable="yes">Cancel</property>
42 <property name="visible">True</property>
43 <property name="can-focus">True</property>
44 <property name="receives-default">True</property>
45 </object>
46 <packing>
47 <property name="expand">True</property>
48 <property name="fill">True</property>
49 <property name="position">0</property>
50 </packing>
51 </child>
52 <child>
53 <object class="GtkButton" id="confirm_button">
54 <property name="label" translatable="yes">Accept</property>
55 <property name="visible">True</property>
56 <property name="can-focus">True</property>
57 <property name="receives-default">True</property>
58 </object>
59 <packing>
60 <property name="expand">True</property>
61 <property name="fill">True</property>
62 <property name="position">1</property>
63 </packing>
64 </child>
65 </object>
66 <packing>
67 <property name="expand">False</property>
68 <property name="fill">False</property>
69 <property name="position">0</property>
70 </packing>
71 </child>
72 <child>
73 <object class="GtkBox">
74 <property name="visible">True</property>
75 <property name="can-focus">False</property>
76 <property name="halign">center</property>
77 <property name="margin-start">8</property>
78 <property name="margin-end">8</property>
79 <property name="margin-top">8</property>
80 <property name="margin-bottom">8</property>
81 <property name="orientation">vertical</property>
82 <property name="spacing">4</property>
83 <child>
84 <object class="GtkDrawingArea" id="id_drawing_area">
85 <property name="height-request">250</property>
86 <property name="visible">True</property>
87 <property name="can-focus">False</property>
88 </object>
89 <packing>
90 <property name="expand">True</property>
91 <property name="fill">True</property>
92 <property name="position">0</property>
93 </packing>
94 </child>
95 <child>
96 <object class="GtkLabel">
97 <property name="visible">True</property>
98 <property name="can-focus">False</property>
99 <property name="label" translatable="yes">ID:</property>
100 <property name="xalign">0</property>
101 </object>
102 <packing>
103 <property name="expand">False</property>
104 <property name="fill">True</property>
105 <property name="position">1</property>
106 </packing>
107 </child>
108 <child>
109 <object class="GtkEntry" id="id_entry">
110 <property name="width-request">250</property>
111 <property name="visible">True</property>
112 <property name="can-focus">True</property>
113 <property name="editable">False</property>
114 </object>
115 <packing>
116 <property name="expand">False</property>
117 <property name="fill">True</property>
118 <property name="position">2</property>
119 </packing>
120 </child>
121 </object>
122 <packing>
123 <property name="expand">False</property>
124 <property name="fill">True</property>
125 <property name="position">1</property>
126 </packing>
127 </child>
128 </object>
129 </child>
130 </object>
131</interface>
diff --git a/resources/ui/new_platform.ui b/resources/ui/new_platform.ui
index 80ff925..4b3fa8f 100644
--- a/resources/ui/new_platform.ui
+++ b/resources/ui/new_platform.ui
@@ -23,8 +23,9 @@ Author: Tobias Frisch
23<interface> 23<interface>
24 <requires lib="gtk+" version="3.24"/> 24 <requires lib="gtk+" version="3.24"/>
25 <requires lib="libhandy" version="1.2"/> 25 <requires lib="libhandy" version="1.2"/>
26 <object class="GtkDialog" id="platform_dialog"> 26 <object class="GtkDialog" id="new_platform_dialog">
27 <property name="can-focus">False</property> 27 <property name="can-focus">False</property>
28 <property name="modal">True</property>
28 <property name="window-position">center-on-parent</property> 29 <property name="window-position">center-on-parent</property>
29 <property name="type-hint">dialog</property> 30 <property name="type-hint">dialog</property>
30 <child internal-child="vbox"> 31 <child internal-child="vbox">
diff --git a/src/application.h b/src/application.h
index ff9875d..9601ac5 100644
--- a/src/application.h
+++ b/src/application.h
@@ -30,6 +30,7 @@
30#include "chat/messenger.h" 30#include "chat/messenger.h"
31 31
32#include "ui/messenger.h" 32#include "ui/messenger.h"
33#include "ui/new_contact.h"
33#include "ui/new_platform.h" 34#include "ui/new_platform.h"
34 35
35#include "util.h" 36#include "util.h"
@@ -65,6 +66,7 @@ typedef struct MESSENGER_Application
65 66
66 UI_MESSENGER_Handle messenger; 67 UI_MESSENGER_Handle messenger;
67 68
69 UI_NEW_CONTACT_Handle new_contact;
68 UI_NEW_PLATFORM_Handle new_platform; 70 UI_NEW_PLATFORM_Handle new_platform;
69 } ui; 71 } ui;
70} MESSENGER_Application; 72} MESSENGER_Application;
diff --git a/src/ui/messenger.c b/src/ui/messenger.c
index 70d71b3..3de94de 100644
--- a/src/ui/messenger.c
+++ b/src/ui/messenger.c
@@ -28,6 +28,7 @@
28 28
29#include "chat_entry.h" 29#include "chat_entry.h"
30#include "message.h" 30#include "message.h"
31#include "new_contact.h"
31#include "new_platform.h" 32#include "new_platform.h"
32#include "../application.h" 33#include "../application.h"
33 34
@@ -67,6 +68,19 @@ handle_account_details_button_click(UNUSED GtkButton* button,
67} 68}
68 69
69static void 70static void
71handle_new_contact_button_click(UNUSED GtkButton* button,
72 gpointer user_data)
73{
74 MESSENGER_Application *app = (MESSENGER_Application*) user_data;
75
76 hdy_flap_set_reveal_flap(HDY_FLAP(app->ui.messenger.flap_user_details), FALSE);
77
78 ui_new_contact_dialog_init(app, &(app->ui.new_contact));
79
80 gtk_widget_show(GTK_WIDGET(app->ui.new_contact.dialog));
81}
82
83static void
70handle_new_platform_button_click(UNUSED GtkButton* button, 84handle_new_platform_button_click(UNUSED GtkButton* button,
71 gpointer user_data) 85 gpointer user_data)
72{ 86{
@@ -76,7 +90,7 @@ handle_new_platform_button_click(UNUSED GtkButton* button,
76 90
77 ui_new_platform_dialog_init(app, &(app->ui.new_platform)); 91 ui_new_platform_dialog_init(app, &(app->ui.new_platform));
78 92
79 gtk_widget_show(GTK_WIDGET(app->ui.new_platform.platform_dialog)); 93 gtk_widget_show(GTK_WIDGET(app->ui.new_platform.dialog));
80} 94}
81 95
82static void 96static void
@@ -226,6 +240,13 @@ ui_messenger_init(MESSENGER_Application *app,
226 ); 240 );
227 241
228 g_signal_connect( 242 g_signal_connect(
243 handle->new_contact_button,
244 "clicked",
245 G_CALLBACK(handle_new_contact_button_click),
246 app
247 );
248
249 g_signal_connect(
229 handle->new_platform_button, 250 handle->new_platform_button,
230 "clicked", 251 "clicked",
231 G_CALLBACK(handle_new_platform_button_click), 252 G_CALLBACK(handle_new_platform_button_click),
diff --git a/src/ui/new_contact.c b/src/ui/new_contact.c
new file mode 100644
index 0000000..f9cd215
--- /dev/null
+++ b/src/ui/new_contact.c
@@ -0,0 +1,266 @@
1/*
2 This file is part of GNUnet.
3 Copyright (C) 2021 GNUnet e.V.
4
5 GNUnet is free software: you can redistribute it and/or modify it
6 under the terms of the GNU Affero General Public License as published
7 by the Free Software Foundation, either version 3 of the License,
8 or (at your option) any later version.
9
10 GNUnet is distributed in the hope that it will be useful, but
11 WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 Affero General Public License for more details.
14
15 You should have received a copy of the GNU Affero General Public License
16 along with this program. If not, see <http://www.gnu.org/licenses/>.
17
18 SPDX-License-Identifier: AGPL3.0-or-later
19 */
20/*
21 * @author Tobias Frisch
22 * @file ui/new_platform.h
23 */
24
25#include "new_contact.h"
26
27#include "../application.h"
28
29static void
30handle_cancel_button_click(UNUSED GtkButton *button,
31 gpointer user_data)
32{
33 GtkDialog *dialog = GTK_DIALOG(user_data);
34 gtk_window_close(GTK_WINDOW(dialog));
35}
36
37static void
38handle_confirm_button_click(UNUSED GtkButton *button,
39 gpointer user_data)
40{
41 MESSENGER_Application *app = (MESSENGER_Application*) user_data;
42
43 // TODO: Add new contact
44
45 gtk_window_close(GTK_WINDOW(app->ui.new_contact.dialog));
46}
47
48static void
49handle_dialog_destroy(UNUSED GtkWidget *window,
50 gpointer user_data)
51{
52 ui_new_contact_dialog_cleanup((UI_NEW_CONTACT_Handle*) user_data);
53}
54
55static gboolean
56handle_id_drawing_area_draw(GtkWidget* drawing_area,
57 cairo_t* cairo,
58 gpointer user_data)
59{
60 UI_NEW_CONTACT_Handle *handle = (UI_NEW_CONTACT_Handle*) user_data;
61
62 GtkStyleContext* context = gtk_widget_get_style_context(drawing_area);
63
64 const guint width = gtk_widget_get_allocated_width(drawing_area);
65 const guint height = gtk_widget_get_allocated_height(drawing_area);
66
67 gtk_render_background(context, cairo, 0, 0, width, height);
68
69 GdkPixbuf *image = NULL;
70
71 if (handle->image)
72 {
73 uint w, h;
74 zbar_image_get_size(handle->image, &w, &h);
75
76 const void* data = zbar_image_get_data(handle->image);
77
78 image = gdk_pixbuf_new_from_data(
79 data,
80 GDK_COLORSPACE_RGB,
81 FALSE,
82 8,
83 w,
84 h,
85 w * 3,
86 NULL,
87 NULL
88 );
89 }
90
91 if (!image)
92 return FALSE;
93
94 int dwidth = gdk_pixbuf_get_width(image);
95 int dheight = gdk_pixbuf_get_height(image);
96
97 double ratio_width = 1.0 * width / dwidth;
98 double ratio_height = 1.0 * height / dheight;
99
100 const double ratio = ratio_width < ratio_height? ratio_width : ratio_height;
101
102 dwidth = (int) (dwidth * ratio);
103 dheight = (int) (dheight * ratio);
104
105 double dx = (width - dwidth) * 0.5;
106 double dy = (height - dheight) * 0.5;
107
108 const int interp_type = (ratio >= 1.0?
109 GDK_INTERP_NEAREST :
110 GDK_INTERP_BILINEAR
111 );
112
113 GdkPixbuf* scaled = gdk_pixbuf_scale_simple(
114 image,
115 dwidth,
116 dheight,
117 interp_type
118 );
119
120 gtk_render_icon(context, cairo, scaled, dx, dy);
121
122 cairo_fill(cairo);
123
124 g_object_unref(scaled);
125 g_object_unref(image);
126
127 zbar_image_destroy(handle->image);
128 handle->image = NULL;
129
130 return FALSE;
131}
132
133static gboolean
134idle_video_processing(gpointer user_data)
135{
136 UI_NEW_CONTACT_Handle *handle = (UI_NEW_CONTACT_Handle*) user_data;
137
138 if (0 == handle->idle_processing)
139 return FALSE;
140
141 zbar_image_t *image = zbar_video_next_image(handle->video);
142
143 if (!image)
144 return TRUE;
145
146 zbar_image_t *rgb = zbar_image_convert(
147 image,
148 zbar_fourcc('R', 'G', 'B', '3')
149 );
150
151 if (!rgb)
152 goto cleanup_image;
153
154 if (handle->image)
155 zbar_image_destroy(handle->image);
156
157 handle->image = rgb;
158
159 if (handle->id_drawing_area)
160 gtk_widget_queue_draw(GTK_WIDGET(handle->id_drawing_area));
161
162cleanup_image:
163 zbar_image_destroy(image);
164 return TRUE;
165}
166
167static void*
168_ui_new_contact_video_thread(void *args)
169{
170 UI_NEW_CONTACT_Handle *handle = (UI_NEW_CONTACT_Handle*) args;
171
172 if (0 != zbar_video_open(handle->video, "/dev/video0"))
173 return NULL;
174
175 if (0 != zbar_video_enable(handle->video, 1))
176 return NULL;
177
178 handle->idle_processing = g_idle_add(idle_video_processing, handle);
179 return NULL;
180}
181
182void
183ui_new_contact_dialog_init(MESSENGER_Application *app,
184 UI_NEW_CONTACT_Handle *handle)
185{
186 handle->video = zbar_video_create();
187 handle->scanner = zbar_image_scanner_create();
188
189 pthread_create(&(handle->video_tid), NULL, _ui_new_contact_video_thread, handle);
190
191 GtkBuilder* builder = gtk_builder_new_from_file("resources/ui/new_contact.ui");
192
193 handle->dialog = GTK_DIALOG(
194 gtk_builder_get_object(builder, "new_contact_dialog")
195 );
196
197 gtk_window_set_title(
198 GTK_WINDOW(handle->dialog),
199 "New Contact"
200 );
201
202 gtk_window_set_transient_for(
203 GTK_WINDOW(handle->dialog),
204 GTK_WINDOW(app->ui.messenger.main_window)
205 );
206
207 handle->id_drawing_area = GTK_DRAWING_AREA(
208 gtk_builder_get_object(builder, "id_drawing_area")
209 );
210
211 g_signal_connect(
212 handle->id_drawing_area,
213 "draw",
214 G_CALLBACK(handle_id_drawing_area_draw),
215 handle
216 );
217
218 handle->id_entry = GTK_ENTRY(
219 gtk_builder_get_object(builder, "platform_entry")
220 );
221
222 handle->cancel_button = GTK_BUTTON(
223 gtk_builder_get_object(builder, "cancel_button")
224 );
225
226 g_signal_connect(
227 handle->cancel_button,
228 "clicked",
229 G_CALLBACK(handle_cancel_button_click),
230 handle->dialog
231 );
232
233 handle->confirm_button = GTK_BUTTON(
234 gtk_builder_get_object(builder, "confirm_button")
235 );
236
237 g_signal_connect(
238 handle->confirm_button,
239 "clicked",
240 G_CALLBACK(handle_confirm_button_click),
241 app
242 );
243
244 g_signal_connect(
245 handle->dialog,
246 "destroy",
247 G_CALLBACK(handle_dialog_destroy),
248 handle
249 );
250
251 handle->idle_processing = 0;
252}
253
254void
255ui_new_contact_dialog_cleanup(UI_NEW_CONTACT_Handle *handle)
256{
257 pthread_join(handle->video_tid, NULL);
258
259 if (0 != handle->idle_processing)
260 g_source_remove(handle->idle_processing);
261
262 handle->idle_processing = 0;
263
264 zbar_image_scanner_destroy(handle->scanner);
265 zbar_video_destroy(handle->video);
266}
diff --git a/src/ui/new_contact.h b/src/ui/new_contact.h
new file mode 100644
index 0000000..760c32d
--- /dev/null
+++ b/src/ui/new_contact.h
@@ -0,0 +1,59 @@
1/*
2 This file is part of GNUnet.
3 Copyright (C) 2021 GNUnet e.V.
4
5 GNUnet is free software: you can redistribute it and/or modify it
6 under the terms of the GNU Affero General Public License as published
7 by the Free Software Foundation, either version 3 of the License,
8 or (at your option) any later version.
9
10 GNUnet is distributed in the hope that it will be useful, but
11 WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 Affero General Public License for more details.
14
15 You should have received a copy of the GNU Affero General Public License
16 along with this program. If not, see <http://www.gnu.org/licenses/>.
17
18 SPDX-License-Identifier: AGPL3.0-or-later
19 */
20/*
21 * @author Tobias Frisch
22 * @file ui/new_contact.h
23 */
24
25#ifndef UI_NEW_CONTACT_H_
26#define UI_NEW_CONTACT_H_
27
28#include "messenger.h"
29
30#include <gdk/gdkpixbuf.h>
31#include <pthread.h>
32#include <zbar.h>
33
34typedef struct UI_NEW_CONTACT_Handle
35{
36 zbar_video_t *video;
37 zbar_image_t *image;
38 zbar_image_scanner_t *scanner;
39
40 GtkDialog* dialog;
41
42 GtkDrawingArea* id_drawing_area;
43 GtkEntry* id_entry;
44
45 GtkButton* cancel_button;
46 GtkButton* confirm_button;
47
48 pthread_t video_tid;
49 guint idle_processing;
50} UI_NEW_CONTACT_Handle;
51
52void
53ui_new_contact_dialog_init(MESSENGER_Application *app,
54 UI_NEW_CONTACT_Handle *handle);
55
56void
57ui_new_contact_dialog_cleanup(UI_NEW_CONTACT_Handle *handle);
58
59#endif /* UI_NEW_CONTACT_H_ */
diff --git a/src/ui/new_platform.c b/src/ui/new_platform.c
index e4f8c4a..0eb0ced 100644
--- a/src/ui/new_platform.c
+++ b/src/ui/new_platform.c
@@ -67,7 +67,7 @@ handle_platform_entry_activate(GtkEntry *entry,
67 67
68 _open_new_platform(entry, app); 68 _open_new_platform(entry, app);
69 69
70 gtk_window_close(GTK_WINDOW(app->ui.new_platform.platform_dialog)); 70 gtk_window_close(GTK_WINDOW(app->ui.new_platform.dialog));
71} 71}
72 72
73static void 73static void
@@ -86,7 +86,7 @@ handle_confirm_button_click(UNUSED GtkButton *button,
86 86
87 _open_new_platform(app->ui.new_platform.platform_entry, app); 87 _open_new_platform(app->ui.new_platform.platform_entry, app);
88 88
89 gtk_window_close(GTK_WINDOW(app->ui.new_platform.platform_dialog)); 89 gtk_window_close(GTK_WINDOW(app->ui.new_platform.dialog));
90} 90}
91 91
92void 92void
@@ -95,22 +95,20 @@ ui_new_platform_dialog_init(MESSENGER_Application *app,
95{ 95{
96 GtkBuilder* builder = gtk_builder_new_from_file("resources/ui/new_platform.ui"); 96 GtkBuilder* builder = gtk_builder_new_from_file("resources/ui/new_platform.ui");
97 97
98 handle->platform_dialog = GTK_DIALOG( 98 handle->dialog = GTK_DIALOG(
99 gtk_builder_get_object(builder, "platform_dialog") 99 gtk_builder_get_object(builder, "new_platform_dialog")
100 ); 100 );
101 101
102 gtk_window_set_title( 102 gtk_window_set_title(
103 GTK_WINDOW(handle->platform_dialog), 103 GTK_WINDOW(handle->dialog),
104 "New Platform" 104 "New Platform"
105 ); 105 );
106 106
107 gtk_window_set_transient_for( 107 gtk_window_set_transient_for(
108 GTK_WINDOW(handle->platform_dialog), 108 GTK_WINDOW(handle->dialog),
109 GTK_WINDOW(app->ui.messenger.main_window) 109 GTK_WINDOW(app->ui.messenger.main_window)
110 ); 110 );
111 111
112 gtk_window_set_modal(GTK_WINDOW(handle->platform_dialog), TRUE);
113
114 handle->platform_avatar = HDY_AVATAR( 112 handle->platform_avatar = HDY_AVATAR(
115 gtk_builder_get_object(builder, "platform_avatar") 113 gtk_builder_get_object(builder, "platform_avatar")
116 ); 114 );
@@ -145,7 +143,7 @@ ui_new_platform_dialog_init(MESSENGER_Application *app,
145 handle->cancel_button, 143 handle->cancel_button,
146 "clicked", 144 "clicked",
147 G_CALLBACK(handle_cancel_button_click), 145 G_CALLBACK(handle_cancel_button_click),
148 handle->platform_dialog 146 handle->dialog
149 ); 147 );
150 148
151 handle->confirm_button = GTK_BUTTON( 149 handle->confirm_button = GTK_BUTTON(
diff --git a/src/ui/new_platform.h b/src/ui/new_platform.h
index 745c4de..12fcbe3 100644
--- a/src/ui/new_platform.h
+++ b/src/ui/new_platform.h
@@ -29,7 +29,7 @@
29 29
30typedef struct UI_NEW_PLATFORM_Handle 30typedef struct UI_NEW_PLATFORM_Handle
31{ 31{
32 GtkDialog* platform_dialog; 32 GtkDialog* dialog;
33 33
34 HdyAvatar* platform_avatar; 34 HdyAvatar* platform_avatar;
35 GtkFileChooserButton* platform_avatar_file; 35 GtkFileChooserButton* platform_avatar_file;