aboutsummaryrefslogtreecommitdiff
path: root/src/ui/new_contact.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/ui/new_contact.c')
-rw-r--r--src/ui/new_contact.c266
1 files changed, 266 insertions, 0 deletions
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}