[shotwell] faces: Add private DBus communication
- From: Jens Georg <jensgeorg src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [shotwell] faces: Add private DBus communication
- Date: Mon, 18 Mar 2019 14:24:47 +0000 (UTC)
commit 2bad02a5d634e1ffe9565d105593e4ced9615227
Author: Jens Georg <mail jensge org>
Date: Mon Mar 18 15:20:51 2019 +0100
faces: Add private DBus communication
meson.build | 5 +
meson_options.txt | 1 +
src/AppDirs.vala | 7 +-
src/faces/FaceDetect.vala | 76 +++++++++++---
src/faces/FacesTool.vala | 14 ++-
subprojects/shotwell-facedetect/meson.build | 2 +-
.../shotwell-facedetect/shotwell-facedetect.cpp | 110 ++++++++++++++++++---
7 files changed, 187 insertions(+), 28 deletions(-)
---
diff --git a/meson.build b/meson.build
index a940c9ac..fda28500 100644
--- a/meson.build
+++ b/meson.build
@@ -103,6 +103,11 @@ endif
if get_option('face-detection')
add_global_arguments(['--define=ENABLE_FACES'], language : 'vala')
+
+ if get_option('face_detection_helper_bus') == 'private'
+ add_global_arguments(['--define=FACEDETECT_BUS_PRIVATE'], language : 'vala')
+ endif
+
if get_option('face-detection-helper')
subproject('shotwell-facedetect')
endif
diff --git a/meson_options.txt b/meson_options.txt
index 72fbe5d2..fe15ee75 100644
--- a/meson_options.txt
+++ b/meson_options.txt
@@ -8,4 +8,5 @@ option('udev', type: 'boolean', value : 'true', description: 'Enable or disable
option('install-apport-hook', type : 'boolean', value : 'true', description: 'Enable Ubuntu apport hook')
option('face-detection', type:'boolean', value:false, description: 'Enable face detection and recognition
features')
option('face-detection-helper', type : 'boolean', value : 'true', description : 'If face-detection is
enabled, build the external helper tool')
+option('face_detection_helper_bus', type:'combo', choices: ['private', 'session'], value : 'session',
description: 'Which DBus bus to use for external helper tool')
option('fatal_warnings', type:'boolean', value:false)
diff --git a/src/AppDirs.vala b/src/AppDirs.vala
index 66b1c938..4c4b8c58 100644
--- a/src/AppDirs.vala
+++ b/src/AppDirs.vala
@@ -263,7 +263,7 @@ class AppDirs {
File? install_dir = get_install_dir();
return (install_dir != null) ? install_dir.get_child("share").get_child("shotwell")
- : get_exec_dir();
+ : get_lib_dir();
}
#endif
@@ -332,7 +332,7 @@ class AppDirs {
#if ENABLE_FACES
public static File get_facedetect_bin() {
const string filename = "shotwell-facedetect";
- File f = AppDirs.get_libexec_dir().get_parent().get_child("facedetect").get_child (filename);
+ File f =
AppDirs.get_libexec_dir().get_parent().get_child("subprojects").get_child(filename).get_child (filename);
if (!f.query_exists()) {
f = AppDirs.get_libexec_dir().get_child("shotwell").get_child(filename);
}
@@ -340,7 +340,8 @@ class AppDirs {
}
public static File get_haarcascade_file() {
- File f =
File.new_for_path(AppDirs.get_exec_dir().get_parent().get_parent().get_child("facedetect").get_child("facedetect-haarcascade.xml").get_path());
+ const string filename = "facedetect-haarcascade.xml";
+ var f =
AppDirs.get_resources_dir().get_parent().get_child("subprojects").get_child("shotwell-facedetect").get_child
(filename);
if (f.query_exists()) {//testing meson builddir
return f;
}
diff --git a/src/faces/FaceDetect.vala b/src/faces/FaceDetect.vala
index 618d3a54..4bf6e6af 100644
--- a/src/faces/FaceDetect.vala
+++ b/src/faces/FaceDetect.vala
@@ -33,7 +33,7 @@ public struct FaceRect {
}
[DBus (name = "org.gnome.Shotwell.Faces1")]
-public interface FaceDetectInterface : Object {
+public interface FaceDetectInterface : DBusProxy {
public abstract FaceRect[] detect_faces(string inputName, string cascadeName, double scale, bool infer)
throws IOError, DBusError;
public abstract bool load_net(string netFile)
@@ -53,6 +53,11 @@ public class FaceDetect {
public static FaceDetectInterface interface;
+#if FACEDETECT_BUS_PRIVATE
+ private static GLib.DBusServer dbus_server;
+ private static Subprocess process;
+#endif
+
public static void create_interface(DBusConnection connection, string bus_name, string owner) {
if (bus_name == DBUS_NAME) {
message("Dbus name %s available", bus_name);
@@ -63,9 +68,67 @@ public class FaceDetect {
message("Dbus name %s gone", bus_name);
connected = false;
}
+
+ private static bool on_new_connection(DBusServer server, DBusConnection connection) {
+ try {
+ interface = connection.get_proxy_sync(null, DBUS_PATH,
+ DBusProxyFlags.DO_NOT_LOAD_PROPERTIES
+ | DBusProxyFlags.DO_NOT_CONNECT_SIGNALS,
+ null);
+ Idle.add(() => {
+ try {
+ if (interface.load_net(net_file))
+ connected = true;
+ else {
+ AppWindow.error_message(ERROR_MESSAGE);
+ }
+ } catch (Error error) {
+ critical("Failed to call load_net: %s", error.message);
+ AppWindow.error_message(ERROR_MESSAGE);
+ }
+ return false;
+ });
+
+ return true;
+ } catch (Error error) {
+ critical("Failed to create interface for face detect: %s", error.message);
+ AppWindow.error_message(ERROR_MESSAGE);
+
+ return false;
+ }
+ }
public static void init(string net_file) {
FaceDetect.net_file = net_file;
+#if FACEDETECT_BUS_PRIVATE
+ var address = "unix:tmpdir=%s".printf(Environment.get_tmp_dir());
+ var observer = new DBusAuthObserver();
+ observer.authorize_authenticated_peer.connect((stream, credentials) => {
+ debug("Observer trying to authorize for %s", credentials.to_string());
+ if (credentials == null)
+ return false;
+
+ try {
+ if (!credentials.is_same_user(new Credentials()))
+ return false;
+ return true;
+ } catch (Error error) {
+ return false;
+ }
+ });
+
+ try {
+ dbus_server = new GLib.DBusServer.sync(address, DBusServerFlags.NONE, DBus.generate_guid(),
observer, null);
+ dbus_server.new_connection.connect(on_new_connection);
+ dbus_server.start();
+ process = new Subprocess(SubprocessFlags.NONE, AppDirs.get_facedetect_bin().get_path(),
+ "--address=" + dbus_server.get_client_address());
+
+ } catch (Error error) {
+ warning("Failed to create private DBus server: %s", error.message);
+ AppWindow.error_message(ERROR_MESSAGE);
+ }
+#else
Bus.watch_name(BusType.SESSION, DBUS_NAME, BusNameWatcherFlags.NONE,
create_interface, interface_gone);
try {
@@ -78,16 +141,7 @@ public class FaceDetect {
AppWindow.error_message(ERROR_MESSAGE);
}
connected = true;
+#endif
}
- public static double dot_product(double[] vec1, double[] vec2) {
- if (vec1.length != vec2.length) {
- return 0;
- }
- double ret = 0;
- for (var i = 0; i < vec1.length; i++) {
- ret += vec1[i] * vec2[i];
- }
- return ret;
- }
}
diff --git a/src/faces/FacesTool.vala b/src/faces/FacesTool.vala
index 1d1db106..866f0317 100644
--- a/src/faces/FacesTool.vala
+++ b/src/faces/FacesTool.vala
@@ -900,6 +900,18 @@ public class FacesTool : EditingTools.EditingTool {
}
}
+ private double dot_product(double[] vec1, double[] vec2) {
+ if (vec1.length != vec2.length) {
+ return 0;
+ }
+
+ double ret = 0;
+ for (var i = 0; i < vec1.length; i++) {
+ ret += vec1[i] * vec2[i];
+ }
+ return ret;
+ }
+
private Face? get_face_match(FaceShape face_shape, double threshold) {
Gee.List<FaceLocationRow?> face_vecs;
try {
@@ -915,7 +927,7 @@ public class FacesTool : EditingTools.EditingTool {
string[] vec_str = row.vec.split(",");
double[] vec = {};
foreach (var d in vec_str) vec += double.parse(d);
- double product = FaceDetect.dot_product(face_shape.get_face_vec(), vec[0:128]);
+ double product = dot_product(face_shape.get_face_vec(), vec[0:128]);
if (product > max_product) {
max_product = product;
guess_id = row.face_id;
diff --git a/subprojects/shotwell-facedetect/meson.build b/subprojects/shotwell-facedetect/meson.build
index 4ece7d15..493bc04b 100644
--- a/subprojects/shotwell-facedetect/meson.build
+++ b/subprojects/shotwell-facedetect/meson.build
@@ -1,4 +1,4 @@
-project('shotwell-facedetect', ['c', 'cpp'])
+project('shotwell-facedetect', ['c', 'cpp'], default_options : ['cpp_std=c++14'])
gnome = import('gnome')
facedetect_dep = dependency('opencv', version : ['>= 2.3.0'], required : true)
cpp = meson.get_compiler('cpp')
diff --git a/subprojects/shotwell-facedetect/shotwell-facedetect.cpp
b/subprojects/shotwell-facedetect/shotwell-facedetect.cpp
index 7a6aca95..9031dfc3 100644
--- a/subprojects/shotwell-facedetect/shotwell-facedetect.cpp
+++ b/subprojects/shotwell-facedetect/shotwell-facedetect.cpp
@@ -11,6 +11,9 @@
#include "shotwell-facedetect.hpp"
#include "dbus-interface.h"
+const char* FACEDETECT_INTERFACE_NAME = "org.gnome.Shotwell.Faces1";
+const char* FACEDETECT_PATH = "/org/gnome/shotwell/faces";
+
// DBus binding functions
static gboolean on_handle_detect_faces(ShotwellFaces1 *object,
GDBusMethodInvocation *invocation,
@@ -84,21 +87,25 @@ static gboolean on_handle_terminate(ShotwellFaces1 *object,
static void on_name_acquired(GDBusConnection *connection,
const gchar *name, gpointer user_data) {
- ShotwellFaces1 *interface;
- GError *error;
- interface = shotwell_faces1_skeleton_new();
g_debug("Got name %s", name);
- g_signal_connect(interface, "handle-detect-faces", G_CALLBACK (on_handle_detect_faces), NULL);
+
+ ShotwellFaces1 *interface = shotwell_faces1_skeleton_new();
+ g_signal_connect(interface, "handle-detect-faces", G_CALLBACK (on_handle_detect_faces), nullptr);
g_signal_connect(interface, "handle-terminate", G_CALLBACK (on_handle_terminate), user_data);
- g_signal_connect(interface, "handle-load-net", G_CALLBACK (on_handle_load_net), NULL);
- g_signal_connect(interface, "handle-face-to-vec", G_CALLBACK (on_handle_face_to_vec), NULL);
- error = NULL;
- g_dbus_interface_skeleton_export(G_DBUS_INTERFACE_SKELETON(interface), connection,
"/org/gnome/shotwell/faces", &error);
+ g_signal_connect(interface, "handle-load-net", G_CALLBACK (on_handle_load_net), nullptr);
+ g_signal_connect(interface, "handle-face-to-vec", G_CALLBACK (on_handle_face_to_vec), nullptr);
+
+ GError *error = nullptr;
+ g_dbus_interface_skeleton_export(G_DBUS_INTERFACE_SKELETON(interface), connection, FACEDETECT_PATH,
&error);
+ if (error != nullptr) {
+ g_print("Failed to export interface: %s", error->message);
+ g_clear_error(&error);
+ }
}
static void on_name_lost(GDBusConnection *connection,
const gchar *name, gpointer user_data) {
- if (connection == NULL) {
+ if (connection == nullptr) {
g_debug("Unable to establish connection for name %s", name);
} else {
g_debug("Connection for name %s disconnected", name);
@@ -106,11 +113,90 @@ static void on_name_lost(GDBusConnection *connection,
g_main_loop_quit((GMainLoop *)user_data);
}
+static char* address = nullptr;
+
+static GOptionEntry entries[] = {
+ { "address", 'a', 0, G_OPTION_ARG_STRING, &address, "Use private DBus ADDRESS instead of session",
"ADDRESS" },
+ { nullptr }
+};
+
+static gboolean
+on_authorize_authenticated_peer (GIOStream *iostream,
+ GCredentials *credentials,
+ gpointer user_data)
+{
+ GCredentials *own_credentials = nullptr;
+ gboolean ret_val = FALSE;
+
+ g_debug("Authorizing peer with credentials %s\n", g_credentials_to_string (credentials));
+
+ if (credentials == nullptr)
+ goto out;
+
+ own_credentials = g_credentials_new ();
+
+ {
+ GError* error = nullptr;
+
+ if (!g_credentials_is_same_user (credentials, own_credentials, &error))
+ {
+ g_warning ("Unable to authorize peer: %s", error->message);
+ g_clear_error (&error);
+
+ goto out;
+ }
+ }
+
+ ret_val = TRUE;
+
+out:
+ g_clear_object (&own_credentials);
+
+ return ret_val;
+}
+
int main(int argc, char **argv) {
GMainLoop *loop;
- loop = g_main_loop_new (NULL, FALSE);
- g_bus_own_name(G_BUS_TYPE_SESSION, "org.gnome.Shotwell.Faces1", G_BUS_NAME_OWNER_FLAGS_NONE, NULL,
- on_name_acquired, on_name_lost, loop, NULL);
+ GError *error = nullptr;
+ GOptionContext *context;
+
+ context = g_option_context_new ("- Shotwell face detection helper service");
+ g_option_context_add_main_entries (context, entries, "shotwell");
+ if (!g_option_context_parse (context, &argc, &argv, &error)) {
+ g_print ("Failed to parse options: %s\n", error->message);
+ exit(1);
+ }
+
+ loop = g_main_loop_new (nullptr, FALSE);
+
+
+ // We are running on the sesion bus
+ if (address == nullptr) {
+ g_debug("Starting %s on G_BUS_TYPE_SESSION", argv[0]);
+ g_bus_own_name(G_BUS_TYPE_SESSION, FACEDETECT_INTERFACE_NAME, G_BUS_NAME_OWNER_FLAGS_NONE,
+ nullptr, on_name_acquired, on_name_lost, loop, nullptr);
+
+ } else {
+ g_debug("Starting %s on %s", argv[0], address);
+ GDBusAuthObserver *observer = g_dbus_auth_observer_new ();
+ g_signal_connect (G_OBJECT (observer), "authorize-authenticated-peer",
+ G_CALLBACK (on_authorize_authenticated_peer), nullptr);
+
+ GDBusConnection *connection = g_dbus_connection_new_for_address_sync (address,
+ G_DBUS_CONNECTION_FLAGS_AUTHENTICATION_CLIENT,
+ observer,
+ nullptr,
+ &error);
+ if (connection != nullptr)
+ on_name_acquired(connection, FACEDETECT_INTERFACE_NAME, loop);
+ }
+
+ if (error != nullptr) {
+ g_error("Failed to get connection on %s bus: %s",
+ address == nullptr ? "session" : "private",
+ error->message);
+ }
+
g_main_loop_run (loop);
return 0;
}
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]