[file-roller] use file-roller as service as well, renamed the interface as org.gnome.ArchiveManager1



commit d02e500fc20450234d53d11d9f078e40d82d31aa
Author: Paolo Bacchilega <paobac src gnome org>
Date:   Tue Jun 19 19:21:17 2012 +0200

    use file-roller as service as well, renamed the interface as org.gnome.ArchiveManager1
    
    Removed file-roller-server as separate executable that implements the D-Bus
    interface, added a --service option to file-roller to act as a service.  Renamed
    the D-Bus interface as org.gnome.ArchiveManager1. Moved the interface
    description in an external file and save it in memory with GResource.

 data/Makefile.am                     |    3 +-
 data/org.gnome.ArchiveManager1.xml   |  102 +++++++
 data/org.gnome.FileRoller.service.in |    4 +-
 po/POTFILES.in                       |    1 -
 src/Makefile.am                      |    8 -
 src/file-roller.gresource.xml        |    3 +-
 src/main.c                           |  322 +++++++++++++++++++++--
 src/server.c                         |  481 ----------------------------------
 src/test-server.c                    |   10 +-
 9 files changed, 421 insertions(+), 513 deletions(-)
---
diff --git a/data/Makefile.am b/data/Makefile.am
index 9ac225a..04a1117 100644
--- a/data/Makefile.am
+++ b/data/Makefile.am
@@ -13,7 +13,7 @@ servicedir = $(datadir)/dbus-1/services
 service_in_files = org.gnome.FileRoller.service.in
 service_DATA = $(service_in_files:.service.in=.service)
 $(service_DATA): $(service_in_files) Makefile
-	$(AM_V_GEN) $(SED) -e "s|\ libexecdir\@|$(libexecdir)|" $< > $@
+	$(AM_V_GEN) $(SED) -e "s|\ bindir\@|$(bindir)|" $< > $@
 
 gsettingsschema_in_files = org.gnome.FileRoller.gschema.xml.in
 gsettings_SCHEMAS = $(gsettingsschema_in_files:.xml.in=.xml)
@@ -41,6 +41,7 @@ update-cache:
 
 EXTRA_DIST = 				\
 	file-roller.convert		\
+	org.gnome.ArchiveManager1.xml	\
 	packages.match.in		\
 	packages.match			\
 	$(desktop_in_in_files)		\
diff --git a/data/org.gnome.ArchiveManager1.xml b/data/org.gnome.ArchiveManager1.xml
new file mode 100644
index 0000000..bccf43b
--- /dev/null
+++ b/data/org.gnome.ArchiveManager1.xml
@@ -0,0 +1,102 @@
+<!DOCTYPE node PUBLIC "-//freedesktop//DTD D-BUS Object Introspection 1.0//EN"
+ "http://www.freedesktop.org/standards/dbus/1.0/introspect.dtd";>
+<node>
+  <!-- org.gnome.ArchiveManager1:
+       @short_description: Create and extract compressed archives
+
+       This D-Bus interface is used to create and extract compressed archives.
+    -->
+  <interface name="org.gnome.ArchiveManager1">
+
+    <!--
+        GetSupportedTypes:
+        @action: Can be one of the following values:
+          *) create: create an archive that can contain many files.
+          *) create_single_file: create an archive that can contain a single file.
+          *) extract: extract the content of an archive.
+        @types: The supported archive types described as an array of hash tables,
+          where each hash table has the following keys:
+          *) mime-type: the mime type relative to the archive type.
+          *) default-extension: the extension to use for newly created archives.
+          *) description: a human readable description of the archive type.
+
+        Returns the supported archive types for a specific action.
+      -->
+    <method name="GetSupportedTypes">
+      <arg name="action" type="s" direction="in"/>
+      <arg name="types" type="aa{ss}" direction="out"/>
+    </method>
+
+    <!--
+        AddToArchive:
+        @archive: The archive URI.
+        @files: The files to add to the archive, as an array of URIs.
+        @use_progress_dialog: Whether to show the progress dialog.
+
+        Adds the specified files to an archive.  If the archive already
+        exists the archive is updated.
+      -->
+    <method name="AddToArchive">
+      <arg name="archive" type="s" direction="in"/>
+      <arg name="files" type="as" direction="in"/>
+      <arg name="use_progress_dialog" type="b" direction="in"/>
+    </method>
+
+    <!--
+        Compress:
+        @files: The files to add to the archive, as an array of URIs.
+        @destination: An optional destination, if not specified the folder of
+          the first file in @files is used.
+        @use_progress_dialog: Whether to show the progress dialog.
+
+        Compresses a series of files in an archive. The user is asked to
+        enter an archive name, archive type and other options.  In this case
+        it's used the same dialog used by the "Compress..." command from the
+        Nautilus context menu.
+        If the user chooses an existing archive, the archive is updated.
+      -->
+    <method name="Compress">
+      <arg name="files" type="as" direction="in"/>
+      <arg name="destination" type="s" direction="in"/>
+      <arg name="use_progress_dialog" type="b" direction="in"/>
+    </method>
+
+    <!--
+        Extract:
+        @archive: The archive to extract.
+        @destination: The location where to extract the archive.
+        @use_progress_dialog: Whether to show the progress dialog.
+
+        Extract an archive in a specified location.
+      -->
+    <method name="Extract">
+      <arg name="archive" type="s" direction="in"/>
+      <arg name="destination" type="s" direction="in"/>
+      <arg name="use_progress_dialog" type="b" direction="in"/>
+    </method>
+
+    <!--
+        ExtractHere:
+        @archive: The archive to extract.
+        @use_progress_dialog: Whether to show the progress dialog.
+
+        Extract an archive in the archive's folder.
+      -->
+    <method name="ExtractHere">
+      <arg name="archive" type="s" direction="in"/>
+      <arg name="use_progress_dialog" type="b" direction="in"/>
+    </method>
+
+    <!--
+        Progress:
+        @fraction: number from 0.0 to 100.0 that indicates the percentage of
+          completion of the operation.
+        @details: text message that describes the current operation.
+      -->
+    <signal name="Progress">
+      <arg name="fraction" type="d"/>
+      <arg name="details" type="s"/>
+    </signal>
+
+  </interface>
+</node>
diff --git a/data/org.gnome.FileRoller.service.in b/data/org.gnome.FileRoller.service.in
index b68b646..f36fc0e 100644
--- a/data/org.gnome.FileRoller.service.in
+++ b/data/org.gnome.FileRoller.service.in
@@ -1,3 +1,3 @@
 [D-BUS Service]
-Name=org.gnome.FileRoller
-Exec= libexecdir@/file-roller-server
+Name=org.gnome.ArchiveManager1
+Exec= bindir@/file-roller --service
diff --git a/po/POTFILES.in b/po/POTFILES.in
index 0957459..f5b64bf 100644
--- a/po/POTFILES.in
+++ b/po/POTFILES.in
@@ -119,7 +119,6 @@ src/preferences.c
 src/preferences.h
 src/rar-utils.c
 src/rar-utils.h
-src/server.c
 src/test-server.c
 src/typedefs.h
 [type: gettext/glade]src/ui/add-options.ui
diff --git a/src/Makefile.am b/src/Makefile.am
index e48b433..f5ff984 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -1,7 +1,6 @@
 SUBDIRS = commands sh ui
 
 bin_PROGRAMS = file-roller
-libexec_PROGRAMS = file-roller-server
 noinst_PROGRAMS = test-server
 
 if MKDTEMP_MISSING
@@ -207,13 +206,6 @@ if ENABLE_MAGIC
 file_roller_LDADD += $(MAGIC_LIBS)
 endif
 
-file_roller_server_SOURCES =		\
-	$(COMMON_SOURCES)		\
-	server.c
-	
-file_roller_server_LDADD =		\
-	$(file_roller_LDADD)
-
 test_server_SOURCES = test-server.c
 test_server_FLAGS = $(FR_CFLAGS)
 test_server_LDADD = $(FR_LIBS)
diff --git a/src/file-roller.gresource.xml b/src/file-roller.gresource.xml
index a0f771a..3bfeecb 100644
--- a/src/file-roller.gresource.xml
+++ b/src/file-roller.gresource.xml
@@ -11,5 +11,6 @@
     <file compressed="true">ui/password.ui</file>
     <file compressed="true">ui/properties.ui</file>
     <file compressed="true">ui/update.ui</file>
+    <file compressed="true">../data/org.gnome.ArchiveManager1.xml</file>
   </gresource>
-</gresources>
\ No newline at end of file
+</gresources>
diff --git a/src/main.c b/src/main.c
index 0f08f26..2735c4a 100644
--- a/src/main.c
+++ b/src/main.c
@@ -36,23 +36,26 @@
 #  include "eggsmclient.h"
 #endif
 #include "eggdesktopfile.h"
+#include "file-utils.h"
 #include "fr-init.h"
 #include "gtk-utils.h"
 
 
-gint              ForceDirectoryCreation;
+#define ORG_GNOME_ARCHIVEMANAGER_XML "/org/gnome/FileRoller/../data/org.gnome.ArchiveManager1.xml"
 
-static char     **remaining_args;
-static char      *arg_add_to = NULL;
-static int        arg_add = FALSE;
-static char      *arg_extract_to = NULL;
-static int        arg_extract = FALSE;
-static int        arg_extract_here = FALSE;
-static char      *arg_default_url = NULL;
-static gboolean   arg_version = FALSE;
 
-/* argv[0] from main(); used as the command to restart the program */
-static const char *program_argv0 = NULL;
+gint                ForceDirectoryCreation;
+static char       **remaining_args;
+static char        *arg_add_to = NULL;
+static int          arg_add = FALSE;
+static char        *arg_extract_to = NULL;
+static int          arg_extract = FALSE;
+static int          arg_extract_here = FALSE;
+static char        *arg_default_url = NULL;
+static gboolean     arg_version = FALSE;
+static gboolean     arg_service = FALSE;
+static const char  *program_argv0 = NULL; /* argv[0] from main(); used as the command to restart the program */
+
 
 static const GOptionEntry options[] = {
 	{ "add-to", 'a', 0, G_OPTION_ARG_STRING, &arg_add_to,
@@ -83,6 +86,9 @@ static const GOptionEntry options[] = {
 	  N_("Create destination folder without asking confirmation"),
 	  NULL },
 
+	{ "service", 'v', 0, G_OPTION_ARG_NONE, &arg_service,
+	  N_("Start as a service"), NULL },
+
 	{ "version", 'v', 0, G_OPTION_ARG_NONE, &arg_version,
 	  N_("Show version"), NULL },
 
@@ -159,6 +165,9 @@ initialize_app_menu (GApplication *application)
 }
 
 
+/* -- session management -- */
+
+
 #ifdef USE_SMCLIENT
 
 
@@ -248,27 +257,303 @@ fr_restore_session (EggSMClient *client)
 #endif /* USE_SMCLIENT */
 
 
+/* -- service -- */
+
+
+static void
+window_ready_cb (GtkWidget *widget,
+		 GError    *error,
+		 gpointer   user_data)
+{
+	if (error == NULL)
+		g_dbus_method_invocation_return_value ((GDBusMethodInvocation *) user_data, NULL);
+	else
+		g_dbus_method_invocation_return_error ((GDBusMethodInvocation *) user_data,
+						       error->domain,
+						       error->code,
+						       "%s",
+						       error->message);
+}
+
+
+static gboolean
+window_progress_cb (FrWindow *window,
+		    double    fraction,
+		    char     *details,
+		    gpointer  user_data)
+{
+	GDBusConnection *connection = user_data;
+
+	g_dbus_connection_emit_signal (connection,
+				       NULL,
+				       "org/gnome/ArchiveManager1",
+				       "org.gnome.ArchiveManager1",
+				       "Progress",
+				       g_variant_new ("(ds)",
+						      fraction,
+						      details),
+				       NULL);
+
+	return TRUE;
+}
+
+
+static void
+handle_method_call (GDBusConnection       *connection,
+		    const char            *sender,
+		    const char            *object_path,
+		    const char            *interface_name,
+		    const char            *method_name,
+		    GVariant              *parameters,
+		    GDBusMethodInvocation *invocation,
+		    gpointer               user_data)
+{
+	update_registered_commands_capabilities ();
+
+	if (g_strcmp0 (method_name, "GetSupportedTypes") == 0) {
+		char *action;
+		int  *supported_types = NULL;
+
+		g_variant_get (parameters, "(s)", &action);
+
+		if (g_strcmp0 (action, "create") == 0) {
+			supported_types = save_type;
+		}
+		else if (g_strcmp0 (action, "create_single_file") == 0) {
+			supported_types = single_file_save_type;
+		}
+		else if (g_strcmp0 (action, "extract") == 0) {
+			supported_types = open_type;
+		}
+
+		if (supported_types == NULL) {
+			g_dbus_method_invocation_return_error (invocation,
+							       G_IO_ERROR,
+							       G_IO_ERROR_INVALID_ARGUMENT,
+							       "Invalid action '%s', valid values are: create, create_single_file, extract",
+							       action);
+		}
+		else {
+			GVariantBuilder builder;
+			int             i;
+
+			g_variant_builder_init (&builder, G_VARIANT_TYPE ("(aa{ss})"));
+			g_variant_builder_open (&builder, G_VARIANT_TYPE ("aa{ss}"));
+			for (i = 0; supported_types[i] != -1; i++) {
+				g_variant_builder_open (&builder, G_VARIANT_TYPE ("a{ss}"));
+				g_variant_builder_add (&builder, "{ss}",
+						       "mime-type",
+						       mime_type_desc[supported_types[i]].mime_type);
+				g_variant_builder_add (&builder, "{ss}",
+						       "default-extension",
+						       mime_type_desc[supported_types[i]].default_ext);
+				g_variant_builder_add (&builder, "{ss}",
+						       "description",
+						       _(mime_type_desc[supported_types[i]].name));
+				g_variant_builder_close (&builder);
+			}
+			g_variant_builder_close (&builder);
+
+			g_dbus_method_invocation_return_value (invocation, g_variant_builder_end (&builder));
+		}
+
+		g_free (action);
+	}
+	else if (g_strcmp0 (method_name, "AddToArchive") == 0) {
+		char       *archive;
+		char      **files;
+		gboolean    use_progress_dialog;
+		int         i;
+		GList      *file_list = NULL;
+		GtkWidget  *window;
+
+		g_variant_get (parameters, "(s^asb)", &archive, &files, &use_progress_dialog);
+
+		for (i = 0; files[i] != NULL; i++)
+			file_list = g_list_prepend (file_list, files[i]);
+		file_list = g_list_reverse (file_list);
+
+		window = fr_window_new ();
+		fr_window_use_progress_dialog (FR_WINDOW (window), use_progress_dialog);
+
+		g_signal_connect (window, "progress", G_CALLBACK (window_progress_cb), connection);
+		g_signal_connect (window, "ready", G_CALLBACK (window_ready_cb), invocation);
+
+		fr_window_new_batch (FR_WINDOW (window), _("Compress"));
+		fr_window_set_batch__add (FR_WINDOW (window), archive, file_list);
+		fr_window_append_batch_action (FR_WINDOW (window), FR_BATCH_ACTION_QUIT, NULL, NULL);
+		fr_window_start_batch (FR_WINDOW (window));
+
+		g_free (archive);
+	}
+	else if (g_strcmp0 (method_name, "Compress") == 0) {
+		char      **files;
+		char       *destination;
+		gboolean    use_progress_dialog;
+		int         i;
+		GList      *file_list = NULL;
+		GtkWidget  *window;
+
+		g_variant_get (parameters, "(^assb)", &files, &destination, &use_progress_dialog);
+
+		for (i = 0; files[i] != NULL; i++)
+			file_list = g_list_prepend (file_list, files[i]);
+		file_list = g_list_reverse (file_list);
+
+		if ((destination == NULL) || (strcmp (destination, "") == 0))
+			destination = remove_level_from_path (file_list->data);
+
+		window = fr_window_new ();
+		fr_window_use_progress_dialog (FR_WINDOW (window), use_progress_dialog);
+		fr_window_set_default_dir (FR_WINDOW (window), destination, TRUE);
+
+		g_signal_connect (window, "progress", G_CALLBACK (window_progress_cb), connection);
+		g_signal_connect (window, "ready", G_CALLBACK (window_ready_cb), invocation);
+
+		fr_window_new_batch (FR_WINDOW (window), _("Extract archive"));
+		fr_window_set_batch__add (FR_WINDOW (window), NULL, file_list);
+		fr_window_append_batch_action (FR_WINDOW (window), FR_BATCH_ACTION_QUIT, NULL, NULL);
+		fr_window_start_batch (FR_WINDOW (window));
+
+		g_free (destination);
+	}
+	else if (g_strcmp0 (method_name, "Extract") == 0) {
+		char      *archive;
+		char      *destination;
+		gboolean   use_progress_dialog;
+		GtkWidget *window;
+
+		g_variant_get (parameters, "(ssb)", &archive, &destination, &use_progress_dialog);
+
+		window = fr_window_new ();
+		fr_window_use_progress_dialog (FR_WINDOW (window), use_progress_dialog);
+		if ((destination != NULL) & (strcmp (destination, "") != 0))
+			fr_window_set_default_dir (FR_WINDOW (window), destination, TRUE);
+
+		g_signal_connect (window, "progress", G_CALLBACK (window_progress_cb), connection);
+		g_signal_connect (window, "ready", G_CALLBACK (window_ready_cb), invocation);
+
+		fr_window_new_batch (FR_WINDOW (window), _("Extract archive"));
+		fr_window_set_batch__extract (FR_WINDOW (window), archive, destination);
+		fr_window_append_batch_action (FR_WINDOW (window), FR_BATCH_ACTION_QUIT, NULL, NULL);
+		fr_window_start_batch (FR_WINDOW (window));
+
+		g_free (destination);
+		g_free (archive);
+	}
+	else if (g_strcmp0 (method_name, "ExtractHere") == 0) {
+		char      *archive;
+		gboolean   use_progress_dialog;
+		GtkWidget *window;
+
+		g_variant_get (parameters, "(sb)", &archive, &use_progress_dialog);
+
+		window = fr_window_new ();
+		fr_window_use_progress_dialog (FR_WINDOW (window), use_progress_dialog);
+
+		g_signal_connect (window, "progress", G_CALLBACK (window_progress_cb), connection);
+		g_signal_connect (window, "ready", G_CALLBACK (window_ready_cb), invocation);
+
+		fr_window_new_batch (FR_WINDOW (window), _("Extract archive"));
+		fr_window_set_batch__extract_here (FR_WINDOW (window), archive);
+		fr_window_append_batch_action (FR_WINDOW (window), FR_BATCH_ACTION_QUIT, NULL, NULL);
+		fr_window_start_batch (FR_WINDOW (window));
+
+		g_free (archive);
+	}
+}
+
+
+static const GDBusInterfaceVTable interface_vtable = {
+	handle_method_call,
+	NULL, 			/* handle_get_property */
+	NULL 			/* handle_set_property */
+};
+
+
 /* -- main application -- */
 
 
-typedef GtkApplication      FrApplication;
+typedef struct {
+	GtkApplication __parent;
+	GDBusNodeInfo  *introspection_data;
+	guint           owner_id;
+} FrApplication;
+
 typedef GtkApplicationClass FrApplicationClass;
 
 static gpointer fr_application_parent_class;
 
 
 G_DEFINE_TYPE (FrApplication, fr_application, GTK_TYPE_APPLICATION)
+#define FR_APPLICATION(x) ((FrApplication *)(x))
 
 
 static void
 fr_application_finalize (GObject *object)
 {
+	FrApplication *self = FR_APPLICATION (object);
+
+	if (self->introspection_data != NULL)
+		g_dbus_node_info_unref (self->introspection_data);
+	if (self->owner_id != 0)
+		g_bus_unown_name (self->owner_id);
+
         G_OBJECT_CLASS (fr_application_parent_class)->finalize (object);
 }
 
 
 static void
-fr_application_init (FrApplication *app)
+on_bus_acquired_for_archive_manager (GDBusConnection *connection,
+				     const char      *name,
+				     gpointer         user_data)
+{
+	FrApplication *self = user_data;
+	guint          registration_id;
+	GError        *error = NULL;
+
+	registration_id = g_dbus_connection_register_object (connection,
+							     "/org/gnome/ArchiveManager1",
+							     self->introspection_data->interfaces[0],
+							     &interface_vtable,
+							     NULL,
+							     NULL,  /* user_data_free_func */
+							     &error); /* GError** */
+	if (registration_id == 0) {
+		g_error ("%s", error->message);
+		g_clear_error (&error);
+	}
+}
+
+
+static void
+fr_application_register_archive_manager_service (FrApplication *self)
+{
+	gsize         size;
+	guchar       *buffer;
+	GInputStream *stream;
+
+	g_resources_get_info (ORG_GNOME_ARCHIVEMANAGER_XML, 0, &size, NULL, NULL);
+	buffer = g_new (guchar, size);
+	stream = g_resources_open_stream (ORG_GNOME_ARCHIVEMANAGER_XML, 0, NULL);
+	g_input_stream_read_all (stream, buffer, size, NULL, NULL, NULL);
+
+	self->introspection_data = g_dbus_node_info_new_for_xml ((gchar *) buffer, NULL);
+	self->owner_id = g_bus_own_name (G_BUS_TYPE_SESSION,
+					 "org.gnome.ArchiveManager1",
+					 G_BUS_NAME_OWNER_FLAGS_NONE,
+					 on_bus_acquired_for_archive_manager,
+					 NULL /*on_name_acquired*/,
+					 NULL /*on_name_lost*/,
+					 self,
+					 NULL);
+
+	g_free (buffer);
+}
+
+
+static void
+fr_application_init (FrApplication *self)
 {
 #ifdef GDK_WINDOWING_X11
 	egg_set_desktop_file (APPLICATIONS_DIR "/file-roller.desktop");
@@ -277,6 +562,9 @@ fr_application_init (FrApplication *app)
 	g_set_application_name (_("File Roller"));
 	gtk_window_set_default_icon_name ("file-roller");
 #endif
+
+	self->owner_id = 0;
+	self->introspection_data = NULL;
 }
 
 
@@ -285,6 +573,7 @@ fr_application_startup (GApplication *application)
 {
 	G_APPLICATION_CLASS (fr_application_parent_class)->startup (application);
 
+	fr_application_register_archive_manager_service (FR_APPLICATION (application));
 	initialize_data ();
 	initialize_app_menu (application);
 }
@@ -397,7 +686,8 @@ fr_application_command_line (GApplication            *application,
 #endif
 
 	if (remaining_args == NULL) { /* No archive specified. */
-		gtk_widget_show (fr_window_new ());
+		if (! arg_service)
+			gtk_widget_show (fr_window_new ());
 		return fr_application_command_line_finished (application, EXIT_SUCCESS);
 	}
 
@@ -566,8 +856,8 @@ static GtkApplication *
 fr_application_new (void)
 {
         return g_object_new (fr_application_get_type (),
-                             "application-id", "org.gnome.file-roller",
-                             "flags", G_APPLICATION_FLAGS_NONE,
+                             "application-id", "org.gnome.FileRoller",
+                             "flags", G_APPLICATION_IS_SERVICE,
                              NULL);
 }
 
diff --git a/src/test-server.c b/src/test-server.c
index 726844b..b0fc4db 100644
--- a/src/test-server.c
+++ b/src/test-server.c
@@ -148,9 +148,9 @@ main (int argc, char *argv[])
 		proxy = g_dbus_proxy_new_sync (connection,
 					       G_DBUS_PROXY_FLAGS_NONE,
 					       NULL,
-					       "org.gnome.FileRoller",
-					       "/org/gnome/FileRoller",
-					       "org.gnome.ArchiveManager",
+					       "org.gnome.ArchiveManager1",
+					       "/org/gnome/ArchiveManager1",
+					       "org.gnome.ArchiveManager1",
 					       NULL,
 					       &error);
 
@@ -266,6 +266,10 @@ main (int argc, char *argv[])
 #endif
 
 		}
+		else {
+			g_error ("%s\n", error->message);
+			g_clear_error (&error);
+		}
 	}
 
 	loop = g_main_loop_new (NULL, FALSE);



[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]