Add g_file_query_default_handler utility to easily look up the GAppInfo
[platform/upstream/glib.git] / gio / giomodule.c
index b87d319..9ec12ff 100644 (file)
 
 #include <config.h>
 
+#include <string.h>
+
 #include "giomodule.h"
 #include "giomodule-priv.h"
-
+#include "glocalfilemonitor.h"
+#include "glocaldirectorymonitor.h"
+#include "gnativevolumemonitor.h"
+#include "gvfs.h"
+#ifdef G_OS_UNIX
+#include "gdesktopappinfo.h"
+#endif
 #include "gioalias.h"
 
 /**
@@ -109,10 +117,10 @@ g_io_module_load_module (GTypeModule *gmodule)
   /* Make sure that the loaded library contains the required methods */
   if (! g_module_symbol (module->library,
                          "g_io_module_load",
-                         (gpointer *) &module->load) ||
+                         (gpointer) &module->load) ||
       ! g_module_symbol (module->library,
                          "g_io_module_unload",
-                         (gpointer *) &module->unload))
+                         (gpointer) &module->unload))
     {
       g_printerr ("%s\n", g_module_error ());
       g_module_close (module->library);
@@ -179,9 +187,13 @@ is_valid_module_name (const gchar *basename)
  * g_io_modules_load_all_in_directory:
  * @dirname: pathname for a directory containing modules to load.
  * 
- * Loads all the modules in the the specified directory.
+ * Loads all the modules in the the specified directory. 
  * 
- * Returns: a list of #GIOModules loaded from the directory
+ * Returns: a list of #GIOModules loaded from the directory,
+ *      All the modules are loaded into memory, if you want to
+ *      unload them (enabling on-demand loading) you must call
+ *      g_type_module_unuse() on all the modules. Free the list
+ *      with g_list_free().
  **/
 GList *
 g_io_modules_load_all_in_directory (const char *dirname)
@@ -218,8 +230,6 @@ g_io_modules_load_all_in_directory (const char *dirname)
          
           g_free (path);
 
-          g_type_module_unuse (G_TYPE_MODULE (module));
-         
           modules = g_list_prepend (modules, module);
         }
     }
@@ -231,24 +241,252 @@ g_io_modules_load_all_in_directory (const char *dirname)
 
 G_LOCK_DEFINE_STATIC (loaded_dirs);
 
+extern GType _g_inotify_directory_monitor_get_type (void);
+extern GType _g_inotify_file_monitor_get_type (void);
+extern GType _g_unix_volume_monitor_get_type (void);
+extern GType _g_local_vfs_get_type (void);
+
 void
 _g_io_modules_ensure_loaded (void)
 {
-  GList *modules;
-  const char *directory;
+  GList *modules, *l;
   static gboolean loaded_dirs = FALSE;
+  GIOExtensionPoint *ep;
 
-  
   G_LOCK (loaded_dirs);
 
   if (!loaded_dirs)
     {
       loaded_dirs = TRUE;
+
+#ifdef G_OS_UNIX
+      ep = g_io_extension_point_register (G_DESKTOP_APP_INFO_LOOKUP_EXTENSION_POINT_NAME);
+      g_io_extension_point_set_required_type (ep, G_TYPE_DESKTOP_APP_INFO_LOOKUP);
+#endif
+      
+      ep = g_io_extension_point_register (G_LOCAL_DIRECTORY_MONITOR_EXTENSION_POINT_NAME);
+      g_io_extension_point_set_required_type (ep, G_TYPE_LOCAL_DIRECTORY_MONITOR);
+      
+      ep = g_io_extension_point_register (G_LOCAL_FILE_MONITOR_EXTENSION_POINT_NAME);
+      g_io_extension_point_set_required_type (ep, G_TYPE_LOCAL_FILE_MONITOR);
+
+      ep = g_io_extension_point_register (G_VOLUME_MONITOR_EXTENSION_POINT_NAME);
+      g_io_extension_point_set_required_type (ep, G_TYPE_VOLUME_MONITOR);
+      
+      ep = g_io_extension_point_register (G_NATIVE_VOLUME_MONITOR_EXTENSION_POINT_NAME);
+      g_io_extension_point_set_required_type (ep, G_TYPE_NATIVE_VOLUME_MONITOR);
+      
+      ep = g_io_extension_point_register (G_VFS_EXTENSION_POINT_NAME);
+      g_io_extension_point_set_required_type (ep, G_TYPE_VFS);
+      
       modules = g_io_modules_load_all_in_directory (GIO_MODULE_DIR);
+
+      /* Initialize types from built-in "modules" */
+#if defined(HAVE_SYS_INOTIFY_H) || defined(HAVE_LINUX_INOTIFY_H)
+      _g_inotify_directory_monitor_get_type ();
+      _g_inotify_file_monitor_get_type ();
+#endif
+#ifdef G_OS_UNIX
+      _g_unix_volume_monitor_get_type ();
+#endif
+      _g_local_vfs_get_type ();
+    
+      for (l = modules; l != NULL; l = l->next)
+       g_type_module_unuse (G_TYPE_MODULE (l->data));
+      
+      g_list_free (modules);
     }
-  
+
   G_UNLOCK (loaded_dirs);
 }
 
+struct _GIOExtension {
+  char *name;
+  GType type;
+  gint priority;
+};
+
+struct _GIOExtensionPoint {
+  GType required_type;
+  char *name;
+  GList *extensions;
+};
+
+static GHashTable *extension_points = NULL;
+G_LOCK_DEFINE_STATIC(extension_points);
+
+
+static void
+g_io_extension_point_free (GIOExtensionPoint *ep)
+{
+  g_free (ep->name);
+  g_free (ep);
+}
+
+GIOExtensionPoint *
+g_io_extension_point_register (const char *name)
+{
+  GIOExtensionPoint *ep;
+  
+  G_LOCK (extension_points);
+  if (extension_points == NULL)
+    extension_points = g_hash_table_new_full (g_str_hash,
+                                             g_str_equal,
+                                             NULL,
+                                             (GDestroyNotify)g_io_extension_point_free);
+
+  if (g_hash_table_lookup (extension_points, name) != NULL)
+    {
+      g_warning ("Extension point %s registered multiple times", name);
+      G_UNLOCK (extension_points);
+      return NULL;
+    }
+
+  ep = g_new0 (GIOExtensionPoint, 1);
+  ep->name = g_strdup (name);
+  
+  g_hash_table_insert (extension_points, ep->name, ep);
+  
+  G_UNLOCK (extension_points);
+
+  return ep;
+}
+
+GIOExtensionPoint *
+g_io_extension_point_lookup (const char *name)
+{
+  GIOExtensionPoint *ep;
+
+  G_LOCK (extension_points);
+  ep = NULL;
+  if (extension_points != NULL)
+    ep = g_hash_table_lookup (extension_points, name);
+  
+  G_UNLOCK (extension_points);
+
+  return ep;
+  
+}
+
+void
+g_io_extension_point_set_required_type (GIOExtensionPoint *extension_point,
+                                       GType              type)
+{
+  extension_point->required_type = type;
+}
+
+GType
+g_io_extension_point_get_required_type (GIOExtensionPoint *extension_point)
+{
+  return extension_point->required_type;
+}
+
+GList *
+g_io_extension_point_get_extensions (GIOExtensionPoint *extension_point)
+{
+  return extension_point->extensions;
+}
+
+GIOExtension *
+g_io_extension_point_get_extension_by_name (GIOExtensionPoint *extension_point,
+                                           const char        *name)
+{
+  GList *l;
+
+  for (l = extension_point->extensions; l != NULL; l = l->next)
+    {
+      GIOExtension *e = l->data;
+
+      if (e->name != NULL &&
+         strcmp (e->name, name) == 0)
+       return e;
+    }
+  
+  return NULL;
+}
+
+static gint
+extension_prio_compare (gconstpointer  a,
+                       gconstpointer  b)
+{
+  const GIOExtension *extension_a = a, *extension_b = b;
+
+  return extension_b->priority - extension_a->priority;
+}
+
+GIOExtension *
+g_io_extension_point_implement (const char *extension_point_name,
+                               GType type,
+                               const char *extension_name,
+                               gint priority)
+{
+  GIOExtensionPoint *extension_point;
+  GIOExtension *extension;
+  GList *l;
+
+  g_return_val_if_fail (extension_point_name != NULL, NULL);
+
+  extension_point = g_io_extension_point_lookup (extension_point_name);
+  if (extension_point == NULL)
+    {
+      g_warning ("Tried to implement non-registered extension point %s", extension_point_name);
+      return NULL;
+    }
+  
+  if (extension_point->required_type != 0 &&
+      !g_type_is_a (type, extension_point->required_type))
+    {
+      g_warning ("Tried to register an extension of the type %s to extension point %s. "
+                "Expected type is %s.",
+                g_type_name (type),
+                extension_point_name, 
+                g_type_name (extension_point->required_type));
+      return NULL;
+    }      
+
+  /* Its safe to register the same type multiple times */
+  for (l = extension_point->extensions; l != NULL; l = l->next)
+    {
+      extension = l->data;
+      if (extension->type == type)
+       return extension;
+    }
+  
+  extension = g_slice_new0 (GIOExtension);
+  extension->type = type;
+  extension->name = g_strdup (extension_name);
+  extension->priority = priority;
+  
+  extension_point->extensions = g_list_insert_sorted (extension_point->extensions,
+                                                     extension, extension_prio_compare);
+  
+  return extension;
+}
+
+GTypeClass *
+g_io_extension_ref_class (GIOExtension *extension)
+{
+  return g_type_class_ref (extension->type);
+}
+
+
+GType
+g_io_extension_get_type (GIOExtension *extension)
+{
+  return extension->type;
+}
+
+const char *
+g_io_extension_get_name (GIOExtension *extension)
+{
+  return extension->name;
+}
+
+gint
+g_io_extension_get_priority (GIOExtension *extension)
+{
+  return extension->priority;
+}
+
 #define __G_IO_MODULE_C__
 #include "gioaliasdef.c"