summaryrefslogtreecommitdiff
path: root/subprojects/shotwell-facedetect/shotwell-facedetect.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'subprojects/shotwell-facedetect/shotwell-facedetect.cpp')
-rw-r--r--subprojects/shotwell-facedetect/shotwell-facedetect.cpp167
1 files changed, 167 insertions, 0 deletions
diff --git a/subprojects/shotwell-facedetect/shotwell-facedetect.cpp b/subprojects/shotwell-facedetect/shotwell-facedetect.cpp
new file mode 100644
index 0000000..3f8edeb
--- /dev/null
+++ b/subprojects/shotwell-facedetect/shotwell-facedetect.cpp
@@ -0,0 +1,167 @@
+/* Copyright 2016 Software Freedom Conservancy Inc.
+ *
+ * Copyright 2011 Valentín Barros Puertas <valentin(at)sanva(dot)net>
+ * Copyright 2018 Ricardo Fantin da Costa <ricardofantin(at)gmail(dot)com>
+ * Copyright 2018 Narendra A <narendra_m_a(at)yahoo(dot)com>
+ *
+ * This software is licensed under the GNU LGPL (version 2.1 or later).
+ * See the COPYING file in this distribution.
+ */
+
+#include "shotwell-facedetect.hpp"
+#include "dbus-interface.h"
+
+#include <gio/gio.h>
+#include <glib.h>
+
+#include <iostream>
+
+constexpr std::string_view FACEDETECT_INTERFACE_NAME{ "org.gnome.Shotwell.Faces1" };
+constexpr std::string_view FACEDETECT_PATH{ "/org/gnome/shotwell/faces" };
+
+GVariant *FaceRect::serialize() const
+{
+ return g_variant_new("(dddd@ad)", x, y, width, height,
+ g_variant_new_fixed_array(G_VARIANT_TYPE_DOUBLE, vec.data(), vec.size(), sizeof(double)));
+}
+
+// DBus binding functions
+static gboolean on_handle_detect_faces(ShotwellFaces1 *object, GDBusMethodInvocation *invocation,
+ [[maybe_unused]]const gchar *arg_image, const gchar *arg_cascade, gdouble arg_scale,
+ gboolean arg_infer)
+{
+ g_auto(GVariantBuilder) builder = G_VARIANT_BUILDER_INIT(G_VARIANT_TYPE("a(ddddad)"));
+ auto rects = detectFaces(arg_image, arg_scale, arg_infer == TRUE);
+
+ // Construct return value
+ for(const auto &rect : rects) {
+ g_variant_builder_add(&builder, "@(ddddad)", rect.serialize());
+ g_debug("Returning %f,%f-%f", rect.x, rect.y, rect.vec.back());
+ }
+
+ // Call return
+ shotwell_faces1_complete_detect_faces(object, invocation, g_variant_builder_end(&builder));
+ return TRUE;
+}
+
+static gboolean on_handle_load_net(ShotwellFaces1 *object, GDBusMethodInvocation *invocation, const gchar *arg_net)
+{
+ // Call return
+ shotwell_faces1_complete_load_net(object, invocation, loadNet(arg_net) ? TRUE : FALSE);
+ return TRUE;
+}
+
+static gboolean on_handle_terminate(ShotwellFaces1 *object, GDBusMethodInvocation *invocation, gpointer user_data)
+{
+ g_debug("Exiting...");
+ shotwell_faces1_complete_terminate(object, invocation);
+ g_main_loop_quit(static_cast<GMainLoop *>(user_data));
+
+ return TRUE;
+}
+
+static void on_name_acquired(GDBusConnection *connection,
+ const gchar *name, gpointer user_data) {
+ g_debug("Got name %s", name);
+
+ auto *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), nullptr);
+
+ g_autoptr(GError) error = nullptr;
+ g_dbus_interface_skeleton_export(G_DBUS_INTERFACE_SKELETON(interface), connection, FACEDETECT_PATH.data(), &error);
+ if (error != nullptr) {
+ g_print("Failed to export interface: %s", error->message);
+ }
+}
+
+static void on_name_lost(GDBusConnection *connection,
+ const gchar *name, gpointer user_data) {
+ if (connection == nullptr) {
+ g_debug("Unable to establish connection for name %s", name);
+ } else {
+ g_debug("Connection for name %s disconnected", name);
+ }
+ g_main_loop_quit(static_cast<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([[maybe_unused]] GIOStream *iostream, GCredentials *credentials,
+ [[maybe_unused]] gpointer user_data)
+{
+ g_autoptr(GCredentials) own_credentials = nullptr;
+
+ g_debug("Authorizing peer with credentials %s\n", g_credentials_to_string(credentials));
+
+ if(credentials == nullptr) {
+ return FALSE;
+ }
+
+ own_credentials = g_credentials_new();
+
+ {
+ g_autoptr(GError) error = nullptr;
+
+ if(g_credentials_is_same_user(credentials, own_credentials, &error) == FALSE) {
+ g_warning("Unable to authorize peer: %s", error->message);
+
+ return FALSE;
+ }
+ }
+
+ return TRUE;
+}
+
+int main(int argc, char **argv) {
+ GMainLoop *loop;
+ 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) == FALSE) {
+ g_print ("Failed to parse options: %s\n", error->message);
+ exit(1);
+ }
+
+ loop = g_main_loop_new (nullptr, FALSE);
+
+
+ // We are running on the session 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.data(), 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.data (), 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;
+}