diff options
author | Dave Camp <dave@ximian.com> | 2003-11-20 19:51:32 +0000 |
---|---|---|
committer | Dave Camp <campd@src.gnome.org> | 2003-11-20 19:51:32 +0000 |
commit | 5b9f3fc0a5e6cf5324434b901dbb3d9bdcf39d67 (patch) | |
tree | e2a6f64f2783b103c56e44d5fbe8d221ed3f74eb | |
parent | a7cdc64a52cd715755e11d8a6a9e5d506fd50b10 (diff) | |
download | nautilus-5b9f3fc0a5e6cf5324434b901dbb3d9bdcf39d67.tar.gz |
New library for nautilus extensions.
2003-11-20 Dave Camp <dave@ximian.com>
* Makefile.am:
* configure.in:
* libnautilus-extension/Makefile.am:
* libnautilus-extension/libnautilus-extension.pc.in:
* libnautilus-extension/nautilus-extension-types.c:
* libnautilus-extension/nautilus-extension-types.h:
* libnautilus-extension/nautilus-file-info.c:
* libnautilus-extension/nautilus-file-info.h:
* libnautilus-extension/nautilus-info-provider.c:
* libnautilus-extension/nautilus-info-provider.h:
New library for nautilus extensions.
* libnautilus-private/nautilus-marshal.list:
* libnautilus-private/Makefile.am:
* libnautilus-private/nautilus-directory-async.c:
(nautilus_directory_set_up_request), (lacks_extension_info),
(wants_extension_info), (extension_info_cancel),
(extension_info_stop), (finish_info_provider),
(info_provider_idle_callback), (info_provider_callback),
(extension_info_start), (start_or_stop_io),
(nautilus_directory_cancel), (cancel_loading_attributes),
(file_needs_extension_work_done), (file_needs_work_done),
(nautilus_directory_remove_file_from_work_queue),
(move_file_to_low_priority_queue), (move_file_to_extension_queue):
* libnautilus-private/nautilus-directory-private.h:
* libnautilus-private/nautilus-directory.c:
(nautilus_directory_init), (nautilus_directory_finalize),
(nautilus_directory_notify_files_changed):
Add a third queue for extension info, that runs after the high
and low priority queues.
* libnautilus-private/nautilus-file-attributes.h:
* libnautilus-private/nautilus-file-operations.c:
* libnautilus-private/nautilus-file-private.h:
* libnautilus-private/nautilus-file.c:
(nautilus_file_invalidate_extension_info_internal),
(nautilus_file_invalidate_attributes_internal):
* libnautilus-private/nautilus-file.c:
(nautilus_file_get_type), (nautilus_file_instance_init),
(nautilus_file_get_keywords), (nautilus_file_get_type),
(nautilus_file_class_init), (nautilus_file_get_vfs_file_info),
(nautilus_file_add_emblem), (nautilus_file_info_providers_done),
(nautilus_file_info_iface_init): Implement the NautilusFileInfo
interface for extensions to use.
* libnautilus-private/nautilus-module.c: (nautilus_module_load),
* libnautilus-private/nautilus-module.h:
Module loading code.
* src/file-manager/fm-directory-view.c: (finish_loading):
Request extension info.
* src/nautilus-application.c: (finish_startup): Initialize the
module interface.
25 files changed, 1348 insertions, 240 deletions
@@ -1,3 +1,61 @@ +2003-11-20 Dave Camp <dave@ximian.com> + + * Makefile.am: + * configure.in: + * libnautilus-extension/Makefile.am: + * libnautilus-extension/libnautilus-extension.pc.in: + * libnautilus-extension/nautilus-extension-types.c: + * libnautilus-extension/nautilus-extension-types.h: + * libnautilus-extension/nautilus-file-info.c: + * libnautilus-extension/nautilus-file-info.h: + * libnautilus-extension/nautilus-info-provider.c: + * libnautilus-extension/nautilus-info-provider.h: + New library for nautilus extensions. + + * libnautilus-private/nautilus-marshal.list: + * libnautilus-private/Makefile.am: + * libnautilus-private/nautilus-directory-async.c: + (nautilus_directory_set_up_request), (lacks_extension_info), + (wants_extension_info), (extension_info_cancel), + (extension_info_stop), (finish_info_provider), + (info_provider_idle_callback), (info_provider_callback), + (extension_info_start), (start_or_stop_io), + (nautilus_directory_cancel), (cancel_loading_attributes), + (file_needs_extension_work_done), (file_needs_work_done), + (nautilus_directory_remove_file_from_work_queue), + (move_file_to_low_priority_queue), (move_file_to_extension_queue): + * libnautilus-private/nautilus-directory-private.h: + * libnautilus-private/nautilus-directory.c: + (nautilus_directory_init), (nautilus_directory_finalize), + (nautilus_directory_notify_files_changed): + Add a third queue for extension info, that runs after the high + and low priority queues. + + * libnautilus-private/nautilus-file-attributes.h: + * libnautilus-private/nautilus-file-operations.c: + * libnautilus-private/nautilus-file-private.h: + * libnautilus-private/nautilus-file.c: + (nautilus_file_invalidate_extension_info_internal), + (nautilus_file_invalidate_attributes_internal): + + * libnautilus-private/nautilus-file.c: + (nautilus_file_get_type), (nautilus_file_instance_init), + (nautilus_file_get_keywords), (nautilus_file_get_type), + (nautilus_file_class_init), (nautilus_file_get_vfs_file_info), + (nautilus_file_add_emblem), (nautilus_file_info_providers_done), + (nautilus_file_info_iface_init): Implement the NautilusFileInfo + interface for extensions to use. + + * libnautilus-private/nautilus-module.c: (nautilus_module_load), + * libnautilus-private/nautilus-module.h: + Module loading code. + + * src/file-manager/fm-directory-view.c: (finish_loading): + Request extension info. + + * src/nautilus-application.c: (finish_startup): Initialize the + module interface. + 2003-11-19 James Willcox <jwillcox@gnome.org> * libnautilus-private/nautilus-icon-canvas-item.c: diff --git a/Makefile.am b/Makefile.am index 871ece7e5..3ad326b2c 100644 --- a/Makefile.am +++ b/Makefile.am @@ -16,6 +16,7 @@ DESKTOP_SETTINGS_FILES= \ SUBDIRS = \ libnautilus \ + libnautilus-extension \ cut-n-paste-code \ libbackground \ libnautilus-private \ diff --git a/components/services/nautilus-dependent-shared/shared-service-widgets.c b/components/services/nautilus-dependent-shared/shared-service-widgets.c deleted file mode 100644 index c88adcbd9..000000000 --- a/components/services/nautilus-dependent-shared/shared-service-widgets.c +++ /dev/null @@ -1,212 +0,0 @@ -/* -*- Mode: C; indent-tabs-mode: t; c-basic-offset: 8; tab-width: 8 -*- */ - -/* - * Copyright (C) 2000 Eazel, Inc - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License as - * published by the Free Software Foundation; either version 2 of the - * License, or (at your option) any later version. - * - * This program 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 - * General Public License for more details. - * - * You should have received a copy of the GNU General Public - * License along with this program; if not, write to the - * Free Software Foundation, Inc., 59 Temple Place - Suite 330, - * Boston, MA 02111-1307, USA. - * - * Authors: Ramiro Estrugo <ramiro@eazel.com> - * J Shane Culpepper <pepper@eazel.com> - * - */ - -#include <config.h> - -#include "shared-service-widgets.h" - -#include <libnautilus-extensions/nautilus-background.h> -#include <libnautilus-extensions/nautilus-gdk-pixbuf-extensions.h> -#include <libnautilus-extensions/nautilus-gtk-extensions.h> -#include <libnautilus-extensions/nautilus-gtk-macros.h> -#include <libnautilus-extensions/nautilus-glib-extensions.h> -#include <libnautilus-extensions/nautilus-global-preferences.h> -#include <libnautilus-extensions/nautilus-file-utilities.h> -#include <libnautilus-extensions/nautilus-string.h> -#include <libnautilus-extensions/nautilus-font-factory.h> -#include <libnautilus-extensions/nautilus-gdk-extensions.h> -#include <libnautilus-extensions/nautilus-theme.h> - -#include <stdio.h> - -/* private shared helper routine to create an image widget from a pixbuf */ -static GtkWidget* -create_image_widget_from_pixbuf (GdkPixbuf *icon_pixbuf, - const char *tile_icon_name) -{ - GtkWidget *image_widget; - - g_return_val_if_fail (icon_pixbuf || tile_icon_name, NULL); - - image_widget = nautilus_image_new (); - - if (icon_pixbuf != NULL) { - nautilus_image_set_pixbuf (NAUTILUS_IMAGE (image_widget), icon_pixbuf); - } - - if (tile_icon_name != NULL) { - char *tile_icon_path; - - tile_icon_path = nautilus_pixmap_file (tile_icon_name); - - if (tile_icon_path != NULL) { - GdkPixbuf *tile_icon_pixbuf; - tile_icon_pixbuf = gdk_pixbuf_new_from_file (tile_icon_path); - g_free (tile_icon_path); - - if (tile_icon_pixbuf != NULL) { - nautilus_buffered_widget_set_tile_pixbuf (NAUTILUS_BUFFERED_WIDGET (image_widget), tile_icon_pixbuf); - gdk_pixbuf_unref (tile_icon_pixbuf); - } - else { - g_warning ("Could not find the requested tile_icon: %s", tile_icon_path); - } - } - } - - return image_widget; -} - -/* create and return an image widget using a themed nautilus icon name and a tiled background */ -GtkWidget* -create_image_widget (const char *icon_name, const char *tile_icon_name) -{ - GtkWidget *image_widget; - GdkPixbuf *pixbuf; - - g_return_val_if_fail (icon_name || tile_icon_name, NULL); - - pixbuf = NULL; - if (icon_name != NULL) { - char *icon_path; - - icon_path = nautilus_theme_get_image_path (icon_name); - if (icon_path != NULL) { - pixbuf = gdk_pixbuf_new_from_file (icon_path); - g_free (icon_path); - - if (pixbuf == NULL) { - g_warning ("Could not find the requested icon: %s", icon_path); - } - } - } - - /* create the image widget then release the pixbuf*/ - image_widget = create_image_widget_from_pixbuf (pixbuf, tile_icon_name); - if (pixbuf != NULL) { - gdk_pixbuf_unref (pixbuf); - } - return image_widget; -} - -/* create and return an image widget from a uri and a tiled background. - It also pins the image to the specified dimensions */ - -/* FIXME bugzilla.eazel.com 5138 - * this calls gnome-vfs synchronously for an HTTP uri and thus can block - * the UI indefinitely - */ -GtkWidget* -create_image_widget_from_uri (const char *uri, const char *tile_icon_name, - int max_width, int max_height) -{ - GtkWidget *image_widget; - GdkPixbuf *pixbuf, *scaled_pixbuf; - - g_return_val_if_fail (uri || tile_icon_name, NULL); - - /* as an optimization, it can be a local file. If it doesn't start with http://, - just pass it on to create_image_widget */ - if (!nautilus_istr_has_prefix (uri, "http://")) { - return create_image_widget (uri, tile_icon_name); - } - - /* load the image - synchronously, at least at first */ - pixbuf = nautilus_gdk_pixbuf_load (uri); - - /* pin the image to the specified dimensions if necessary */ - if (pixbuf && max_width > 0 && max_height > 0) { - scaled_pixbuf = nautilus_gdk_pixbuf_scale_down_to_fit (pixbuf, max_width, max_height); - gdk_pixbuf_unref (pixbuf); - pixbuf = scaled_pixbuf; - } - - /* create the image widget then release the pixbuf*/ - image_widget = create_image_widget_from_pixbuf (pixbuf, tile_icon_name); - if (pixbuf != NULL) { - gdk_pixbuf_unref (pixbuf); - } - - return image_widget; -} - -/* create a label widget with anti-aliased text and a tiled image background */ -GtkWidget* -create_label_widget (const char *text, - guint font_size, - const char *tile_icon_name, - guint xpad, - guint ypad, - gint horizontal_offset, - gint vertical_offset) -{ - GtkWidget *label; - - g_return_val_if_fail (text != NULL, NULL); - g_return_val_if_fail (font_size > 0, NULL); - - label = nautilus_label_new (text); - - nautilus_label_set_font_from_components (NAUTILUS_LABEL (label), "helvetica", "bold", NULL, NULL); - nautilus_label_set_font_size (NAUTILUS_LABEL (label), font_size); - nautilus_label_set_text_color (NAUTILUS_LABEL (label), NAUTILUS_RGB_COLOR_WHITE); - - if (tile_icon_name != NULL) { - char *tile_icon_path; - - tile_icon_path = nautilus_pixmap_file (tile_icon_name); - - if (tile_icon_path != NULL) { - GdkPixbuf *tile_icon_pixbuf; - tile_icon_pixbuf = gdk_pixbuf_new_from_file (tile_icon_path); - g_free (tile_icon_path); - - if (tile_icon_pixbuf != NULL) { - nautilus_buffered_widget_set_tile_pixbuf (NAUTILUS_BUFFERED_WIDGET (label), tile_icon_pixbuf); - gdk_pixbuf_unref (tile_icon_pixbuf); - } - else { - g_warning ("Could not find the requested tile_icon: %s", tile_icon_path); - } - } - } - - gtk_misc_set_padding (GTK_MISC (label), xpad, ypad); - - nautilus_buffered_widget_set_vertical_offset (NAUTILUS_BUFFERED_WIDGET (label), vertical_offset); - nautilus_buffered_widget_set_horizontal_offset (NAUTILUS_BUFFERED_WIDGET (label), horizontal_offset); - - return label; -} - -/* utility routine to show an error message */ -void -show_feedback (GtkWidget *widget, - char *error_message) -{ - nautilus_label_set_text (NAUTILUS_LABEL (widget), error_message); - gtk_widget_show (widget); -} - diff --git a/configure.in b/configure.in index 8c8ebf023..75145e199 100644 --- a/configure.in +++ b/configure.in @@ -325,6 +325,13 @@ AC_SUBST(LIBNAUTILUS_LIBS) LIBNAUTILUS_IDL_INCLUDES="`$PKG_CONFIG --variable=idldir $LIBNAUTILUS_MODULES | $srcdir/add-include-prefix`" AC_SUBST(LIBNAUTILUS_IDL_INCLUDES) +dnl libnautilus-extension +LIBNAUTILUS_EXTENSION_MODULES="glib-2.0 gtk+-2.0 gnome-vfs-2.0" +LIBNAUTILUS_EXTENSION_CFLAGS="`$PKG_CONFIG --cflags $LIBNAUTILUS_EXTENSION_MODULES`" +AC_SUBST(LIBNAUTILUS_EXTENSION_CFLAGS) +LIBNAUTILUS_EXTENSION_LIBS="`$PKG_CONFIG --libs $LIBNAUTILUS_EXTENSION_MODULES`" +AC_SUBST(LIBNAUTILUS_EXTENSION_LIBS) + dnl core nautilus (must list bonobo-activation and libbonobo because idldir does not respect "requires") CORE_MODULES="eel-2.0 librsvg-2.0 bonobo-activation-2.0 libbonobo-2.0 libbonoboui-2.0 esound gnome-desktop-2.0 $EXTRA_CORE_MODULES" CORE_CFLAGS="`$PKG_CONFIG --cflags $CORE_MODULES` $x_cflags" @@ -425,6 +432,8 @@ libnautilus-adapter/Makefile libnautilus-private/Makefile libnautilus/Makefile libnautilus/libnautilus.pc +libnautilus-extension/Makefile +libnautilus-extension/libnautilus-extension.pc nautilus.spec po/Makefile.in src/Makefile diff --git a/libnautilus-extension/Makefile.am b/libnautilus-extension/Makefile.am new file mode 100644 index 000000000..4d79b380f --- /dev/null +++ b/libnautilus-extension/Makefile.am @@ -0,0 +1,38 @@ +include $(top_srcdir)/Makefile.shared + +lib_LTLIBRARIES=libnautilus-extension.la + +INCLUDES=\ + -I$(top_srcdir) \ + -I$(top_builddir) \ + $(LIBNAUTILUS_EXTENSION_CFLAGS) \ + $(DISABLE_DEPRECATED_CFLAGS) \ + -DDATADIR=\""$(datadir)"\" \ + $(NULL) + +libnautilus_extension_la_LDFLAGS=\ + -version-info 1:0:0 \ + $(LIBNAUTILUS_EXTENSION_LIBS) \ + -no-undefined \ + $(NULL) + +libnautilus_extension_includedir=$(includedir)/nautilus/libnautilus-extension + +libnautilus_extension_include_HEADERS= \ + nautilus-extension-types.h \ + nautilus-file-info.h \ + nautilus-info-provider.h \ + $(NULL) + +libnautilus_extension_la_SOURCES= \ + nautilus-extension-types.c \ + nautilus-file-info.c \ + nautilus-info-provider.c \ + $(NULL) + +pkgconfigdir=$(libdir)/pkgconfig +pkgconfig_DATA=libnautilus-extension.pc + +EXTRA_DIST = \ + libnautilus-extension.pc.in \ + $(NULL) diff --git a/libnautilus-extension/libnautilus-extension.pc.in b/libnautilus-extension/libnautilus-extension.pc.in new file mode 100644 index 000000000..5286e9b9b --- /dev/null +++ b/libnautilus-extension/libnautilus-extension.pc.in @@ -0,0 +1,11 @@ +prefix=@prefix@ +exec_prefix=@exec_prefix@ +libdir=@libdir@ +includedir=@includedir@ + +Name: libnautilus-extension +Description: A library to create Nautilus view extensions +Version: @VERSION@ +Requires: glib-2.0 gtk+-2.0 gnome-vfs-2.0 +Libs: -L${libdir} -lnautilus-extension +Cflags: -I${includedir}/nautilus diff --git a/libnautilus-extension/nautilus-extension-types.c b/libnautilus-extension/nautilus-extension-types.c new file mode 100644 index 000000000..ee815fc10 --- /dev/null +++ b/libnautilus-extension/nautilus-extension-types.c @@ -0,0 +1,57 @@ +/* + * nautilus-extension-types.c - Type definitions for Nautilus extensions + * + * Copyright (C) 2003 Novell, Inc. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 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 + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the Free + * Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + * + * Author: Dave Camp <dave@ximian.com> + * + */ + +#include <config.h> +#include "nautilus-extension-types.h" + + +GType +nautilus_operation_result_get_type (void) +{ + static GType type = 0; + if (type == 0) { + static const GEnumValue values[] = { + { + NAUTILUS_OPERATION_COMPLETE, + "NAUTILUS_OPERATION_COMPLETE", + "complete", + }, + { + NAUTILUS_OPERATION_FAILED, + "NAUTILUS_OPERATION_FAILED", + "failed", + }, + { + NAUTILUS_OPERATION_IN_PROGRESS, + "NAUTILUS_OPERATION_IN_PROGRESS", + "in_progress", + }, + { 0, NULL, NULL } + }; + + type = g_enum_register_static ("NautilusOperationResult", + values); + } + + return type; +} diff --git a/libnautilus-extension/nautilus-extension-types.h b/libnautilus-extension/nautilus-extension-types.h new file mode 100644 index 000000000..806d17118 --- /dev/null +++ b/libnautilus-extension/nautilus-extension-types.h @@ -0,0 +1,67 @@ +/* + * nautilus-info-provider.h - Type definitions for Nautilus extensions + * + * Copyright (C) 2003 Novell, Inc. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 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 + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the Free + * Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + * + * Author: Dave Camp <dave@ximian.com> + * + */ + +/* This interface is implemented by Nautilus extensions that want to + * provide information about files. Extensions are called when Nautilus + * needs information about a file. They are passed a NautilusFileInfo + * object which should be filled with relevant information */ + +#ifndef NAUTILUS_EXTENSION_TYPES_H +#define NAUTILUS_EXTENSION_TYPES_H + +#include <glib-object.h> + +G_BEGIN_DECLS + +#define NAUTILUS_TYPE_OPERATION_RESULT (nautilus_operation_result_get_type ()) + +/* Handle for asynchronous interfaces. These are opaque handles that must + * be unique within an extension object. These are returned by operations + * that return NAUTILUS_OPERATION_IN_PROGRESS */ +typedef struct _NautilusOperationHandle NautilusOperationHandle; + +typedef enum { + /* Returned if the call succeeded, and the extension is done + * with the request */ + NAUTILUS_OPERATION_COMPLETE, + + /* Returned if the call failed */ + NAUTILUS_OPERATION_FAILED, + + /* Returned if the extension has begun an async operation. + * If this is returned, the extension must set the handle + * parameter and call the callback closure when the + * operation is complete. */ + NAUTILUS_OPERATION_IN_PROGRESS, +} NautilusOperationResult; + +GType nautilus_operation_result_get_type (void); + +void nautilus_module_initialize (GTypeModule *module); +void nautilus_module_shutdown (void); +void nautilus_module_list_types (const GType **types, + int *num_types); + +G_END_DECLS + +#endif diff --git a/libnautilus-extension/nautilus-file-info.c b/libnautilus-extension/nautilus-file-info.c new file mode 100644 index 000000000..2bbc2f4ec --- /dev/null +++ b/libnautilus-extension/nautilus-file-info.c @@ -0,0 +1,140 @@ +/* + * nautilus-file-info.c - Information about a file + * + * Copyright (C) 2003 Novell, Inc. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 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 + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the Free + * Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + * + */ + +#include <config.h> +#include "nautilus-file-info.h" + +static void +nautilus_file_info_base_init (gpointer g_class) +{ +} + +GType +nautilus_file_info_get_type (void) +{ + static GType type = 0; + + if (!type) { + static const GTypeInfo info = { + sizeof (NautilusFileInfoIface), + nautilus_file_info_base_init, + NULL, + NULL, + NULL, + NULL, + 0, + 0, + NULL + }; + + type = g_type_register_static (G_TYPE_INTERFACE, + "NautilusFileInfo", + &info, 0); + g_type_interface_add_prerequisite (type, G_TYPE_OBJECT); + } + + return type; +} + +gboolean +nautilus_file_info_is_gone (NautilusFileInfo *file) +{ + g_return_val_if_fail (NAUTILUS_IS_FILE_INFO (file), FALSE); + g_return_val_if_fail (NAUTILUS_FILE_INFO_GET_IFACE (file)->is_gone != NULL, FALSE); + + return NAUTILUS_FILE_INFO_GET_IFACE (file)->is_gone (file); +} + +char * +nautilus_file_info_get_name (NautilusFileInfo *file) +{ + g_return_val_if_fail (NAUTILUS_IS_FILE_INFO (file), NULL); + g_return_val_if_fail (NAUTILUS_FILE_INFO_GET_IFACE (file)->get_name != NULL, NULL); + + return NAUTILUS_FILE_INFO_GET_IFACE (file)->get_name (file); +} + +char * +nautilus_file_info_get_uri (NautilusFileInfo *file) +{ + g_return_val_if_fail (NAUTILUS_IS_FILE_INFO (file), NULL); + g_return_val_if_fail (NAUTILUS_FILE_INFO_GET_IFACE (file)->get_uri != NULL, NULL); + + return NAUTILUS_FILE_INFO_GET_IFACE (file)->get_uri (file); +} + +char * +nautilus_file_info_get_parent_uri (NautilusFileInfo *file) +{ + g_return_val_if_fail (NAUTILUS_IS_FILE_INFO (file), NULL); + g_return_val_if_fail (NAUTILUS_FILE_INFO_GET_IFACE (file)->get_uri != NULL, NULL); + + return NAUTILUS_FILE_INFO_GET_IFACE (file)->get_parent_uri (file); +} + +char * +nautilus_file_info_get_mime_type (NautilusFileInfo *file) +{ + g_return_val_if_fail (NAUTILUS_IS_FILE_INFO (file), NULL); + g_return_val_if_fail (NAUTILUS_FILE_INFO_GET_IFACE (file)->get_mime_type != NULL, NULL); + + return NAUTILUS_FILE_INFO_GET_IFACE (file)->get_mime_type (file); +} + +gboolean +nautilus_file_info_is_mime_type (NautilusFileInfo *file, + const char *mime_type) +{ + g_return_val_if_fail (NAUTILUS_IS_FILE_INFO (file), FALSE); + g_return_val_if_fail (mime_type != NULL, FALSE); + g_return_val_if_fail (NAUTILUS_FILE_INFO_GET_IFACE (file)->is_mime_type != NULL, FALSE); + + return NAUTILUS_FILE_INFO_GET_IFACE (file)->is_mime_type (file, + mime_type); +} + +gboolean +nautilus_file_info_is_directory (NautilusFileInfo *file) +{ + g_return_val_if_fail (NAUTILUS_IS_FILE_INFO (file), FALSE); + g_return_val_if_fail (NAUTILUS_FILE_INFO_GET_IFACE (file)->is_directory != NULL, FALSE); + + return NAUTILUS_FILE_INFO_GET_IFACE (file)->is_directory (file); +} + +GnomeVFSFileInfo * +nautilus_file_info_get_vfs_file_info (NautilusFileInfo *file) +{ + g_return_val_if_fail (NAUTILUS_IS_FILE_INFO (file), NULL); + g_return_val_if_fail (NAUTILUS_FILE_INFO_GET_IFACE (file)->get_vfs_file_info != NULL, NULL); + + return NAUTILUS_FILE_INFO_GET_IFACE (file)->get_vfs_file_info (file); +} + +void +nautilus_file_info_add_emblem (NautilusFileInfo *file, + const char *emblem_name) +{ + g_return_if_fail (NAUTILUS_IS_FILE_INFO (file)); + g_return_if_fail (NAUTILUS_FILE_INFO_GET_IFACE (file)->get_vfs_file_info != NULL); + + NAUTILUS_FILE_INFO_GET_IFACE (file)->add_emblem (file, emblem_name); +} diff --git a/libnautilus-extension/nautilus-file-info.h b/libnautilus-extension/nautilus-file-info.h new file mode 100644 index 000000000..fc73e8648 --- /dev/null +++ b/libnautilus-extension/nautilus-file-info.h @@ -0,0 +1,102 @@ +/* + * nautilus-file-info.h - Information about a file + * + * Copyright (C) 2003 Novell, Inc. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 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 + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the Free + * Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + * + */ + +/* NautilusFileInfo is an interface to the NautilusFile object. It + * provides access to the asynchronous data in the NautilusFile. + * Extensions are passed objects of this type for operations. */ + +#ifndef NAUTILUS_FILE_INFO_H +#define NAUTILUS_FILE_INFO_H + +#include <glib-object.h> +#include <libgnomevfs/gnome-vfs-file-info.h> + +G_BEGIN_DECLS + +#define NAUTILUS_TYPE_FILE_INFO (nautilus_file_info_get_type ()) +#define NAUTILUS_FILE_INFO(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), NAUTILUS_TYPE_FILE_INFO, NautilusFileInfo)) +#define NAUTILUS_IS_FILE_INFO(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), NAUTILUS_TYPE_FILE_INFO)) +#define NAUTILUS_FILE_INFO_GET_IFACE(obj) (G_TYPE_INSTANCE_GET_INTERFACE ((obj), NAUTILUS_TYPE_FILE_INFO, NautilusFileInfoIface)) + + +#ifndef NAUTILUS_FILE_DEFINED +#define NAUTILUS_FILE_DEFINED +/* Using NautilusFile for the vtable to make implementing this in + * NautilusFile easier */ +typedef struct NautilusFile NautilusFile; +#endif + +typedef NautilusFile NautilusFileInfo; +typedef struct _NautilusFileInfoIface NautilusFileInfoIface; + + +struct _NautilusFileInfoIface +{ + gboolean (*is_gone) (NautilusFileInfo *file); + + char * (*get_name) (NautilusFileInfo *file); + char * (*get_uri) (NautilusFileInfo *file); + char * (*get_parent_uri) (NautilusFileInfo *file); + + char * (*get_mime_type) (NautilusFileInfo *file); + gboolean (*is_mime_type) (NautilusFileInfo *file, + const char *mime_Type); + gboolean (*is_directory) (NautilusFileInfo *file); + + GnomeVFSFileInfo *(*get_vfs_file_info) (NautilusFileInfo *file); + + void (*add_emblem) (NautilusFileInfo *file, + const char *emblem_name); + +}; + +GType nautilus_file_info_get_type (void); + + +/* Return true if the file has been deleted */ +gboolean nautilus_file_info_is_gone (NautilusFileInfo *file); + + +/* Name and Location */ +char * nautilus_file_info_get_name (NautilusFileInfo *file); +char * nautilus_file_info_get_uri (NautilusFileInfo *file); +char * nautilus_file_info_get_parent_uri (NautilusFileInfo *file); + + +/* File Type */ +char * nautilus_file_info_get_mime_type (NautilusFileInfo *file); +gboolean nautilus_file_info_is_mime_type (NautilusFileInfo *file, + const char *mime_type); +gboolean nautilus_file_info_is_directory (NautilusFileInfo *file); + + +/* Other File Info */ +GnomeVFSFileInfo *nautilus_file_info_get_vfs_file_info (NautilusFileInfo *file); + + +/* Modifying the NautilusFileInfo */ +void nautilus_file_info_add_emblem (NautilusFileInfo *file, + const char *emblem_name); + + +G_END_DECLS + +#endif diff --git a/libnautilus-extension/nautilus-info-provider.c b/libnautilus-extension/nautilus-info-provider.c new file mode 100644 index 000000000..942245190 --- /dev/null +++ b/libnautilus-extension/nautilus-info-provider.c @@ -0,0 +1,120 @@ +/* + * nautilus-info-provider.c - Interface for Nautilus extensions that + * provide info about files. + * + * Copyright (C) 2003 Novell, Inc. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 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 + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the Free + * Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + * + * Author: Dave Camp <dave@ximian.com> + * + */ + +#include <config.h> +#include "nautilus-info-provider.h" + +#include <glib-object.h> + +static void +nautilus_info_provider_base_init (gpointer g_class) +{ +} + +GType +nautilus_info_provider_get_type (void) +{ + static GType type = 0; + + if (!type) { + static const GTypeInfo info = { + sizeof (NautilusInfoProviderIface), + nautilus_info_provider_base_init, + NULL, + NULL, + NULL, + NULL, + 0, + 0, + NULL + }; + + type = g_type_register_static (G_TYPE_INTERFACE, + "NautilusInfoProvider", + &info, 0); + g_type_interface_add_prerequisite (type, G_TYPE_OBJECT); + } + + return type; +} + +NautilusOperationResult +nautilus_info_provider_update_file_info (NautilusInfoProvider *provider, + NautilusFileInfo *file, + GClosure *update_complete, + NautilusOperationHandle **handle) +{ + g_return_val_if_fail (NAUTILUS_IS_INFO_PROVIDER (provider), + NAUTILUS_OPERATION_FAILED); + g_return_val_if_fail (NAUTILUS_INFO_PROVIDER_GET_IFACE (provider)->update_file_info != NULL, + NAUTILUS_OPERATION_FAILED); + g_return_val_if_fail (update_complete != NULL, + NAUTILUS_OPERATION_FAILED); + g_return_val_if_fail (handle != NULL, NAUTILUS_OPERATION_FAILED); + + return NAUTILUS_INFO_PROVIDER_GET_IFACE (provider)->update_file_info + (provider, file, update_complete, handle); +} + +void +nautilus_info_provider_cancel_update (NautilusInfoProvider *provider, + NautilusOperationHandle *handle) +{ + g_return_if_fail (NAUTILUS_IS_INFO_PROVIDER (provider)); + g_return_if_fail (NAUTILUS_INFO_PROVIDER_GET_IFACE (provider)->cancel_update != NULL); + g_return_if_fail (NAUTILUS_INFO_PROVIDER_GET_IFACE (provider)->cancel_update != NULL); + g_return_if_fail (handle != NULL); + + NAUTILUS_INFO_PROVIDER_GET_IFACE (provider)->cancel_update (provider, + handle); +} + +void +nautilus_info_provider_update_complete_invoke (GClosure *update_complete, + NautilusInfoProvider *provider, + NautilusOperationHandle *handle, + NautilusOperationResult result) +{ + GValue args[3] = { { 0, } }; + GValue return_val = { 0, }; + + g_return_if_fail (update_complete != NULL); + g_return_if_fail (NAUTILUS_IS_INFO_PROVIDER (provider)); + + g_value_init (&args[0], NAUTILUS_TYPE_INFO_PROVIDER); + g_value_init (&args[1], G_TYPE_POINTER); + g_value_init (&args[2], NAUTILUS_TYPE_OPERATION_RESULT); + + g_value_set_object (&args[0], provider); + g_value_set_pointer (&args[1], handle); + g_value_set_enum (&args[2], result); + + g_closure_invoke (update_complete, &return_val, 3, args, NULL); + + g_value_unset (&args[0]); + g_value_unset (&args[1]); + g_value_unset (&args[2]); +} + + diff --git a/libnautilus-extension/nautilus-info-provider.h b/libnautilus-extension/nautilus-info-provider.h new file mode 100644 index 000000000..50e01d4c0 --- /dev/null +++ b/libnautilus-extension/nautilus-info-provider.h @@ -0,0 +1,80 @@ +/* + * nautilus-info-provider.h - Interface for Nautilus extensions that + * provide info about files. + * + * Copyright (C) 2003 Novell, Inc. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 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 + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the Free + * Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + * + * Author: Dave Camp <dave@ximian.com> + * + */ + +/* This interface is implemented by Nautilus extensions that want to + * provide information about files. Extensions are called when Nautilus + * needs information about a file. They are passed a NautilusFileInfo + * object which should be filled with relevant information */ + +#ifndef NAUTILUS_INFO_PROVIDER_H +#define NAUTILUS_INFO_PROVIDER_H + +#include <glib-object.h> +#include "nautilus-extension-types.h" +#include "nautilus-file-info.h" + +G_BEGIN_DECLS + +#define NAUTILUS_TYPE_INFO_PROVIDER (nautilus_info_provider_get_type ()) +#define NAUTILUS_INFO_PROVIDER(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), NAUTILUS_TYPE_INFO_PROVIDER, NautilusInfoProvider)) +#define NAUTILUS_IS_INFO_PROVIDER(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), NAUTILUS_TYPE_INFO_PROVIDER)) +#define NAUTILUS_INFO_PROVIDER_GET_IFACE(obj) (G_TYPE_INSTANCE_GET_INTERFACE ((obj), NAUTILUS_TYPE_INFO_PROVIDER, NautilusInfoProviderIface)) + +typedef struct _NautilusInfoProvider NautilusInfoProvider; +typedef struct _NautilusInfoProviderIface NautilusInfoProviderIface; + +typedef void (*NautilusInfoProviderUpdateComplete) (NautilusInfoProvider *provider, + NautilusOperationHandle *handle, + NautilusOperationResult result, + gpointer user_data); + +struct _NautilusInfoProviderIface { + NautilusOperationResult (*update_file_info) (NautilusInfoProvider *provider, + NautilusFileInfo *file, + GClosure *update_complete, + NautilusOperationHandle **handle); + void (*cancel_update) (NautilusInfoProvider *provider, + NautilusOperationHandle *handle); +}; + +/* Interface Functions */ +GType nautilus_info_provider_get_type (void); +NautilusOperationResult nautilus_info_provider_update_file_info (NautilusInfoProvider *provider, + NautilusFileInfo *file, + GClosure *update_complete, + NautilusOperationHandle **handle); +void nautilus_info_provider_cancel_update (NautilusInfoProvider *provider, + NautilusOperationHandle *handle); + + + +/* Helper functions for implementations */ +void nautilus_info_provider_update_complete_invoke (GClosure *update_complete, + NautilusInfoProvider *provider, + NautilusOperationHandle *handle, + NautilusOperationResult result); + +G_END_DECLS + +#endif diff --git a/libnautilus-private/Makefile.am b/libnautilus-private/Makefile.am index 8d66a8601..06e425617 100644 --- a/libnautilus-private/Makefile.am +++ b/libnautilus-private/Makefile.am @@ -2,7 +2,9 @@ include $(top_srcdir)/Makefile.shared lib_LTLIBRARIES=libnautilus-private.la -libnautilus_private_la_LIBADD = ../libnautilus/libnautilus.la +libnautilus_private_la_LIBADD = \ + ../libnautilus/libnautilus.la \ + ../libnautilus-extension/libnautilus-extension.la INCLUDES = \ -I$(top_srcdir) \ @@ -13,6 +15,7 @@ INCLUDES = \ -DDATADIR=\""$(datadir)"\" \ -DSYSCONFDIR=\""$(sysconfdir)"\" \ -DNAUTILUS_DATADIR=\""$(datadir)/nautilus"\" \ + -DNAUTILUS_EXTENSIONDIR=\""$(libdir)/nautilus/extensions-1.0"\" \ $(NULL) dependency_static_libs = \ @@ -138,6 +141,8 @@ libnautilus_private_la_SOURCES = \ nautilus-metafile.h \ nautilus-mime-actions.c \ nautilus-mime-actions.h \ + nautilus-module.c \ + nautilus-module.h \ nautilus-monitor.c \ nautilus-monitor.h \ nautilus-program-chooser.c \ diff --git a/libnautilus-private/nautilus-directory-async.c b/libnautilus-private/nautilus-directory-async.c index 343dd4db3..ab6394dd7 100644 --- a/libnautilus-private/nautilus-directory-async.c +++ b/libnautilus-private/nautilus-directory-async.c @@ -32,6 +32,7 @@ #include "nautilus-file-utilities.h" #include "nautilus-global-preferences.h" #include "nautilus-link.h" +#include "nautilus-marshal.h" #include "nautilus-metafile.h" #include "nautilus-search-uri.h" #include <eel/eel-glib-extensions.h> @@ -94,6 +95,13 @@ typedef struct { Request request; } Monitor; +typedef struct { + NautilusDirectory *directory; + NautilusInfoProvider *provider; + NautilusOperationHandle *handle; + NautilusOperationResult result; +} InfoProviderResponse; + typedef gboolean (* RequestCheck) (const Request *); typedef gboolean (* FileCheck) (NautilusFile *); @@ -127,8 +135,12 @@ static gboolean file_needs_high_priority_work_done (NautilusDirectory *directory NautilusFile *file); static gboolean file_needs_low_priority_work_done (NautilusDirectory *directory, NautilusFile *file); +static gboolean file_needs_extension_work_done (NautilusDirectory *directory, + NautilusFile *file); static void move_file_to_low_priority_queue (NautilusDirectory *directory, NautilusFile *file); +static void move_file_to_extension_queue (NautilusDirectory *directory, + NautilusFile *file); void @@ -571,6 +583,8 @@ nautilus_directory_set_up_request (Request *request, request->metafile |= (file_attributes & NAUTILUS_FILE_ATTRIBUTE_METADATA) != FALSE; + + request->extension_info = (file_attributes & NAUTILUS_FILE_ATTRIBUTE_EXTENSION_INFO) != FALSE; } static void @@ -1748,6 +1762,17 @@ wants_link_info (const Request *request) return request->link_info; } +static gboolean +lacks_extension_info (NautilusFile *file) +{ + return file->details->pending_info_providers != NULL; +} + +static gboolean +wants_extension_info (const Request *request) +{ + return request->extension_info; +} static gboolean has_problem (NautilusDirectory *directory, NautilusFile *file, FileCheck problem) @@ -3136,6 +3161,153 @@ link_info_start (NautilusDirectory *directory, } static void +extension_info_cancel (NautilusDirectory *directory) +{ + if (directory->details->extension_info_in_progress != NULL) { + nautilus_info_provider_cancel_update + (directory->details->extension_info_provider, + directory->details->extension_info_in_progress); + + directory->details->extension_info_in_progress = NULL; + directory->details->extension_info_file = NULL; + directory->details->extension_info_provider = NULL; + + async_job_end (directory, "extension info"); + } +} + +static void +extension_info_stop (NautilusDirectory *directory) +{ + if (directory->details->extension_info_in_progress != NULL) { + NautilusFile *file; + + file = directory->details->extension_info_file; + if (file != NULL) { + g_assert (NAUTILUS_IS_FILE (file)); + g_assert (file->details->directory == directory); + if (is_needy (file, lacks_extension_info, wants_extension_info)) { + return; + } + } + + /* The info is not wanted, so stop it. */ + extension_info_cancel (directory); + } +} + +static void +finish_info_provider (NautilusDirectory *directory, + NautilusFile *file, + NautilusInfoProvider *provider) +{ + file->details->pending_info_providers = + g_list_remove (file->details->pending_info_providers, + provider); + g_object_unref (provider); + + nautilus_directory_async_state_changed (directory); + + if (file->details->pending_info_providers == NULL) { + nautilus_file_info_providers_done (file); + } +} + + +static gboolean +info_provider_idle_callback (gpointer user_data) +{ + InfoProviderResponse *response; + NautilusDirectory *directory; + + response = user_data; + directory = response->directory; + + if (response->handle != directory->details->extension_info_in_progress + || response->provider != directory->details->extension_info_provider) { + g_warning ("Unexpected plugin response. This probably indicates a bug in a Nautilus extension: handle=%p", response->handle); + } else { + NautilusFile *file; + async_job_end (directory, "extension info"); + + file = directory->details->extension_info_file; + + directory->details->extension_info_file = NULL; + directory->details->extension_info_provider = NULL; + directory->details->extension_info_in_progress = NULL; + + finish_info_provider (directory, file, response->provider); + } + + return FALSE; +} + +static void +info_provider_callback (NautilusInfoProvider *provider, + NautilusOperationHandle *handle, + NautilusOperationResult result, + gpointer user_data) +{ + InfoProviderResponse *response; + + response = g_new0 (InfoProviderResponse, 1); + response->provider = provider; + response->handle = handle; + response->result = result; + response->directory = NAUTILUS_DIRECTORY (user_data); + + g_idle_add (info_provider_idle_callback, response); +} + +static void +extension_info_start (NautilusDirectory *directory, + NautilusFile *file) +{ + NautilusInfoProvider *provider; + NautilusOperationResult result; + NautilusOperationHandle *handle; + GClosure *update_complete; + + if (directory->details->extension_info_in_progress != NULL) { + return; + } + + if (!is_needy (file, lacks_extension_info, wants_extension_info)) { + return; + } + + if (!async_job_start (directory, "extension info")) { + return; + } + + provider = file->details->pending_info_providers->data; + + update_complete = g_cclosure_new (G_CALLBACK (info_provider_callback), + directory, + NULL); + g_closure_set_marshal (update_complete, + nautilus_marshal_VOID__POINTER_ENUM); + + result = nautilus_info_provider_update_file_info + (provider, + NAUTILUS_FILE_INFO (file), + update_complete, + &handle); + + g_closure_unref (update_complete); + + if (result == NAUTILUS_OPERATION_COMPLETE || + result == NAUTILUS_OPERATION_FAILED) { + finish_info_provider (directory, file, provider); + async_job_end (directory, "extension info"); + } else { + directory->details->extension_info_in_progress = handle; + directory->details->extension_info_provider = provider; + directory->details->extension_info_file = file; + } +} + +static void start_or_stop_io (NautilusDirectory *directory) { NautilusFile *file; @@ -3150,6 +3322,7 @@ start_or_stop_io (NautilusDirectory *directory) mime_list_stop (directory); top_left_stop (directory); link_info_stop (directory); + extension_info_stop (directory); /* Take files that are all done off the queue. */ while (!nautilus_file_queue_is_empty (directory->details->high_priority_queue)) { @@ -3177,6 +3350,20 @@ start_or_stop_io (NautilusDirectory *directory) top_left_start (directory, file); return; } else { + move_file_to_extension_queue (directory, file); + + } + } + + /* Low priority queue must be empty */ + while (!nautilus_file_queue_is_empty (directory->details->extension_queue)) { + file = nautilus_file_queue_head (directory->details->extension_queue); + + if (file_needs_extension_work_done (directory, file)) { + /* Start getting attributes if possible */ + extension_info_start (directory, file); + return; + } else { nautilus_directory_remove_file_from_work_queue (directory, file); } @@ -3228,6 +3415,7 @@ nautilus_directory_cancel (NautilusDirectory *directory) link_info_cancel (directory); mime_list_cancel (directory); top_left_cancel (directory); + extension_info_cancel (directory); /* We aren't waiting for anything any more. */ if (waiting_directories != NULL) { @@ -3322,6 +3510,10 @@ cancel_loading_attributes (NautilusDirectory *directory, if (request.link_info) { link_info_cancel (directory); } + + if (request.extension_info) { + extension_info_cancel (directory); + } /* FIXME bugzilla.gnome.org 45064: implement cancelling metadata when we implement invalidating metadata */ @@ -3407,11 +3599,23 @@ file_needs_low_priority_work_done (NautilusDirectory *directory, } static gboolean +file_needs_extension_work_done (NautilusDirectory *directory, + NautilusFile *file) +{ + if (is_needy (file, lacks_extension_info, wants_extension_info)) { + return TRUE; + } + + return FALSE; +} + +static gboolean file_needs_work_done (NautilusDirectory *directory, NautilusFile *file) { return (file_needs_high_priority_work_done (directory, file) || - file_needs_low_priority_work_done (directory, file)); + file_needs_low_priority_work_done (directory, file) || + file_needs_extension_work_done (directory, file)); } @@ -3451,6 +3655,8 @@ nautilus_directory_remove_file_from_work_queue (NautilusDirectory *directory, file); nautilus_file_queue_remove (directory->details->low_priority_queue, file); + nautilus_file_queue_remove (directory->details->extension_queue, + file); } @@ -3458,15 +3664,32 @@ static void move_file_to_low_priority_queue (NautilusDirectory *directory, NautilusFile *file) { + /* Must add before removing to avoid ref underflow */ + nautilus_file_queue_enqueue (directory->details->low_priority_queue, + file); + nautilus_file_queue_remove (directory->details->high_priority_queue, + file); + if (!file_needs_low_priority_work_done (directory, file)) { - nautilus_file_queue_remove (directory->details->high_priority_queue, + move_file_to_extension_queue (directory, file); + + return; + } +} + +static void +move_file_to_extension_queue (NautilusDirectory *directory, + NautilusFile *file) +{ + if (!file_needs_extension_work_done (directory, file)) { + nautilus_file_queue_remove (directory->details->low_priority_queue, file); return; } /* Must add before removing to avoid ref underflow */ - nautilus_file_queue_enqueue (directory->details->low_priority_queue, + nautilus_file_queue_enqueue (directory->details->extension_queue, file); - nautilus_file_queue_remove (directory->details->high_priority_queue, + nautilus_file_queue_remove (directory->details->low_priority_queue, file); } diff --git a/libnautilus-private/nautilus-directory-private.h b/libnautilus-private/nautilus-directory-private.h index fc4cd5d72..9dc3bae98 100644 --- a/libnautilus-private/nautilus-directory-private.h +++ b/libnautilus-private/nautilus-directory-private.h @@ -33,6 +33,7 @@ #include <libnautilus-private/nautilus-metafile-server.h> #include <libnautilus-private/nautilus-monitor.h> #include <libnautilus/nautilus-idle-queue.h> +#include <libnautilus-extension/nautilus-info-provider.h> #include <libxml/tree.h> typedef struct LinkInfoReadState LinkInfoReadState; @@ -53,6 +54,7 @@ struct NautilusDirectoryDetails /* Queues of files needing some I/O done. */ NautilusFileQueue *high_priority_queue; NautilusFileQueue *low_priority_queue; + NautilusFileQueue *extension_queue; /* These lists are going to be pretty short. If we think they * are going to get big, we can use hash tables instead. @@ -100,6 +102,10 @@ struct NautilusDirectoryDetails NautilusFile *get_info_file; GnomeVFSAsyncHandle *get_info_in_progress; + NautilusFile *extension_info_file; + NautilusInfoProvider *extension_info_provider; + NautilusOperationHandle *extension_info_in_progress; + TopLeftTextReadState *top_left_read_state; LinkInfoReadState *link_info_read_state; @@ -119,6 +125,7 @@ typedef struct { gboolean metafile; gboolean mime_list; gboolean top_left_text; + gboolean extension_info; } Request; NautilusDirectory *nautilus_directory_get_existing (const char *uri); diff --git a/libnautilus-private/nautilus-directory.c b/libnautilus-private/nautilus-directory.c index 1c20e942f..7c2fd2e19 100644 --- a/libnautilus-private/nautilus-directory.c +++ b/libnautilus-private/nautilus-directory.c @@ -133,6 +133,7 @@ nautilus_directory_init (gpointer object, gpointer klass) directory->details->file_hash = g_hash_table_new (g_str_hash, g_str_equal); directory->details->high_priority_queue = nautilus_file_queue_new (); directory->details->low_priority_queue = nautilus_file_queue_new (); + directory->details->extension_queue = nautilus_file_queue_new (); directory->details->idle_queue = nautilus_idle_queue_new (); directory->details->hidden_file_hash = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, NULL); @@ -207,6 +208,7 @@ nautilus_directory_finalize (GObject *object) nautilus_file_queue_destroy (directory->details->high_priority_queue); nautilus_file_queue_destroy (directory->details->low_priority_queue); + nautilus_file_queue_destroy (directory->details->extension_queue); nautilus_idle_queue_destroy (directory->details->idle_queue); g_assert (directory->details->directory_load_in_progress == NULL); g_assert (directory->details->count_in_progress == NULL); @@ -1023,6 +1025,7 @@ nautilus_directory_notify_files_changed (GList *uris) file->details->file_info_is_up_to_date = FALSE; file->details->top_left_text_is_up_to_date = FALSE; file->details->link_info_is_up_to_date = FALSE; + nautilus_file_invalidate_extension_info_internal (file); hash_table_list_prepend (changed_lists, file->details->directory, diff --git a/libnautilus-private/nautilus-file-attributes.h b/libnautilus-private/nautilus-file-attributes.h index 38e1da94f..ba02bd426 100644 --- a/libnautilus-private/nautilus-file-attributes.h +++ b/libnautilus-private/nautilus-file-attributes.h @@ -43,6 +43,7 @@ typedef enum { NAUTILUS_FILE_ATTRIBUTE_TOP_LEFT_TEXT = 1 << 10, NAUTILUS_FILE_ATTRIBUTE_DISPLAY_NAME = 1 << 11, NAUTILUS_FILE_ATTRIBUTE_VOLUMES = 1 << 12, + NAUTILUS_FILE_ATTRIBUTE_EXTENSION_INFO = 1 << 13, } NautilusFileAttributes; #endif /* NAUTILUS_FILE_ATTRIBUTES_H */ diff --git a/libnautilus-private/nautilus-file-operations.c b/libnautilus-private/nautilus-file-operations.c index 3f9586caf..2278f8771 100644 --- a/libnautilus-private/nautilus-file-operations.c +++ b/libnautilus-private/nautilus-file-operations.c @@ -37,14 +37,19 @@ #include <eel/eel-stock-dialogs.h> #include <eel/eel-vfs-extensions.h> -#include <gnome.h> +#include <libgnome/gnome-i18n.h> #include <gtk/gtklabel.h> +#include <gtk/gtkstock.h> +#include <gtk/gtkhbox.h> +#include <gtk/gtkimage.h> +#include <gtk/gtkvbox.h> #include <libgnomevfs/gnome-vfs-async-ops.h> #include <libgnomevfs/gnome-vfs-find-directory.h> #include <libgnomevfs/gnome-vfs-ops.h> #include <libgnomevfs/gnome-vfs-result.h> #include <libgnomevfs/gnome-vfs-uri.h> #include <libgnomevfs/gnome-vfs-utils.h> +#include <stdio.h> #include "nautilus-file-changes-queue.h" #include "nautilus-file-private.h" #include "nautilus-desktop-icon-file.h" diff --git a/libnautilus-private/nautilus-file-private.h b/libnautilus-private/nautilus-file-private.h index 443f57da7..b7aae13db 100644 --- a/libnautilus-private/nautilus-file-private.h +++ b/libnautilus-private/nautilus-file-private.h @@ -93,7 +93,14 @@ struct NautilusFileDetails /* We use this to cache automatic emblems and emblem keywords to speed up compare_by_emblems. */ NautilusFileSortByEmblemCache *compare_by_emblem_cache; - + + /* NautilusInfoProviders that need to be run for this file */ + GList *pending_info_providers; + + /* Emblems provided by extensions */ + GList *extension_emblems; + GList *pending_extension_emblems; + /* boolean fields: bitfield to save space, since there can be many NautilusFile objects. */ @@ -171,13 +178,15 @@ gboolean nautilus_file_should_get_top_left_text (NautilusFile /* Mark specified attributes for this file out of date without canceling current * I/O or kicking off new I/O. */ -void nautilus_file_invalidate_attributes_internal (NautilusFile *file, - NautilusFileAttributes file_attributes); -NautilusFileAttributes nautilus_file_get_all_attributes (void); -gboolean nautilus_file_is_self_owned (NautilusFile *file); -void nautilus_file_invalidate_count_and_mime_list (NautilusFile *file); -gboolean nautilus_file_rename_in_progress (NautilusFile *file); -GnomeVFSFileInfo * nautilus_file_peek_vfs_file_info (NautilusFile *file); +void nautilus_file_invalidate_attributes_internal (NautilusFile *file, + NautilusFileAttributes file_attributes); +NautilusFileAttributes nautilus_file_get_all_attributes (void); +gboolean nautilus_file_is_self_owned (NautilusFile *file); +void nautilus_file_invalidate_count_and_mime_list (NautilusFile *file); +gboolean nautilus_file_rename_in_progress (NautilusFile *file); +GnomeVFSFileInfo * nautilus_file_peek_vfs_file_info (NautilusFile *file); +void nautilus_file_invalidate_extension_info_internal (NautilusFile *file); +void nautilus_file_info_providers_done (NautilusFile *file); /* Thumbnailing: */ diff --git a/libnautilus-private/nautilus-file.c b/libnautilus-private/nautilus-file.c index 1dee388cc..77d5fc121 100644 --- a/libnautilus-private/nautilus-file.c +++ b/libnautilus-private/nautilus-file.c @@ -39,6 +39,7 @@ #include "nautilus-link.h" #include "nautilus-link-desktop-file.h" #include "nautilus-metadata.h" +#include "nautilus-module.h" #include "nautilus-thumbnails.h" #include "nautilus-trash-directory.h" #include "nautilus-trash-file.h" @@ -59,6 +60,7 @@ #include <libgnomevfs/gnome-vfs-volume.h> #include <libgnomevfs/gnome-vfs-volume-monitor.h> #include <libgnomevfs/gnome-vfs-drive.h> +#include <libnautilus-extension/nautilus-file-info.h> #include <libxml/parser.h> #include <pwd.h> #include <stdlib.h> @@ -110,24 +112,62 @@ enum { static guint signals[LAST_SIGNAL]; -static GHashTable *symbolic_links; - -static char * nautilus_file_get_owner_as_string (NautilusFile *file, - gboolean include_real_name); -static char * nautilus_file_get_type_as_string (NautilusFile *file); -static gboolean update_info_and_name (NautilusFile *file, - GnomeVFSFileInfo *info); -static char * nautilus_file_get_display_name_nocopy (NautilusFile *file); -static char * nautilus_file_get_display_name_collation_key (NautilusFile *file); +static GObjectClass *parent_class = NULL; +static GHashTable *symbolic_links; -GNOME_CLASS_BOILERPLATE (NautilusFile, nautilus_file, - GObject, G_TYPE_OBJECT) +static void nautilus_file_instance_init (NautilusFile *file); +static void nautilus_file_class_init (NautilusFileClass *class); +static void nautilus_file_info_iface_init (NautilusFileInfoIface *iface); +static char * nautilus_file_get_owner_as_string (NautilusFile *file, + gboolean include_real_name); +static char * nautilus_file_get_type_as_string (NautilusFile *file); +static gboolean update_info_and_name (NautilusFile *file, + GnomeVFSFileInfo *info); +static char * nautilus_file_get_display_name_nocopy (NautilusFile *file); +static char * nautilus_file_get_display_name_collation_key (NautilusFile *file); + +GType +nautilus_file_get_type (void) +{ + static GType type = 0; + + if (!type) { + static const GTypeInfo info = { + sizeof (NautilusFileClass), + NULL, + NULL, + (GClassInitFunc) nautilus_file_class_init, + NULL, + NULL, + sizeof (NautilusFile), + 0, + (GInstanceInitFunc) nautilus_file_instance_init, + }; + + static const GInterfaceInfo file_info_iface_info = { + (GInterfaceInitFunc) nautilus_file_info_iface_init, + NULL, + NULL + }; + + type = g_type_register_static (G_TYPE_OBJECT, + "NautilusFile", + &info, 0); + g_type_add_interface_static (type, + NAUTILUS_TYPE_FILE_INFO, + &file_info_iface_info); + } + + return type; +} static void nautilus_file_instance_init (NautilusFile *file) { file->details = g_new0 (NautilusFileDetails, 1); + + nautilus_file_invalidate_extension_info_internal (file); } static NautilusFile * @@ -4695,7 +4735,10 @@ nautilus_file_get_keywords (NautilusFile *file) /* Put all the keywords into a list. */ keywords = nautilus_file_get_metadata_list (file, "keyword", "name"); - + + keywords = g_list_concat (keywords, eel_g_str_list_copy (file->details->extension_emblems)); + keywords = g_list_concat (keywords, eel_g_str_list_copy (file->details->pending_extension_emblems)); + return sort_keyword_list_and_remove_duplicates (keywords); } @@ -5279,7 +5322,6 @@ invalidate_directory_count (NautilusFile *file) file->details->directory_count_is_up_to_date = FALSE; } - static void invalidate_deep_counts (NautilusFile *file) { @@ -5311,6 +5353,13 @@ invalidate_link_info (NautilusFile *file) } void +nautilus_file_invalidate_extension_info_internal (NautilusFile *file) +{ + file->details->pending_info_providers = + nautilus_module_get_extensions_for_type (NAUTILUS_TYPE_INFO_PROVIDER); +} + +void nautilus_file_invalidate_attributes_internal (NautilusFile *file, NautilusFileAttributes file_attributes) { @@ -5348,6 +5397,9 @@ nautilus_file_invalidate_attributes_internal (NautilusFile *file, if (request.link_info) { invalidate_link_info (file); } + if (request.extension_info) { + nautilus_file_invalidate_extension_info_internal (file); + } /* FIXME bugzilla.gnome.org 45075: implement invalidating metadata */ } @@ -5619,6 +5671,8 @@ nautilus_extract_top_left_text (const char *text, static void nautilus_file_class_init (NautilusFileClass *class) { + parent_class = g_type_class_peek_parent (class); + G_OBJECT_CLASS (class)->finalize = finalize; signals[CHANGED] = @@ -5640,6 +5694,50 @@ nautilus_file_class_init (NautilusFileClass *class) G_TYPE_NONE, 0); } +static GnomeVFSFileInfo * +nautilus_file_get_vfs_file_info (NautilusFile *file) +{ + return gnome_vfs_file_info_dup (file->details->info); +} + +static void +nautilus_file_add_emblem (NautilusFile *file, + const char *emblem_name) +{ + if (file->details->pending_info_providers) { + file->details->pending_extension_emblems = g_list_prepend (file->details->pending_extension_emblems, + g_strdup (emblem_name)); + } else { + file->details->extension_emblems = g_list_prepend (file->details->extension_emblems, + g_strdup (emblem_name)); + } + + nautilus_file_changed (file); +} + +void +nautilus_file_info_providers_done (NautilusFile *file) +{ + eel_g_list_free_deep (file->details->extension_emblems); + file->details->extension_emblems = file->details->pending_extension_emblems; + file->details->pending_extension_emblems = NULL; + nautilus_file_changed (file); +} + +static void +nautilus_file_info_iface_init (NautilusFileInfoIface *iface) +{ + iface->is_gone = nautilus_file_is_gone; + iface->get_name = nautilus_file_get_name; + iface->get_uri = nautilus_file_get_uri; + iface->get_parent_uri = nautilus_file_get_parent_uri; + iface->get_mime_type = nautilus_file_get_mime_type; + iface->is_mime_type = nautilus_file_is_mime_type; + iface->is_directory = nautilus_file_is_directory; + iface->get_vfs_file_info = nautilus_file_get_vfs_file_info; + iface->add_emblem = nautilus_file_add_emblem; +} + #if !defined (NAUTILUS_OMIT_SELF_CHECK) void diff --git a/libnautilus-private/nautilus-marshal.list b/libnautilus-private/nautilus-marshal.list index c0d617827..3261b785f 100644 --- a/libnautilus-private/nautilus-marshal.list +++ b/libnautilus-private/nautilus-marshal.list @@ -13,3 +13,4 @@ VOID:POINTER,STRING VOID:STRING,STRING VOID:POINTER,POINTER,POINTER,INT,INT,INT VOID:POINTER,STRING,UINT,INT,INT +VOID:POINTER,ENUM diff --git a/libnautilus-private/nautilus-module.c b/libnautilus-private/nautilus-module.c new file mode 100644 index 000000000..b61269dd0 --- /dev/null +++ b/libnautilus-private/nautilus-module.c @@ -0,0 +1,243 @@ +/* + * nautilus-module.h - Interface to nautilus extensions + * + * Copyright (C) 2003 Novell, Inc. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 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 + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the Free + * Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + * + * Author: Dave Camp <dave@ximian.com> + * + */ + +#include <config.h> +#include "nautilus-module.h" + +#include <eel/eel-gtk-macros.h> +#include <gmodule.h> +#include <libgnome/gnome-macros.h> + + +#define NAUTILUS_TYPE_MODULE (nautilus_module_get_type ()) +#define NAUTILUS_MODULE(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), NAUTILUS_TYPE_MODULE, NautilusModule)) +#define NAUTILUS_MODULE_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), NAUTILUS_TYPE_MODULE, NautilusModule)) +#define NAUTILUS_IS_MODULE(obj) (G_TYPE_INSTANCE_CHECK_TYPE ((obj), NAUTILUS_TYPE_MODULE)) +#define NAUTILUS_IS_MODULE_CLASS(klass) (G_TYPE_CLASS_CHECK_CLASS_TYPE ((klass), NAUTILUS_TYPE_MODULE)) + +typedef struct _NautilusModule NautilusModule; +typedef struct _NautilusModuleClass NautilusModuleClass; + +struct _NautilusModule { + GTypeModule parent; + + GModule *library; + + char *path; + + void (*initialize) (GTypeModule *module); + void (*shutdown) (void); + + void (*list_types) (const GType **types, + int *num_types); + +}; + +struct _NautilusModuleClass { + GTypeModuleClass parent; +}; + +static GType nautilus_module_get_type (void); + +static GList *module_objects = NULL; + +GNOME_CLASS_BOILERPLATE (NautilusModule, + nautilus_module, + GTypeModule, + G_TYPE_TYPE_MODULE); + +static gboolean +nautilus_module_load (GTypeModule *gmodule) +{ + NautilusModule *module; + + module = NAUTILUS_MODULE (gmodule); + + module->library = g_module_open (module->path, 0); + + if (!module->library) { + g_warning (g_module_error ()); + return FALSE; + } + + if (!g_module_symbol (module->library, + "nautilus_module_initialize", + (gpointer *)&module->initialize) || + !g_module_symbol (module->library, + "nautilus_module_shutdown", + (gpointer *)&module->shutdown) || + !g_module_symbol (module->library, + "nautilus_module_list_types", + (gpointer *)&module->list_types)) { + + g_warning (g_module_error ()); + g_module_close (module->library); + + return FALSE; + } + + module->initialize (gmodule); + + return TRUE; +} + +static void +nautilus_module_unload (GTypeModule *gmodule) +{ + NautilusModule *module; + + module = NAUTILUS_MODULE (gmodule); + + module->shutdown (); + + g_module_close (module->library); + + module->initialize = NULL; + module->shutdown = NULL; + module->list_types = NULL; +} + +static void +nautilus_module_finalize (GObject *object) +{ + NautilusModule *module; + + module = NAUTILUS_MODULE (object); + + g_free (module->path); + + EEL_CALL_PARENT (G_OBJECT_CLASS, finalize, (object)); +} + +static void +nautilus_module_instance_init (NautilusModule *module) +{ +} + +static void +nautilus_module_class_init (NautilusModuleClass *class) +{ + G_OBJECT_CLASS (class)->finalize = nautilus_module_finalize; + G_TYPE_MODULE_CLASS (class)->load = nautilus_module_load; + G_TYPE_MODULE_CLASS (class)->unload = nautilus_module_unload; +} + +static void +module_object_weak_notify (gpointer user_data, GObject *object) +{ + module_objects = g_list_remove (module_objects, object); +} + +static void +add_module_objects (NautilusModule *module) +{ + const GType *types; + int num_types; + int i; + + module->list_types (&types, &num_types); + + for (i = 0; i < num_types; i++) { + GObject *object; + + object = g_object_new (types[i], NULL); + g_object_weak_ref (object, + (GWeakNotify)module_object_weak_notify, + NULL); + + module_objects = g_list_prepend (module_objects, object); + } +} + +static NautilusModule * +nautilus_module_load_file (const char *filename) +{ + NautilusModule *module; + + g_print ("loading %s\n", filename); + module = g_object_new (NAUTILUS_TYPE_MODULE, NULL); + module->path = g_strdup (filename); + + if (g_type_module_use (G_TYPE_MODULE (module))) { + add_module_objects (module); + g_type_module_unuse (G_TYPE_MODULE (module)); + return module; + } else { + g_object_unref (module); + return NULL; + } +} + +static void +load_module_dir (const char *dirname) +{ + GDir *dir; + + dir = g_dir_open (dirname, 0, NULL); + + if (dir) { + const char *name; + + while ((name = g_dir_read_name (dir))) { + if (g_str_has_suffix (name, "." G_MODULE_SUFFIX)) { + char *filename; + + filename = g_build_filename (dirname, + name, + NULL); + nautilus_module_load_file (filename); + } + } + + g_dir_close (dir); + } +} + +void +nautilus_module_init (void) +{ + static gboolean initialized = FALSE; + + if (!initialized) { + initialized = TRUE; + + load_module_dir (NAUTILUS_EXTENSIONDIR); + } +} + +GList * +nautilus_module_get_extensions_for_type (GType type) +{ + GList *l; + GList *ret = NULL; + + for (l = module_objects; l != NULL; l = l->next) { + if (G_TYPE_CHECK_INSTANCE_TYPE (G_OBJECT (l->data), + type)) { + g_object_ref (l->data); + ret = g_list_prepend (ret, l->data); + } + } + + return ret; +} diff --git a/libnautilus-private/nautilus-module.h b/libnautilus-private/nautilus-module.h new file mode 100644 index 000000000..ef3f20408 --- /dev/null +++ b/libnautilus-private/nautilus-module.h @@ -0,0 +1,37 @@ +/* + * nautilus-module.h - Interface to nautilus extensions + * + * Copyright (C) 2003 Novell, Inc. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 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 + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the Free + * Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + * + * Author: Dave Camp <dave@ximian.com> + * + */ + +#ifndef NAUTILUS_MODULE_H +#define NAUTILUS_MODULE_H + +#include <glib-object.h> + +G_BEGIN_DECLS + +void nautilus_module_init (void); +GList *nautilus_module_get_extensions_for_type (GType type); + + +G_END_DECLS + +#endif diff --git a/src/file-manager/fm-directory-view.c b/src/file-manager/fm-directory-view.c index 18a124655..717e8e8e8 100644 --- a/src/file-manager/fm-directory-view.c +++ b/src/file-manager/fm-directory-view.c @@ -5908,7 +5908,8 @@ finish_loading (FMDirectoryView *view) attributes |= NAUTILUS_FILE_ATTRIBUTE_DIRECTORY_ITEM_COUNT | NAUTILUS_FILE_ATTRIBUTE_METADATA | NAUTILUS_FILE_ATTRIBUTE_MIME_TYPE | - NAUTILUS_FILE_ATTRIBUTE_DISPLAY_NAME; + NAUTILUS_FILE_ATTRIBUTE_DISPLAY_NAME | + NAUTILUS_FILE_ATTRIBUTE_EXTENSION_INFO; nautilus_directory_file_monitor_add (view->details->model, &view->details->model, diff --git a/src/nautilus-application.c b/src/nautilus-application.c index aab7fe3f6..cb1d7a23a 100644 --- a/src/nautilus-application.c +++ b/src/nautilus-application.c @@ -70,6 +70,7 @@ #include <libnautilus-private/nautilus-global-preferences.h> #include <libnautilus-private/nautilus-icon-factory.h> #include <libnautilus-private/nautilus-metafile-factory.h> +#include <libnautilus-private/nautilus-module.h> #include <libnautilus-private/nautilus-sound.h> #include <libnautilus-private/nautilus-bonobo-extensions.h> #include <libnautilus-private/nautilus-undo-manager.h> @@ -390,6 +391,9 @@ create_starthere_link_callback (gpointer data) static void finish_startup (NautilusApplication *application) { + /* initialize nautilus modules */ + nautilus_module_init (); + /* initialize the sound machinery */ nautilus_sound_init (); |