Skip to content
GitLab
Projects
Groups
Snippets
Help
Loading...
Help
What's new
10
Help
Support
Community forum
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in / Register
Toggle navigation
Open sidebar
Vasily Khoruzhick
libfprint
Commits
29461fa9
Commit
29461fa9
authored
Oct 08, 2018
by
Bastien Nocera
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
demo: Add GTK+ test application
parent
f7173e66
Changes
8
Hide whitespace changes
Inline
Side-by-side
Showing
8 changed files
with
1127 additions
and
0 deletions
+1127
-0
demo/gtk-libfprint-test.c
demo/gtk-libfprint-test.c
+514
-0
demo/gtk-libfprint-test.gresource.xml
demo/gtk-libfprint-test.gresource.xml
+6
-0
demo/gtk-libfprint-test.ui
demo/gtk-libfprint-test.ui
+351
-0
demo/loop.c
demo/loop.c
+196
-0
demo/loop.h
demo/loop.h
+27
-0
demo/meson.build
demo/meson.build
+17
-0
meson.build
meson.build
+12
-0
meson_options.txt
meson_options.txt
+4
-0
No files found.
demo/gtk-libfprint-test.c
0 → 100644
View file @
29461fa9
/*
* Example libfprint GTK+ image capture program
* Copyright (C) 2018 Bastien Nocera <hadess@hadess.net>
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/
#include "config.h"
#include <gtk/gtk.h>
#include <libfprint/fprint.h>
#include "loop.h"
typedef
GtkApplication
LibfprintDemo
;
typedef
GtkApplicationClass
LibfprintDemoClass
;
G_DEFINE_TYPE
(
LibfprintDemo
,
libfprint_demo
,
GTK_TYPE_APPLICATION
)
typedef
enum
{
IMAGE_DISPLAY_NONE
=
0
,
IMAGE_DISPLAY_MINUTIAE
=
1
<<
0
,
IMAGE_DISPLAY_BINARY
=
1
<<
1
}
ImageDisplayFlags
;
typedef
struct
{
GtkApplicationWindow
parent_instance
;
GtkWidget
*
header_bar
;
GtkWidget
*
mode_stack
;
GtkWidget
*
capture_button
;
GtkWidget
*
capture_image
;
GtkWidget
*
spinner
;
GtkWidget
*
instructions
;
struct
fp_dscv_dev
*
ddev
;
struct
fp_dev
*
dev
;
struct
fp_img
*
img
;
ImageDisplayFlags
img_flags
;
}
LibfprintDemoWindow
;
typedef
GtkApplicationWindowClass
LibfprintDemoWindowClass
;
G_DEFINE_TYPE
(
LibfprintDemoWindow
,
libfprint_demo_window
,
GTK_TYPE_APPLICATION_WINDOW
)
typedef
enum
{
EMPTY_MODE
,
NOIMAGING_MODE
,
CAPTURE_MODE
,
SPINNER_MODE
,
ERROR_MODE
}
LibfprintDemoMode
;
static
void
libfprint_demo_set_mode
(
LibfprintDemoWindow
*
win
,
LibfprintDemoMode
mode
);
static
void
pixbuf_destroy
(
guchar
*
pixels
,
gpointer
data
)
{
if
(
pixels
==
NULL
)
return
;
g_free
(
pixels
);
}
static
unsigned
char
*
img_to_rgbdata
(
struct
fp_img
*
img
,
int
width
,
int
height
)
{
int
size
=
width
*
height
;
unsigned
char
*
imgdata
=
fp_img_get_data
(
img
);
unsigned
char
*
rgbdata
=
g_malloc
(
size
*
3
);
size_t
i
;
size_t
rgb_offset
=
0
;
for
(
i
=
0
;
i
<
size
;
i
++
)
{
unsigned
char
pixel
=
imgdata
[
i
];
rgbdata
[
rgb_offset
++
]
=
pixel
;
rgbdata
[
rgb_offset
++
]
=
pixel
;
rgbdata
[
rgb_offset
++
]
=
pixel
;
}
return
rgbdata
;
}
static
void
plot_minutiae
(
unsigned
char
*
rgbdata
,
int
width
,
int
height
,
struct
fp_minutia
**
minlist
,
int
nr_minutiae
)
{
int
i
;
#define write_pixel(num) do { \
rgbdata[((num) * 3)] = 0xff; \
rgbdata[((num) * 3) + 1] = 0; \
rgbdata[((num) * 3) + 2] = 0; \
} while(0)
for
(
i
=
0
;
i
<
nr_minutiae
;
i
++
)
{
struct
fp_minutia
*
min
=
minlist
[
i
];
int
x
,
y
;
size_t
pixel_offset
;
fp_minutia_get_coords
(
min
,
&
x
,
&
y
);
pixel_offset
=
(
y
*
width
)
+
x
;
write_pixel
(
pixel_offset
-
2
);
write_pixel
(
pixel_offset
-
1
);
write_pixel
(
pixel_offset
);
write_pixel
(
pixel_offset
+
1
);
write_pixel
(
pixel_offset
+
2
);
write_pixel
(
pixel_offset
-
(
width
*
2
));
write_pixel
(
pixel_offset
-
(
width
*
1
)
-
1
);
write_pixel
(
pixel_offset
-
(
width
*
1
));
write_pixel
(
pixel_offset
-
(
width
*
1
)
+
1
);
write_pixel
(
pixel_offset
+
(
width
*
1
)
-
1
);
write_pixel
(
pixel_offset
+
(
width
*
1
));
write_pixel
(
pixel_offset
+
(
width
*
1
)
+
1
);
write_pixel
(
pixel_offset
+
(
width
*
2
));
}
}
static
GdkPixbuf
*
img_to_pixbuf
(
struct
fp_img
*
img
,
ImageDisplayFlags
flags
)
{
int
width
;
int
height
;
unsigned
char
*
rgbdata
;
width
=
fp_img_get_width
(
img
);
height
=
fp_img_get_height
(
img
);
if
(
flags
&
IMAGE_DISPLAY_BINARY
)
{
struct
fp_img
*
binary
;
binary
=
fp_img_binarize
(
img
);
rgbdata
=
img_to_rgbdata
(
binary
,
width
,
height
);
fp_img_free
(
binary
);
}
else
{
rgbdata
=
img_to_rgbdata
(
img
,
width
,
height
);
}
if
(
flags
&
IMAGE_DISPLAY_MINUTIAE
)
{
struct
fp_minutia
**
minlist
;
int
nr_minutiae
;
minlist
=
fp_img_get_minutiae
(
img
,
&
nr_minutiae
);
plot_minutiae
(
rgbdata
,
width
,
height
,
minlist
,
nr_minutiae
);
}
return
gdk_pixbuf_new_from_data
(
rgbdata
,
GDK_COLORSPACE_RGB
,
FALSE
,
8
,
width
,
height
,
width
*
3
,
pixbuf_destroy
,
NULL
);
}
static
void
update_image
(
LibfprintDemoWindow
*
win
)
{
GdkPixbuf
*
pixbuf
;
if
(
win
->
img
==
NULL
)
{
gtk_image_clear
(
GTK_IMAGE
(
win
->
capture_image
));
return
;
}
g_debug
(
"Updating image, minutiae %s, binary mode %s"
,
win
->
img_flags
&
IMAGE_DISPLAY_MINUTIAE
?
"shown"
:
"hidden"
,
win
->
img_flags
&
IMAGE_DISPLAY_BINARY
?
"on"
:
"off"
);
pixbuf
=
img_to_pixbuf
(
win
->
img
,
win
->
img_flags
);
gtk_image_set_from_pixbuf
(
GTK_IMAGE
(
win
->
capture_image
),
pixbuf
);
g_object_unref
(
pixbuf
);
}
static
void
libfprint_demo_set_spinner_label
(
LibfprintDemoWindow
*
win
,
const
char
*
message
)
{
char
*
label
;
label
=
g_strdup_printf
(
"<b><span size=
\"
large
\"
>%s</span></b>"
,
message
);
gtk_label_set_markup
(
GTK_LABEL
(
win
->
instructions
),
label
);
g_free
(
label
);
}
static
void
libfprint_demo_set_capture_label
(
LibfprintDemoWindow
*
win
)
{
struct
fp_driver
*
drv
;
enum
fp_scan_type
scan_type
;
const
char
*
message
;
drv
=
fp_dscv_dev_get_driver
(
win
->
ddev
);
scan_type
=
fp_driver_get_scan_type
(
drv
);
switch
(
scan_type
)
{
case
FP_SCAN_TYPE_PRESS
:
message
=
"Place your finger on the fingerprint reader"
;
break
;
case
FP_SCAN_TYPE_SWIPE
:
message
=
"Swipe your finger across the fingerprint reader"
;
break
;
default:
g_assert_not_reached
();
}
libfprint_demo_set_spinner_label
(
win
,
message
);
}
static
void
dev_capture_start_cb
(
struct
fp_dev
*
dev
,
int
result
,
struct
fp_img
*
img
,
void
*
user_data
)
{
LibfprintDemoWindow
*
win
=
user_data
;
if
(
result
<
0
)
{
libfprint_demo_set_mode
(
win
,
ERROR_MODE
);
return
;
}
fp_async_capture_stop
(
dev
,
NULL
,
NULL
);
win
->
img
=
img
;
update_image
(
win
);
libfprint_demo_set_mode
(
win
,
CAPTURE_MODE
);
}
static
void
dev_open_cb
(
struct
fp_dev
*
dev
,
int
status
,
void
*
user_data
)
{
LibfprintDemoWindow
*
win
=
user_data
;
int
r
;
if
(
status
<
0
)
{
libfprint_demo_set_mode
(
win
,
ERROR_MODE
);
return
;
}
libfprint_demo_set_capture_label
(
win
);
win
->
dev
=
dev
;
r
=
fp_async_capture_start
(
win
->
dev
,
FALSE
,
dev_capture_start_cb
,
user_data
);
if
(
r
<
0
)
{
g_warning
(
"fp_async_capture_start failed: %d"
,
r
);
libfprint_demo_set_mode
(
win
,
ERROR_MODE
);
return
;
}
}
static
void
activate_capture
(
GSimpleAction
*
action
,
GVariant
*
parameter
,
gpointer
user_data
)
{
LibfprintDemoWindow
*
win
=
user_data
;
int
r
;
libfprint_demo_set_mode
(
win
,
SPINNER_MODE
);
g_clear_pointer
(
&
win
->
img
,
fp_img_free
);
if
(
win
->
dev
!=
NULL
)
{
dev_open_cb
(
win
->
dev
,
0
,
user_data
);
return
;
}
libfprint_demo_set_spinner_label
(
win
,
"Opening fingerprint reader"
);
r
=
fp_async_dev_open
(
win
->
ddev
,
dev_open_cb
,
user_data
);
if
(
r
<
0
)
{
g_warning
(
"fp_async_dev_open failed: %d"
,
r
);
libfprint_demo_set_mode
(
win
,
ERROR_MODE
);
return
;
}
}
static
void
activate_quit
(
GSimpleAction
*
action
,
GVariant
*
parameter
,
gpointer
user_data
)
{
GtkApplication
*
app
=
user_data
;
GtkWidget
*
win
;
GList
*
list
,
*
next
;
list
=
gtk_application_get_windows
(
app
);
while
(
list
)
{
win
=
list
->
data
;
next
=
list
->
next
;
gtk_widget_destroy
(
GTK_WIDGET
(
win
));
list
=
next
;
}
}
static
void
activate_show_minutiae
(
GSimpleAction
*
action
,
GVariant
*
parameter
,
gpointer
user_data
)
{
LibfprintDemoWindow
*
win
=
user_data
;
GVariant
*
state
;
gboolean
new_state
;
state
=
g_action_get_state
(
G_ACTION
(
action
));
new_state
=
!
g_variant_get_boolean
(
state
);
g_action_change_state
(
G_ACTION
(
action
),
g_variant_new_boolean
(
new_state
));
g_variant_unref
(
state
);
if
(
new_state
)
win
->
img_flags
|=
IMAGE_DISPLAY_MINUTIAE
;
else
win
->
img_flags
&=
~
IMAGE_DISPLAY_MINUTIAE
;
update_image
(
win
);
}
static
void
activate_show_binary
(
GSimpleAction
*
action
,
GVariant
*
parameter
,
gpointer
user_data
)
{
LibfprintDemoWindow
*
win
=
user_data
;
GVariant
*
state
;
gboolean
new_state
;
state
=
g_action_get_state
(
G_ACTION
(
action
));
new_state
=
!
g_variant_get_boolean
(
state
);
g_action_change_state
(
G_ACTION
(
action
),
g_variant_new_boolean
(
new_state
));
g_variant_unref
(
state
);
if
(
new_state
)
win
->
img_flags
|=
IMAGE_DISPLAY_BINARY
;
else
win
->
img_flags
&=
~
IMAGE_DISPLAY_BINARY
;
update_image
(
win
);
}
static
void
change_show_minutiae_state
(
GSimpleAction
*
action
,
GVariant
*
state
,
gpointer
user_data
)
{
g_simple_action_set_state
(
action
,
state
);
}
static
void
change_show_binary_state
(
GSimpleAction
*
action
,
GVariant
*
state
,
gpointer
user_data
)
{
g_simple_action_set_state
(
action
,
state
);
}
static
GActionEntry
app_entries
[]
=
{
{
"quit"
,
activate_quit
,
NULL
,
NULL
,
NULL
},
};
static
GActionEntry
win_entries
[]
=
{
{
"show-minutiae"
,
activate_show_minutiae
,
NULL
,
"false"
,
change_show_minutiae_state
},
{
"show-binary"
,
activate_show_binary
,
NULL
,
"false"
,
change_show_binary_state
},
{
"capture"
,
activate_capture
,
NULL
,
NULL
,
NULL
}
};
static
void
activate
(
GApplication
*
app
)
{
LibfprintDemoWindow
*
window
;
window
=
g_object_new
(
libfprint_demo_window_get_type
(),
"application"
,
app
,
NULL
);
gtk_widget_show
(
GTK_WIDGET
(
window
));
}
static
void
libfprint_demo_set_mode
(
LibfprintDemoWindow
*
win
,
LibfprintDemoMode
mode
)
{
struct
fp_driver
*
drv
;
char
*
title
;
switch
(
mode
)
{
case
EMPTY_MODE
:
gtk_stack_set_visible_child_name
(
GTK_STACK
(
win
->
mode_stack
),
"empty-mode"
);
gtk_widget_set_sensitive
(
win
->
capture_button
,
FALSE
);
gtk_spinner_stop
(
GTK_SPINNER
(
win
->
spinner
));
break
;
case
NOIMAGING_MODE
:
gtk_stack_set_visible_child_name
(
GTK_STACK
(
win
->
mode_stack
),
"noimaging-mode"
);
gtk_widget_set_sensitive
(
win
->
capture_button
,
FALSE
);
gtk_spinner_stop
(
GTK_SPINNER
(
win
->
spinner
));
break
;
case
CAPTURE_MODE
:
gtk_stack_set_visible_child_name
(
GTK_STACK
(
win
->
mode_stack
),
"capture-mode"
);
gtk_widget_set_sensitive
(
win
->
capture_button
,
TRUE
);
drv
=
fp_dscv_dev_get_driver
(
win
->
ddev
);
title
=
g_strdup_printf
(
"%s Test"
,
fp_driver_get_full_name
(
drv
));
gtk_header_bar_set_title
(
GTK_HEADER_BAR
(
win
->
header_bar
),
title
);
g_free
(
title
);
gtk_spinner_stop
(
GTK_SPINNER
(
win
->
spinner
));
break
;
case
SPINNER_MODE
:
gtk_stack_set_visible_child_name
(
GTK_STACK
(
win
->
mode_stack
),
"spinner-mode"
);
gtk_widget_set_sensitive
(
win
->
capture_button
,
FALSE
);
gtk_spinner_start
(
GTK_SPINNER
(
win
->
spinner
));
break
;
case
ERROR_MODE
:
gtk_stack_set_visible_child_name
(
GTK_STACK
(
win
->
mode_stack
),
"error-mode"
);
gtk_widget_set_sensitive
(
win
->
capture_button
,
FALSE
);
gtk_spinner_stop
(
GTK_SPINNER
(
win
->
spinner
));
break
;
default:
g_assert_not_reached
();
}
}
static
void
libfprint_demo_init
(
LibfprintDemo
*
app
)
{
g_action_map_add_action_entries
(
G_ACTION_MAP
(
app
),
app_entries
,
G_N_ELEMENTS
(
app_entries
),
app
);
}
static
void
libfprint_demo_class_init
(
LibfprintDemoClass
*
class
)
{
GApplicationClass
*
app_class
=
G_APPLICATION_CLASS
(
class
);
app_class
->
activate
=
activate
;
}
static
void
libfprint_demo_window_init
(
LibfprintDemoWindow
*
window
)
{
struct
fp_dscv_dev
**
discovered_devs
;
gtk_widget_init_template
(
GTK_WIDGET
(
window
));
gtk_window_set_default_size
(
GTK_WINDOW
(
window
),
700
,
500
);
g_action_map_add_action_entries
(
G_ACTION_MAP
(
window
),
win_entries
,
G_N_ELEMENTS
(
win_entries
),
window
);
if
(
fp_init
()
<
0
)
{
libfprint_demo_set_mode
(
window
,
ERROR_MODE
);
return
;
}
setup_pollfds
();
discovered_devs
=
fp_discover_devs
();
if
(
!
discovered_devs
)
return
;
if
(
!
fp_driver_supports_imaging
(
fp_dscv_dev_get_driver
(
discovered_devs
[
0
])))
{
libfprint_demo_set_mode
(
window
,
NOIMAGING_MODE
);
return
;
}
window
->
ddev
=
discovered_devs
[
0
];
libfprint_demo_set_mode
(
window
,
CAPTURE_MODE
);
}
static
void
libfprint_demo_window_class_init
(
LibfprintDemoWindowClass
*
class
)
{
GtkWidgetClass
*
widget_class
=
GTK_WIDGET_CLASS
(
class
);
gtk_widget_class_set_template_from_resource
(
widget_class
,
"/libfprint_demo/gtk-libfprint-test.ui"
);
gtk_widget_class_bind_template_child
(
widget_class
,
LibfprintDemoWindow
,
header_bar
);
gtk_widget_class_bind_template_child
(
widget_class
,
LibfprintDemoWindow
,
mode_stack
);
gtk_widget_class_bind_template_child
(
widget_class
,
LibfprintDemoWindow
,
capture_button
);
gtk_widget_class_bind_template_child
(
widget_class
,
LibfprintDemoWindow
,
capture_image
);
gtk_widget_class_bind_template_child
(
widget_class
,
LibfprintDemoWindow
,
spinner
);
gtk_widget_class_bind_template_child
(
widget_class
,
LibfprintDemoWindow
,
instructions
);
//FIXME setup dispose
}
int
main
(
int
argc
,
char
**
argv
)
{
GtkApplication
*
app
;
app
=
GTK_APPLICATION
(
g_object_new
(
libfprint_demo_get_type
(),
"application-id"
,
"org.freedesktop.libfprint.Demo"
,
"flags"
,
G_APPLICATION_FLAGS_NONE
,
NULL
));
return
g_application_run
(
G_APPLICATION
(
app
),
0
,
NULL
);
}
demo/gtk-libfprint-test.gresource.xml
0 → 100644
View file @
29461fa9
<?xml version="1.0" encoding="UTF-8"?>
<gresources>
<gresource
prefix=
"/libfprint_demo"
>
<file>
gtk-libfprint-test.ui
</file>
</gresource>
</gresources>
demo/gtk-libfprint-test.ui
0 → 100644
View file @
29461fa9
<?xml version="1.0" encoding="UTF-8"?>
<!-- Generated with glade 3.22.1 -->
<interface>
<requires
lib=
"gtk+"
version=
"3.20"
/>
<template
class=
"LibfprintDemoWindow"
parent=
"GtkApplicationWindow"
>
<property
name=
"can_focus"
>
False
</property>
<property
name=
"default_width"
>
500
</property>
<property
name=
"default_height"
>
400
</property>
<property
name=
"show_menubar"
>
False
</property>
<child
type=
"titlebar"
>
<object
class=
"GtkHeaderBar"
id=
"header_bar"
>
<property
name=
"visible"
>
True
</property>
<property
name=
"can_focus"
>
False
</property>
<property
name=
"title"
>
Fingerprint Reader Test
</property>
<property
name=
"subtitle"
>
Capture test
</property>
<property
name=
"show_close_button"
>
True
</property>
<child>
<object
class=
"GtkMenuButton"
id=
"option-menu-button"
>
<property
name=
"visible"
>
True
</property>
<property
name=
"sensitive"
>
False
</property>
<property
name=
"can_focus"
>
True
</property>
<property
name=
"receives_default"
>
False
</property>
<property
name=
"valign"
>
center
</property>
<property
name=
"menu-model"
>
options-menu
</property>
<child>
<object
class=
"GtkImage"
>
<property
name=
"visible"
>
True
</property>
<property
name=
"can_focus"
>
False
</property>
<property
name=
"icon_name"
>
open-menu-symbolic
</property>
</object>
</child>
</object>
<packing>
<property
name=
"pack_type"
>
end
</property>
</packing>
</child>
<child>
<object
class=
"GtkButton"
id=
"capture_button"
>
<property
name=
"visible"
>
True
</property>
<property
name=
"sensitive"
>
False
</property>
<property
name=
"can_focus"
>
True
</property>
<property
name=
"receives_default"
>
False
</property>
<property
name=
"valign"
>
center
</property>
<property
name=
"action_name"
>
win.capture
</property>
<child>
<object
class=
"GtkLabel"
id=
"capture_label"
>
<property
name=
"visible"
>
True
</property>
<property
name=
"can_focus"
>
False
</property>
<property
name=
"label"
translatable=
"yes"
>
_Capture
</property>
<property
name=
"use_underline"
>
True
</property>
</object>
</child>
<style>
<class
name=
"text-button"
/>
</style>
</object>
<packing>
<property
name=
"pack_type"
>
end
</property>
</packing>
</child>
</object>
</child>
<child>
<object
class=
"GtkStack"
id=
"mode_stack"
>
<property
name=
"visible"
>
True
</property>
<property
name=
"can_focus"
>
False
</property>
<child>
<object
class=
"GtkGrid"
id=
"spinner-mode"
>
<property
name=
"visible"
>
True
</property>
<property
name=
"can_focus"
>
False
</property>
<property
name=
"halign"
>
center
</property>
<property
name=
"valign"
>
center
</property>
<property
name=
"hexpand"
>
True
</property>
<property
name=
"vexpand"
>
True
</property>
<property
name=
"orientation"
>
vertical
</property>
<property
name=
"row_spacing"
>
12
</property>
<child>
<object
class=
"GtkSpinner"
id=
"spinner"
>
<property
name=
"visible"
>
True
</property>
<property
name=
"can_focus"
>
False
</property>
<property
name=
"margin_bottom"
>
9
</property>
</object>
<packing>
<property
name=
"left_attach"
>
1
</property>
<property
name=
"top_attach"
>
0
</property>
</packing>
</child>
<child>
<object
class=
"GtkLabel"
id=
"instructions"
>
<property
name=
"visible"
>
True
</property>
<property
name=
"can_focus"
>
False
</property>
<property
name=
"margin_top"
>
9
</property>
<property
name=
"label"
translatable=
"yes"
>
<
b
><
span size="large"
>
Please press finger on reader
<
/span
><
/b
>
</property>
<property
name=
"use_markup"
>
True
</property>
</object>
<packing>
<property
name=
"left_attach"
>
1
</property>
<property
name=
"top_attach"
>
1
</property>
</packing>
</child>