diff options
Diffstat (limited to 'subprojects/shotwell-facedetect/shotwell-facedetect.cpp')
-rw-r--r-- | subprojects/shotwell-facedetect/shotwell-facedetect.cpp | 167 |
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; +} |