Initial checkin of Pika from heckimp
This commit is contained in:
11
libpikamodule/Makefile.gi
Normal file
11
libpikamodule/Makefile.gi
Normal file
@ -0,0 +1,11 @@
|
||||
# Introspectable sources for libpikamodule
|
||||
|
||||
libpikamodule_introspectable_headers = \
|
||||
../libpikamodule/pikamoduletypes.h \
|
||||
../libpikamodule/pikamodule.h \
|
||||
../libpikamodule/pikamoduledb.h
|
||||
|
||||
libpikamodule_introspectable = \
|
||||
../libpikamodule/pikamodule.c \
|
||||
../libpikamodule/pikamoduledb.c \
|
||||
$(libpikamodule_introspectable_headers)
|
37
libpikamodule/meson.build
Normal file
37
libpikamodule/meson.build
Normal file
@ -0,0 +1,37 @@
|
||||
|
||||
libpikamodule_sources = files(
|
||||
'pikamodule.c',
|
||||
'pikamoduledb.c',
|
||||
)
|
||||
|
||||
libpikamodule_headers = files(
|
||||
'pikamodule.h',
|
||||
'pikamoduledb.h',
|
||||
'pikamoduletypes.h',
|
||||
)
|
||||
|
||||
libpikamodule_introspectable = [
|
||||
libpikamodule_sources,
|
||||
libpikamodule_headers,
|
||||
]
|
||||
|
||||
libpikamodule = library('pikamodule-' + pika_api_version,
|
||||
libpikamodule_sources,
|
||||
include_directories: rootInclude,
|
||||
dependencies: [
|
||||
gio, glib, gmodule,
|
||||
],
|
||||
c_args: [ '-DG_LOG_DOMAIN="LibPikaModule"', '-DPIKA_MODULE_COMPILATION', ],
|
||||
link_with: [
|
||||
libpikabase,
|
||||
libpikaconfig,
|
||||
],
|
||||
vs_module_defs: 'pikamodule.def',
|
||||
install: true,
|
||||
version: so_version,
|
||||
)
|
||||
|
||||
install_headers(
|
||||
libpikamodule_headers,
|
||||
subdir: pika_api_name / 'libpikamodule',
|
||||
)
|
681
libpikamodule/pikamodule.c
Normal file
681
libpikamodule/pikamodule.c
Normal file
@ -0,0 +1,681 @@
|
||||
/* LIBPIKA - The PIKA Library
|
||||
* Copyright (C) 1995-1997 Peter Mattis and Spencer Kimball
|
||||
*
|
||||
* pikamodule.c
|
||||
* (C) 1999 Austin Donnelly <austin@gimp.org>
|
||||
*
|
||||
* This library is free software: you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 3 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
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library. If not, see
|
||||
* <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include "config.h"
|
||||
|
||||
#include <string.h>
|
||||
|
||||
#include <gio/gio.h>
|
||||
|
||||
#include "libpikabase/pikabase.h"
|
||||
|
||||
#include "pikamodule.h"
|
||||
|
||||
#include "libpika/libpika-intl.h"
|
||||
|
||||
|
||||
/**
|
||||
* SECTION: pikamodule
|
||||
* @title: PikaModule
|
||||
* @short_description: A #GTypeModule subclass which implements module
|
||||
* loading using #GModule.
|
||||
* @see_also: #GModule, #GTypeModule
|
||||
*
|
||||
* #PikaModule is a generic mechanism to dynamically load modules into
|
||||
* PIKA. It is a #GTypeModule subclass, implementing module loading
|
||||
* using #GModule. #PikaModule does not know which functionality is
|
||||
* implemented by the modules, it just provides a framework to get
|
||||
* arbitrary #GType implementations loaded from disk.
|
||||
**/
|
||||
|
||||
|
||||
enum
|
||||
{
|
||||
PROP_0,
|
||||
PROP_AUTO_LOAD,
|
||||
PROP_ON_DISK,
|
||||
N_PROPS
|
||||
};
|
||||
static GParamSpec *obj_props[N_PROPS] = { NULL, };
|
||||
|
||||
struct _PikaModulePrivate
|
||||
{
|
||||
GFile *file; /* path to the module */
|
||||
gboolean auto_load; /* auto-load the module on creation */
|
||||
gboolean verbose; /* verbose error reporting */
|
||||
|
||||
PikaModuleInfo *info; /* returned values from module_query */
|
||||
PikaModuleState state; /* what's happened to the module */
|
||||
gchar *last_error;
|
||||
|
||||
gboolean on_disk; /* TRUE if file still exists */
|
||||
|
||||
GModule *module; /* handle on the module */
|
||||
|
||||
PikaModuleQueryFunc query_module;
|
||||
PikaModuleRegisterFunc register_module;
|
||||
};
|
||||
|
||||
|
||||
static void pika_module_get_property (GObject *object,
|
||||
guint property_id,
|
||||
GValue *value,
|
||||
GParamSpec *pspec);
|
||||
static void pika_module_set_property (GObject *object,
|
||||
guint property_id,
|
||||
const GValue *value,
|
||||
GParamSpec *pspec);
|
||||
static void pika_module_finalize (GObject *object);
|
||||
|
||||
static gboolean pika_module_load (GTypeModule *module);
|
||||
static void pika_module_unload (GTypeModule *module);
|
||||
|
||||
static gboolean pika_module_open (PikaModule *module);
|
||||
static gboolean pika_module_close (PikaModule *module);
|
||||
static void pika_module_set_last_error (PikaModule *module,
|
||||
const gchar *error_str);
|
||||
|
||||
static PikaModuleInfo * pika_module_info_new (guint32 abi_version,
|
||||
const gchar *purpose,
|
||||
const gchar *author,
|
||||
const gchar *version,
|
||||
const gchar *copyright,
|
||||
const gchar *date);
|
||||
static PikaModuleInfo * pika_module_info_copy (const PikaModuleInfo *info);
|
||||
static void pika_module_info_free (PikaModuleInfo *info);
|
||||
|
||||
|
||||
G_DEFINE_TYPE_WITH_PRIVATE (PikaModule, pika_module, G_TYPE_TYPE_MODULE)
|
||||
|
||||
#define parent_class pika_module_parent_class
|
||||
|
||||
|
||||
static void
|
||||
pika_module_class_init (PikaModuleClass *klass)
|
||||
{
|
||||
GObjectClass *object_class = G_OBJECT_CLASS (klass);
|
||||
GTypeModuleClass *module_class = G_TYPE_MODULE_CLASS (klass);
|
||||
|
||||
object_class->set_property = pika_module_set_property;
|
||||
object_class->get_property = pika_module_get_property;
|
||||
object_class->finalize = pika_module_finalize;
|
||||
|
||||
obj_props[PROP_AUTO_LOAD] = g_param_spec_boolean ("auto-load", "auto-load", "auto-load",
|
||||
FALSE, PIKA_PARAM_READWRITE);
|
||||
obj_props[PROP_ON_DISK] = g_param_spec_boolean ("on-disk", "on-disk", "on-disk",
|
||||
FALSE, PIKA_PARAM_READABLE);
|
||||
g_object_class_install_properties (object_class, N_PROPS, obj_props);
|
||||
|
||||
module_class->load = pika_module_load;
|
||||
module_class->unload = pika_module_unload;
|
||||
}
|
||||
|
||||
static void
|
||||
pika_module_init (PikaModule *module)
|
||||
{
|
||||
module->priv = pika_module_get_instance_private (module);
|
||||
|
||||
module->priv->state = PIKA_MODULE_STATE_ERROR;
|
||||
}
|
||||
|
||||
static void
|
||||
pika_module_set_property (GObject *object,
|
||||
guint property_id,
|
||||
const GValue *value,
|
||||
GParamSpec *pspec)
|
||||
{
|
||||
PikaModule *module = PIKA_MODULE (object);
|
||||
|
||||
switch (property_id)
|
||||
{
|
||||
case PROP_AUTO_LOAD:
|
||||
pika_module_set_auto_load (module, g_value_get_boolean (value));
|
||||
break;
|
||||
|
||||
default:
|
||||
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
pika_module_get_property (GObject *object,
|
||||
guint property_id,
|
||||
GValue *value,
|
||||
GParamSpec *pspec)
|
||||
{
|
||||
PikaModule *module = PIKA_MODULE (object);
|
||||
|
||||
switch (property_id)
|
||||
{
|
||||
case PROP_AUTO_LOAD:
|
||||
g_value_set_boolean (value, pika_module_get_auto_load (module));
|
||||
break;
|
||||
|
||||
case PROP_ON_DISK:
|
||||
g_value_set_boolean (value, pika_module_is_on_disk (module));
|
||||
break;
|
||||
|
||||
default:
|
||||
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
pika_module_finalize (GObject *object)
|
||||
{
|
||||
PikaModule *module = PIKA_MODULE (object);
|
||||
|
||||
g_clear_object (&module->priv->file);
|
||||
g_clear_pointer (&module->priv->info, pika_module_info_free);
|
||||
g_clear_pointer (&module->priv->last_error, g_free);
|
||||
|
||||
G_OBJECT_CLASS (parent_class)->finalize (object);
|
||||
}
|
||||
|
||||
static gboolean
|
||||
pika_module_load (GTypeModule *module)
|
||||
{
|
||||
PikaModule *pika_module = PIKA_MODULE (module);
|
||||
gpointer func;
|
||||
|
||||
g_return_val_if_fail (pika_module->priv->file != NULL, FALSE);
|
||||
g_return_val_if_fail (pika_module->priv->module == NULL, FALSE);
|
||||
|
||||
if (pika_module->priv->verbose)
|
||||
g_print ("Loading module '%s'\n",
|
||||
pika_file_get_utf8_name (pika_module->priv->file));
|
||||
|
||||
if (! pika_module_open (pika_module))
|
||||
return FALSE;
|
||||
|
||||
if (! pika_module_query_module (pika_module))
|
||||
return FALSE;
|
||||
|
||||
/* find the pika_module_register symbol */
|
||||
if (! g_module_symbol (pika_module->priv->module, "pika_module_register",
|
||||
&func))
|
||||
{
|
||||
pika_module_set_last_error (pika_module,
|
||||
"Missing pika_module_register() symbol");
|
||||
|
||||
g_message (_("Module '%s' load error: %s"),
|
||||
pika_file_get_utf8_name (pika_module->priv->file),
|
||||
pika_module->priv->last_error);
|
||||
|
||||
pika_module_close (pika_module);
|
||||
|
||||
pika_module->priv->state = PIKA_MODULE_STATE_ERROR;
|
||||
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
pika_module->priv->register_module = func;
|
||||
|
||||
if (! pika_module->priv->register_module (module))
|
||||
{
|
||||
pika_module_set_last_error (pika_module,
|
||||
"pika_module_register() returned FALSE");
|
||||
|
||||
g_message (_("Module '%s' load error: %s"),
|
||||
pika_file_get_utf8_name (pika_module->priv->file),
|
||||
pika_module->priv->last_error);
|
||||
|
||||
pika_module_close (pika_module);
|
||||
|
||||
pika_module->priv->state = PIKA_MODULE_STATE_LOAD_FAILED;
|
||||
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
pika_module->priv->state = PIKA_MODULE_STATE_LOADED;
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static void
|
||||
pika_module_unload (GTypeModule *module)
|
||||
{
|
||||
PikaModule *pika_module = PIKA_MODULE (module);
|
||||
|
||||
g_return_if_fail (pika_module->priv->module != NULL);
|
||||
|
||||
if (pika_module->priv->verbose)
|
||||
g_print ("Unloading module '%s'\n",
|
||||
pika_file_get_utf8_name (pika_module->priv->file));
|
||||
|
||||
pika_module_close (pika_module);
|
||||
}
|
||||
|
||||
|
||||
/* public functions */
|
||||
|
||||
/**
|
||||
* pika_module_new:
|
||||
* @file: A #GFile pointing to a loadable module.
|
||||
* @auto_load: Pass %TRUE to exclude this module from auto-loading.
|
||||
* @verbose: Pass %TRUE to enable debugging output.
|
||||
*
|
||||
* Creates a new #PikaModule instance.
|
||||
*
|
||||
* Returns: The new #PikaModule object.
|
||||
**/
|
||||
PikaModule *
|
||||
pika_module_new (GFile *file,
|
||||
gboolean auto_load,
|
||||
gboolean verbose)
|
||||
{
|
||||
PikaModule *module;
|
||||
|
||||
g_return_val_if_fail (G_IS_FILE (file), NULL);
|
||||
g_return_val_if_fail (g_file_is_native (file), NULL);
|
||||
|
||||
module = g_object_new (PIKA_TYPE_MODULE, NULL);
|
||||
|
||||
module->priv->file = g_object_ref (file);
|
||||
module->priv->auto_load = auto_load ? TRUE : FALSE;
|
||||
module->priv->verbose = verbose ? TRUE : FALSE;
|
||||
|
||||
if (module->priv->auto_load)
|
||||
{
|
||||
if (pika_module_load (G_TYPE_MODULE (module)))
|
||||
pika_module_unload (G_TYPE_MODULE (module));
|
||||
}
|
||||
else
|
||||
{
|
||||
if (verbose)
|
||||
g_print ("Skipping module '%s'\n",
|
||||
pika_file_get_utf8_name (file));
|
||||
|
||||
module->priv->state = PIKA_MODULE_STATE_NOT_LOADED;
|
||||
}
|
||||
|
||||
return module;
|
||||
}
|
||||
|
||||
/**
|
||||
* pika_module_get_file:
|
||||
* @module: A #PikaModule
|
||||
*
|
||||
* Returns #GFile of the @module,
|
||||
*
|
||||
* Returns: (transfer none): The @module's #GFile.
|
||||
*
|
||||
* Since: 3.0
|
||||
**/
|
||||
GFile *
|
||||
pika_module_get_file (PikaModule *module)
|
||||
{
|
||||
g_return_val_if_fail (PIKA_IS_MODULE (module), NULL);
|
||||
|
||||
return module->priv->file;
|
||||
}
|
||||
|
||||
/**
|
||||
* pika_module_set_auto_load:
|
||||
* @module: A #PikaModule
|
||||
* @auto_load: Pass %FALSE to exclude this module from auto-loading
|
||||
*
|
||||
* Sets the @auto_load property of the module
|
||||
*
|
||||
* Since: 3.0
|
||||
**/
|
||||
void
|
||||
pika_module_set_auto_load (PikaModule *module,
|
||||
gboolean auto_load)
|
||||
{
|
||||
g_return_if_fail (PIKA_IS_MODULE (module));
|
||||
|
||||
if (auto_load != module->priv->auto_load)
|
||||
{
|
||||
module->priv->auto_load = auto_load;
|
||||
|
||||
g_object_notify_by_pspec (G_OBJECT (module), obj_props[PROP_AUTO_LOAD]);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* pika_module_get_auto_load:
|
||||
* @module: A #PikaModule
|
||||
*
|
||||
* Returns whether this @module in automatically loaded at startup.
|
||||
*
|
||||
* Returns: The @module's 'auto_load' property.
|
||||
*
|
||||
* Since: 3.0
|
||||
**/
|
||||
gboolean
|
||||
pika_module_get_auto_load (PikaModule *module)
|
||||
{
|
||||
g_return_val_if_fail (PIKA_IS_MODULE (module), FALSE);
|
||||
|
||||
return module->priv->auto_load;
|
||||
}
|
||||
|
||||
/**
|
||||
* pika_module_is_on_disk:
|
||||
* @module: A #PikaModule
|
||||
*
|
||||
* Returns: Whether the @module is present on diak.
|
||||
*
|
||||
* Since: 3.0
|
||||
**/
|
||||
gboolean
|
||||
pika_module_is_on_disk (PikaModule *module)
|
||||
{
|
||||
gboolean old_on_disk;
|
||||
|
||||
g_return_val_if_fail (PIKA_IS_MODULE (module), FALSE);
|
||||
|
||||
old_on_disk = module->priv->on_disk;
|
||||
|
||||
module->priv->on_disk =
|
||||
(g_file_query_file_type (module->priv->file,
|
||||
G_FILE_QUERY_INFO_NONE, NULL) ==
|
||||
G_FILE_TYPE_REGULAR);
|
||||
|
||||
if (module->priv->on_disk != old_on_disk)
|
||||
g_object_notify_by_pspec (G_OBJECT (module), obj_props[PROP_ON_DISK]);
|
||||
|
||||
return module->priv->on_disk;
|
||||
}
|
||||
|
||||
/**
|
||||
* pika_module_is_loaded:
|
||||
* @module: A #PikaModule
|
||||
*
|
||||
* Returns: Whether the @module is currently loaded.
|
||||
*
|
||||
* Since: 3.0
|
||||
**/
|
||||
gboolean
|
||||
pika_module_is_loaded (PikaModule *module)
|
||||
{
|
||||
g_return_val_if_fail (PIKA_IS_MODULE (module), FALSE);
|
||||
|
||||
return module->priv->module != NULL;
|
||||
}
|
||||
|
||||
/**
|
||||
* pika_module_get_info:
|
||||
* @module: A #PikaModule
|
||||
*
|
||||
* Returns: (transfer none): The @module's #PikaModuleInfo as provided
|
||||
* by the actual module, or %NULL.
|
||||
*
|
||||
* Since: 3.0
|
||||
**/
|
||||
const PikaModuleInfo *
|
||||
pika_module_get_info (PikaModule *module)
|
||||
{
|
||||
g_return_val_if_fail (PIKA_IS_MODULE (module), NULL);
|
||||
|
||||
return module->priv->info;
|
||||
}
|
||||
|
||||
/**
|
||||
* pika_module_get_state:
|
||||
* @module: A #PikaModule
|
||||
*
|
||||
* Returns: The @module's state.
|
||||
*
|
||||
* Since: 3.0
|
||||
**/
|
||||
PikaModuleState
|
||||
pika_module_get_state (PikaModule *module)
|
||||
{
|
||||
g_return_val_if_fail (PIKA_IS_MODULE (module), PIKA_MODULE_STATE_ERROR);
|
||||
|
||||
return module->priv->state;
|
||||
}
|
||||
|
||||
/**
|
||||
* pika_module_get_last_error:
|
||||
* @module: A #PikaModule
|
||||
*
|
||||
* Returns: The @module's last error message.
|
||||
*
|
||||
* Since: 3.0
|
||||
**/
|
||||
const gchar *
|
||||
pika_module_get_last_error (PikaModule *module)
|
||||
{
|
||||
g_return_val_if_fail (PIKA_IS_MODULE (module), NULL);
|
||||
|
||||
return module->priv->last_error;
|
||||
}
|
||||
|
||||
/**
|
||||
* pika_module_query_module:
|
||||
* @module: A #PikaModule.
|
||||
*
|
||||
* Queries the module without actually registering any of the types it
|
||||
* may implement. After successful query, pika_module_get_info() can be
|
||||
* used to get further about the module.
|
||||
*
|
||||
* Returns: %TRUE on success.
|
||||
**/
|
||||
gboolean
|
||||
pika_module_query_module (PikaModule *module)
|
||||
{
|
||||
const PikaModuleInfo *info;
|
||||
gboolean close_module = FALSE;
|
||||
gpointer func;
|
||||
|
||||
g_return_val_if_fail (PIKA_IS_MODULE (module), FALSE);
|
||||
|
||||
if (! module->priv->module)
|
||||
{
|
||||
if (! pika_module_open (module))
|
||||
return FALSE;
|
||||
|
||||
close_module = TRUE;
|
||||
}
|
||||
|
||||
/* find the pika_module_query symbol */
|
||||
if (! g_module_symbol (module->priv->module, "pika_module_query", &func))
|
||||
{
|
||||
pika_module_set_last_error (module,
|
||||
"Missing pika_module_query() symbol");
|
||||
|
||||
g_message (_("Module '%s' load error: %s"),
|
||||
pika_file_get_utf8_name (module->priv->file),
|
||||
module->priv->last_error);
|
||||
|
||||
pika_module_close (module);
|
||||
|
||||
module->priv->state = PIKA_MODULE_STATE_ERROR;
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
module->priv->query_module = func;
|
||||
|
||||
g_clear_pointer (&module->priv->info, pika_module_info_free);
|
||||
|
||||
info = module->priv->query_module (G_TYPE_MODULE (module));
|
||||
|
||||
if (! info || info->abi_version != PIKA_MODULE_ABI_VERSION)
|
||||
{
|
||||
pika_module_set_last_error (module,
|
||||
info ?
|
||||
"module ABI version does not match" :
|
||||
"pika_module_query() returned NULL");
|
||||
|
||||
g_message (_("Module '%s' load error: %s"),
|
||||
pika_file_get_utf8_name (module->priv->file),
|
||||
module->priv->last_error);
|
||||
|
||||
pika_module_close (module);
|
||||
|
||||
module->priv->state = PIKA_MODULE_STATE_ERROR;
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
module->priv->info = pika_module_info_copy (info);
|
||||
|
||||
if (close_module)
|
||||
return pika_module_close (module);
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
/**
|
||||
* pika_module_error_quark:
|
||||
*
|
||||
* This function is never called directly. Use PIKA_MODULE_ERROR() instead.
|
||||
*
|
||||
* Returns: the #GQuark that defines the PIKA module error domain.
|
||||
*
|
||||
* Since: 2.8
|
||||
**/
|
||||
GQuark
|
||||
pika_module_error_quark (void)
|
||||
{
|
||||
return g_quark_from_static_string ("pika-module-error-quark");
|
||||
}
|
||||
|
||||
|
||||
/* private functions */
|
||||
|
||||
static gboolean
|
||||
pika_module_open (PikaModule *module)
|
||||
{
|
||||
gchar *path = g_file_get_path (module->priv->file);
|
||||
|
||||
module->priv->module = g_module_open (path, 0);
|
||||
|
||||
g_free (path);
|
||||
|
||||
if (! module->priv->module)
|
||||
{
|
||||
module->priv->state = PIKA_MODULE_STATE_ERROR;
|
||||
pika_module_set_last_error (module, g_module_error ());
|
||||
|
||||
g_message (_("Module '%s' load error: %s"),
|
||||
pika_file_get_utf8_name (module->priv->file),
|
||||
module->priv->last_error);
|
||||
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static gboolean
|
||||
pika_module_close (PikaModule *module)
|
||||
{
|
||||
g_module_close (module->priv->module); /* FIXME: error handling */
|
||||
module->priv->module = NULL;
|
||||
module->priv->query_module = NULL;
|
||||
module->priv->register_module = NULL;
|
||||
|
||||
module->priv->state = PIKA_MODULE_STATE_NOT_LOADED;
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static void
|
||||
pika_module_set_last_error (PikaModule *module,
|
||||
const gchar *error_str)
|
||||
{
|
||||
if (module->priv->last_error)
|
||||
g_free (module->priv->last_error);
|
||||
|
||||
module->priv->last_error = g_strdup (error_str);
|
||||
}
|
||||
|
||||
|
||||
/* PikaModuleInfo functions */
|
||||
|
||||
/**
|
||||
* pika_module_info_new:
|
||||
* @abi_version: The #PIKA_MODULE_ABI_VERSION the module was compiled against.
|
||||
* @purpose: The module's general purpose.
|
||||
* @author: The module's author.
|
||||
* @version: The module's version.
|
||||
* @copyright: The module's copyright.
|
||||
* @date: The module's release date.
|
||||
*
|
||||
* Creates a newly allocated #PikaModuleInfo struct.
|
||||
*
|
||||
* Returns: The new #PikaModuleInfo struct.
|
||||
**/
|
||||
static PikaModuleInfo *
|
||||
pika_module_info_new (guint32 abi_version,
|
||||
const gchar *purpose,
|
||||
const gchar *author,
|
||||
const gchar *version,
|
||||
const gchar *copyright,
|
||||
const gchar *date)
|
||||
{
|
||||
PikaModuleInfo *info = g_slice_new0 (PikaModuleInfo);
|
||||
|
||||
info->abi_version = abi_version;
|
||||
info->purpose = g_strdup (purpose);
|
||||
info->author = g_strdup (author);
|
||||
info->version = g_strdup (version);
|
||||
info->copyright = g_strdup (copyright);
|
||||
info->date = g_strdup (date);
|
||||
|
||||
return info;
|
||||
}
|
||||
|
||||
/**
|
||||
* pika_module_info_copy:
|
||||
* @info: The #PikaModuleInfo struct to copy.
|
||||
*
|
||||
* Copies a #PikaModuleInfo struct.
|
||||
*
|
||||
* Returns: The new copy.
|
||||
**/
|
||||
static PikaModuleInfo *
|
||||
pika_module_info_copy (const PikaModuleInfo *info)
|
||||
{
|
||||
g_return_val_if_fail (info != NULL, NULL);
|
||||
|
||||
return pika_module_info_new (info->abi_version,
|
||||
info->purpose,
|
||||
info->author,
|
||||
info->version,
|
||||
info->copyright,
|
||||
info->date);
|
||||
}
|
||||
|
||||
/**
|
||||
* pika_module_info_free:
|
||||
* @info: The #PikaModuleInfo struct to free
|
||||
*
|
||||
* Frees the passed #PikaModuleInfo.
|
||||
**/
|
||||
static void
|
||||
pika_module_info_free (PikaModuleInfo *info)
|
||||
{
|
||||
g_return_if_fail (info != NULL);
|
||||
|
||||
g_free (info->purpose);
|
||||
g_free (info->author);
|
||||
g_free (info->version);
|
||||
g_free (info->copyright);
|
||||
g_free (info->date);
|
||||
|
||||
g_slice_free (PikaModuleInfo, info);
|
||||
}
|
21
libpikamodule/pikamodule.def
Normal file
21
libpikamodule/pikamodule.def
Normal file
@ -0,0 +1,21 @@
|
||||
EXPORTS
|
||||
pika_module_db_get_load_inhibit
|
||||
pika_module_db_get_type
|
||||
pika_module_db_get_verbose
|
||||
pika_module_db_load
|
||||
pika_module_db_new
|
||||
pika_module_db_refresh
|
||||
pika_module_db_set_load_inhibit
|
||||
pika_module_db_set_verbose
|
||||
pika_module_error_quark
|
||||
pika_module_get_auto_load
|
||||
pika_module_get_file
|
||||
pika_module_get_info
|
||||
pika_module_get_last_error
|
||||
pika_module_get_state
|
||||
pika_module_get_type
|
||||
pika_module_is_loaded
|
||||
pika_module_is_on_disk
|
||||
pika_module_new
|
||||
pika_module_query_module
|
||||
pika_module_set_auto_load
|
214
libpikamodule/pikamodule.h
Normal file
214
libpikamodule/pikamodule.h
Normal file
@ -0,0 +1,214 @@
|
||||
/* LIBPIKA - The PIKA Library
|
||||
* Copyright (C) 1995-1997 Peter Mattis and Spencer Kimball
|
||||
*
|
||||
* pikamodule.h
|
||||
* (C) 1999 Austin Donnelly <austin@gimp.org>
|
||||
*
|
||||
* This library is free software: you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 3 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
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library. If not, see
|
||||
* <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#ifndef __PIKA_MODULE_H__
|
||||
#define __PIKA_MODULE_H__
|
||||
|
||||
#include <gio/gio.h>
|
||||
#include <gmodule.h>
|
||||
|
||||
#define __PIKA_MODULE_H_INSIDE__
|
||||
|
||||
#include <libpikamodule/pikamoduletypes.h>
|
||||
|
||||
#include <libpikamodule/pikamoduledb.h>
|
||||
|
||||
#undef __PIKA_MODULE_H_INSIDE__
|
||||
|
||||
G_BEGIN_DECLS
|
||||
|
||||
|
||||
/**
|
||||
* PIKA_MODULE_ABI_VERSION:
|
||||
*
|
||||
* The version of the module system's ABI. Modules put this value into
|
||||
* #PikaModuleInfo's @abi_version field so the code loading the modules
|
||||
* can check if it was compiled against the same module ABI the modules
|
||||
* are compiled against.
|
||||
*
|
||||
* PIKA_MODULE_ABI_VERSION is incremented each time one of the
|
||||
* following changes:
|
||||
*
|
||||
* - the libpikamodule implementation (if the change affects modules).
|
||||
*
|
||||
* - one of the classes implemented by modules (currently #PikaColorDisplay,
|
||||
* #PikaColorSelector and #PikaController).
|
||||
**/
|
||||
#define PIKA_MODULE_ABI_VERSION 0x0005
|
||||
|
||||
|
||||
/**
|
||||
* PikaModuleState:
|
||||
* @PIKA_MODULE_STATE_ERROR: Missing pika_module_register() function
|
||||
* or other error.
|
||||
* @PIKA_MODULE_STATE_LOADED: An instance of a type implemented by
|
||||
* this module is allocated.
|
||||
* @PIKA_MODULE_STATE_LOAD_FAILED: pika_module_register() returned %FALSE.
|
||||
* @PIKA_MODULE_STATE_NOT_LOADED: There are no instances allocated of
|
||||
* types implemented by this module.
|
||||
*
|
||||
* The possible states a #PikaModule can be in.
|
||||
**/
|
||||
typedef enum
|
||||
{
|
||||
PIKA_MODULE_STATE_ERROR,
|
||||
PIKA_MODULE_STATE_LOADED,
|
||||
PIKA_MODULE_STATE_LOAD_FAILED,
|
||||
PIKA_MODULE_STATE_NOT_LOADED
|
||||
} PikaModuleState;
|
||||
|
||||
|
||||
#define PIKA_MODULE_ERROR (pika_module_error_quark ())
|
||||
|
||||
GQuark pika_module_error_quark (void) G_GNUC_CONST;
|
||||
|
||||
/**
|
||||
* PikaModuleError:
|
||||
* @PIKA_MODULE_FAILED: Generic error condition
|
||||
*
|
||||
* Types of errors returned by modules
|
||||
**/
|
||||
typedef enum
|
||||
{
|
||||
PIKA_MODULE_FAILED
|
||||
} PikaModuleError;
|
||||
|
||||
|
||||
/**
|
||||
* PikaModuleInfo:
|
||||
* @abi_version: The #PIKA_MODULE_ABI_VERSION the module was compiled against.
|
||||
* @purpose: The module's general purpose.
|
||||
* @author: The module's author.
|
||||
* @version: The module's version.
|
||||
* @copyright: The module's copyright.
|
||||
* @date: The module's release date.
|
||||
*
|
||||
* This structure contains information about a loadable module.
|
||||
**/
|
||||
struct _PikaModuleInfo
|
||||
{
|
||||
guint32 abi_version;
|
||||
gchar *purpose;
|
||||
gchar *author;
|
||||
gchar *version;
|
||||
gchar *copyright;
|
||||
gchar *date;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* PikaModuleQueryFunc:
|
||||
* @module: The module responsible for this loadable module.
|
||||
*
|
||||
* The signature of the query function a loadable PIKA module must
|
||||
* implement. In the module, the function must be called [func@Module.query].
|
||||
*
|
||||
* [class@Module] will copy the returned [struct@ModuleInfo], so the
|
||||
* module doesn't need to keep these values around (however in most
|
||||
* cases the module will just return a pointer to a constant
|
||||
* structure).
|
||||
*
|
||||
* Returns: The info struct describing the module.
|
||||
**/
|
||||
typedef const PikaModuleInfo * (* PikaModuleQueryFunc) (GTypeModule *module);
|
||||
|
||||
/**
|
||||
* PikaModuleRegisterFunc:
|
||||
* @module: The module responsible for this loadable module.
|
||||
*
|
||||
* The signature of the register function a loadable PIKA module must
|
||||
* implement. In the module, the function must be called
|
||||
* [func@Module.register].
|
||||
*
|
||||
* When this function is called, the module should register all the types
|
||||
* it implements with the passed @module.
|
||||
*
|
||||
* Returns: Whether the registration was succesfull
|
||||
**/
|
||||
typedef gboolean (* PikaModuleRegisterFunc) (GTypeModule *module);
|
||||
|
||||
|
||||
/* PikaModules have to implement these */
|
||||
G_MODULE_EXPORT const PikaModuleInfo * pika_module_query (GTypeModule *module);
|
||||
G_MODULE_EXPORT gboolean pika_module_register (GTypeModule *module);
|
||||
|
||||
|
||||
#define PIKA_TYPE_MODULE (pika_module_get_type ())
|
||||
#define PIKA_MODULE(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), PIKA_TYPE_MODULE, PikaModule))
|
||||
#define PIKA_MODULE_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), PIKA_TYPE_MODULE, PikaModuleClass))
|
||||
#define PIKA_IS_MODULE(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), PIKA_TYPE_MODULE))
|
||||
#define PIKA_IS_MODULE_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), PIKA_TYPE_MODULE))
|
||||
#define PIKA_MODULE_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), PIKA_TYPE_MODULE, PikaModuleClass))
|
||||
|
||||
|
||||
typedef struct _PikaModulePrivate PikaModulePrivate;
|
||||
typedef struct _PikaModuleClass PikaModuleClass;
|
||||
|
||||
struct _PikaModule
|
||||
{
|
||||
GTypeModule parent_instance;
|
||||
|
||||
PikaModulePrivate *priv;
|
||||
};
|
||||
|
||||
struct _PikaModuleClass
|
||||
{
|
||||
GTypeModuleClass parent_class;
|
||||
|
||||
void (* modified) (PikaModule *module);
|
||||
|
||||
/* Padding for future expansion */
|
||||
void (* _pika_reserved1) (void);
|
||||
void (* _pika_reserved2) (void);
|
||||
void (* _pika_reserved3) (void);
|
||||
void (* _pika_reserved4) (void);
|
||||
void (* _pika_reserved5) (void);
|
||||
void (* _pika_reserved6) (void);
|
||||
void (* _pika_reserved7) (void);
|
||||
void (* _pika_reserved8) (void);
|
||||
};
|
||||
|
||||
|
||||
GType pika_module_get_type (void) G_GNUC_CONST;
|
||||
|
||||
PikaModule * pika_module_new (GFile *file,
|
||||
gboolean auto_load,
|
||||
gboolean verbose);
|
||||
|
||||
GFile * pika_module_get_file (PikaModule *module);
|
||||
|
||||
void pika_module_set_auto_load (PikaModule *module,
|
||||
gboolean auto_load);
|
||||
gboolean pika_module_get_auto_load (PikaModule *module);
|
||||
|
||||
gboolean pika_module_is_on_disk (PikaModule *module);
|
||||
gboolean pika_module_is_loaded (PikaModule *module);
|
||||
|
||||
const PikaModuleInfo * pika_module_get_info (PikaModule *module);
|
||||
PikaModuleState pika_module_get_state (PikaModule *module);
|
||||
const gchar * pika_module_get_last_error (PikaModule *module);
|
||||
|
||||
gboolean pika_module_query_module (PikaModule *module);
|
||||
|
||||
|
||||
G_END_DECLS
|
||||
|
||||
#endif /* __PIKA_MODULE_H__ */
|
484
libpikamodule/pikamoduledb.c
Normal file
484
libpikamodule/pikamoduledb.c
Normal file
@ -0,0 +1,484 @@
|
||||
/* LIBPIKA - The PIKA Library
|
||||
* Copyright (C) 1995-1997 Peter Mattis and Spencer Kimball
|
||||
*
|
||||
* This library is free software: you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 3 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
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library. If not, see
|
||||
* <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include "config.h"
|
||||
|
||||
#include <string.h>
|
||||
|
||||
#include <gio/gio.h>
|
||||
|
||||
#include "libpikabase/pikabase.h"
|
||||
#include "libpikaconfig/pikaconfig.h"
|
||||
|
||||
#include "pikamoduletypes.h"
|
||||
|
||||
#include "pikamodule.h"
|
||||
#include "pikamoduledb.h"
|
||||
|
||||
#include "libpika/libpika-intl.h"
|
||||
|
||||
|
||||
/**
|
||||
* SECTION: pikamoduledb
|
||||
* @title: PikaModuleDB
|
||||
* @short_description: Keeps a list of #PikaModule's found in a given
|
||||
* searchpath.
|
||||
*
|
||||
* Keeps a list of #PikaModule's found in a given searchpath.
|
||||
**/
|
||||
|
||||
|
||||
struct _PikaModuleDB
|
||||
{
|
||||
GObject parent_instance;
|
||||
|
||||
GPtrArray *modules;
|
||||
|
||||
gchar *load_inhibit;
|
||||
gboolean verbose;
|
||||
};
|
||||
|
||||
|
||||
static void pika_module_db_finalize (GObject *object);
|
||||
|
||||
static void pika_module_db_load_directory (PikaModuleDB *db,
|
||||
GFile *directory);
|
||||
static void pika_module_db_load_module (PikaModuleDB *db,
|
||||
GFile *file);
|
||||
|
||||
static PikaModule * pika_module_db_module_find_by_file (PikaModuleDB *db,
|
||||
GFile *file);
|
||||
|
||||
static void pika_module_db_module_dump_func (gpointer data,
|
||||
gpointer user_data);
|
||||
|
||||
static void pika_module_db_list_model_iface_init (GListModelInterface *iface);
|
||||
|
||||
|
||||
G_DEFINE_TYPE_WITH_CODE (PikaModuleDB, pika_module_db, G_TYPE_OBJECT,
|
||||
G_IMPLEMENT_INTERFACE (G_TYPE_LIST_MODEL,
|
||||
pika_module_db_list_model_iface_init))
|
||||
|
||||
#define parent_class pika_module_db_parent_class
|
||||
|
||||
|
||||
static void
|
||||
pika_module_db_class_init (PikaModuleDBClass *klass)
|
||||
{
|
||||
GObjectClass *object_class = G_OBJECT_CLASS (klass);
|
||||
|
||||
object_class->finalize = pika_module_db_finalize;
|
||||
}
|
||||
|
||||
static void
|
||||
pika_module_db_init (PikaModuleDB *db)
|
||||
{
|
||||
db->modules = g_ptr_array_new ();
|
||||
db->load_inhibit = NULL;
|
||||
db->verbose = FALSE;
|
||||
}
|
||||
|
||||
static void
|
||||
pika_module_db_finalize (GObject *object)
|
||||
{
|
||||
PikaModuleDB *db = PIKA_MODULE_DB (object);
|
||||
|
||||
g_clear_pointer (&db->modules, g_ptr_array_unref);
|
||||
g_clear_pointer (&db->load_inhibit, g_free);
|
||||
|
||||
G_OBJECT_CLASS (parent_class)->finalize (object);
|
||||
}
|
||||
|
||||
static GType
|
||||
pika_module_db_get_item_type (GListModel *list)
|
||||
{
|
||||
return PIKA_TYPE_MODULE;
|
||||
}
|
||||
|
||||
static guint
|
||||
pika_module_db_get_n_items (GListModel *list)
|
||||
{
|
||||
PikaModuleDB *self = PIKA_MODULE_DB (list);
|
||||
return self->modules->len;
|
||||
}
|
||||
|
||||
static void *
|
||||
pika_module_db_get_item (GListModel *list,
|
||||
guint index)
|
||||
{
|
||||
PikaModuleDB *self = PIKA_MODULE_DB (list);
|
||||
|
||||
if (index >= self->modules->len)
|
||||
return NULL;
|
||||
return g_object_ref (g_ptr_array_index (self->modules, index));
|
||||
}
|
||||
|
||||
static void
|
||||
pika_module_db_list_model_iface_init (GListModelInterface *iface)
|
||||
{
|
||||
iface->get_item_type = pika_module_db_get_item_type;
|
||||
iface->get_n_items = pika_module_db_get_n_items;
|
||||
iface->get_item = pika_module_db_get_item;
|
||||
}
|
||||
|
||||
/**
|
||||
* pika_module_db_new:
|
||||
* @verbose: Pass %TRUE to enable debugging output.
|
||||
*
|
||||
* Creates a new #PikaModuleDB instance. The @verbose parameter will be
|
||||
* passed to the created #PikaModule instances using pika_module_new().
|
||||
*
|
||||
* Returns: The new #PikaModuleDB instance.
|
||||
**/
|
||||
PikaModuleDB *
|
||||
pika_module_db_new (gboolean verbose)
|
||||
{
|
||||
PikaModuleDB *db;
|
||||
|
||||
db = g_object_new (PIKA_TYPE_MODULE_DB, NULL);
|
||||
|
||||
db->verbose = verbose ? TRUE : FALSE;
|
||||
|
||||
return db;
|
||||
}
|
||||
|
||||
/**
|
||||
* pika_module_db_set_verbose:
|
||||
* @db: A #PikaModuleDB.
|
||||
* @verbose: the new 'verbose' setting
|
||||
*
|
||||
* Sets the 'verbose' setting of @db.
|
||||
*
|
||||
* Since: 3.0
|
||||
**/
|
||||
void
|
||||
pika_module_db_set_verbose (PikaModuleDB *db,
|
||||
gboolean verbose)
|
||||
{
|
||||
g_return_if_fail (PIKA_IS_MODULE_DB (db));
|
||||
|
||||
db->verbose = verbose ? TRUE : FALSE;
|
||||
}
|
||||
|
||||
/**
|
||||
* pika_module_db_get_verbose:
|
||||
* @db: A #PikaModuleDB.
|
||||
*
|
||||
* Returns the 'verbose' setting of @db.
|
||||
*
|
||||
* Returns: the 'verbose' setting.
|
||||
*
|
||||
* Since: 3.0
|
||||
**/
|
||||
gboolean
|
||||
pika_module_db_get_verbose (PikaModuleDB *db)
|
||||
{
|
||||
g_return_val_if_fail (PIKA_IS_MODULE_DB (db), FALSE);
|
||||
|
||||
return db->verbose;
|
||||
}
|
||||
|
||||
static gboolean
|
||||
is_in_inhibit_list (GFile *file,
|
||||
const gchar *inhibit_list)
|
||||
{
|
||||
gchar *filename;
|
||||
gchar *p;
|
||||
gint pathlen;
|
||||
const gchar *start;
|
||||
const gchar *end;
|
||||
|
||||
if (! inhibit_list || ! strlen (inhibit_list))
|
||||
return FALSE;
|
||||
|
||||
filename = g_file_get_path (file);
|
||||
|
||||
p = strstr (inhibit_list, filename);
|
||||
if (! p)
|
||||
{
|
||||
g_free (filename);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
/* we have a substring, but check for colons either side */
|
||||
start = p;
|
||||
while (start != inhibit_list && *start != G_SEARCHPATH_SEPARATOR)
|
||||
start--;
|
||||
|
||||
if (*start == G_SEARCHPATH_SEPARATOR)
|
||||
start++;
|
||||
|
||||
end = strchr (p, G_SEARCHPATH_SEPARATOR);
|
||||
if (! end)
|
||||
end = inhibit_list + strlen (inhibit_list);
|
||||
|
||||
pathlen = strlen (filename);
|
||||
|
||||
g_free (filename);
|
||||
|
||||
if ((end - start) == pathlen)
|
||||
return TRUE;
|
||||
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
/**
|
||||
* pika_module_db_set_load_inhibit:
|
||||
* @db: A #PikaModuleDB.
|
||||
* @load_inhibit: A #G_SEARCHPATH_SEPARATOR delimited list of module
|
||||
* filenames to exclude from auto-loading.
|
||||
*
|
||||
* Sets the @load_inhibit flag for all #PikaModule's which are kept
|
||||
* by @db (using pika_module_set_load_inhibit()).
|
||||
**/
|
||||
void
|
||||
pika_module_db_set_load_inhibit (PikaModuleDB *db,
|
||||
const gchar *load_inhibit)
|
||||
{
|
||||
guint i;
|
||||
|
||||
g_return_if_fail (PIKA_IS_MODULE_DB (db));
|
||||
|
||||
g_free (db->load_inhibit);
|
||||
|
||||
db->load_inhibit = g_strdup (load_inhibit);
|
||||
|
||||
for (i = 0; i < db->modules->len; i++)
|
||||
{
|
||||
PikaModule *module = g_ptr_array_index (db->modules, i);
|
||||
gboolean inhibit;
|
||||
|
||||
inhibit = is_in_inhibit_list (pika_module_get_file (module),
|
||||
load_inhibit);
|
||||
|
||||
pika_module_set_auto_load (module, ! inhibit);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* pika_module_db_get_load_inhibit:
|
||||
* @db: A #PikaModuleDB.
|
||||
*
|
||||
* Return the #G_SEARCHPATH_SEPARATOR delimited list of module filenames
|
||||
* which are excluded from auto-loading.
|
||||
*
|
||||
* Returns: the @db's @load_inhibit string.
|
||||
**/
|
||||
const gchar *
|
||||
pika_module_db_get_load_inhibit (PikaModuleDB *db)
|
||||
{
|
||||
g_return_val_if_fail (PIKA_IS_MODULE_DB (db), NULL);
|
||||
|
||||
return db->load_inhibit;
|
||||
}
|
||||
|
||||
/**
|
||||
* pika_module_db_load:
|
||||
* @db: A #PikaModuleDB.
|
||||
* @module_path: A #G_SEARCHPATH_SEPARATOR delimited list of directories
|
||||
* to load modules from.
|
||||
*
|
||||
* Scans the directories contained in @module_path and creates a
|
||||
* #PikaModule instance for every loadable module contained in the
|
||||
* directories.
|
||||
**/
|
||||
void
|
||||
pika_module_db_load (PikaModuleDB *db,
|
||||
const gchar *module_path)
|
||||
{
|
||||
g_return_if_fail (PIKA_IS_MODULE_DB (db));
|
||||
g_return_if_fail (module_path != NULL);
|
||||
|
||||
if (g_module_supported ())
|
||||
{
|
||||
GList *path;
|
||||
GList *list;
|
||||
|
||||
path = pika_config_path_expand_to_files (module_path, NULL);
|
||||
|
||||
for (list = path; list; list = g_list_next (list))
|
||||
{
|
||||
pika_module_db_load_directory (db, list->data);
|
||||
}
|
||||
|
||||
g_list_free_full (path, (GDestroyNotify) g_object_unref);
|
||||
}
|
||||
|
||||
if (FALSE)
|
||||
g_ptr_array_foreach (db->modules, pika_module_db_module_dump_func, NULL);
|
||||
}
|
||||
|
||||
/**
|
||||
* pika_module_db_refresh:
|
||||
* @db: A #PikaModuleDB.
|
||||
* @module_path: A #G_SEARCHPATH_SEPARATOR delimited list of directories
|
||||
* to load modules from.
|
||||
*
|
||||
* Does the same as pika_module_db_load(), plus removes all #PikaModule
|
||||
* instances whose modules have been deleted from disk.
|
||||
*
|
||||
* Note that the #PikaModule's will just be removed from the internal
|
||||
* list and not freed as this is not possible with #GTypeModule
|
||||
* instances which actually implement types.
|
||||
**/
|
||||
void
|
||||
pika_module_db_refresh (PikaModuleDB *db,
|
||||
const gchar *module_path)
|
||||
{
|
||||
guint i;
|
||||
|
||||
g_return_if_fail (PIKA_IS_MODULE_DB (db));
|
||||
g_return_if_fail (module_path != NULL);
|
||||
|
||||
for (i = 0; i < db->modules->len; i++)
|
||||
{
|
||||
PikaModule *module = g_ptr_array_index (db->modules, i);
|
||||
|
||||
if (! pika_module_is_on_disk (module) &&
|
||||
! pika_module_is_loaded (module))
|
||||
{
|
||||
g_ptr_array_remove_index (db->modules, i);
|
||||
g_list_model_items_changed (G_LIST_MODEL (db), i, 1, 0);
|
||||
i--;
|
||||
}
|
||||
}
|
||||
|
||||
/* walk filesystem and add new things we find */
|
||||
pika_module_db_load (db, module_path);
|
||||
}
|
||||
|
||||
static void
|
||||
pika_module_db_load_directory (PikaModuleDB *db,
|
||||
GFile *directory)
|
||||
{
|
||||
GFileEnumerator *enumerator;
|
||||
|
||||
enumerator = g_file_enumerate_children (directory,
|
||||
G_FILE_ATTRIBUTE_STANDARD_NAME ","
|
||||
G_FILE_ATTRIBUTE_STANDARD_IS_HIDDEN ","
|
||||
G_FILE_ATTRIBUTE_STANDARD_TYPE,
|
||||
G_FILE_QUERY_INFO_NONE,
|
||||
NULL, NULL);
|
||||
|
||||
if (enumerator)
|
||||
{
|
||||
GFileInfo *info;
|
||||
|
||||
while ((info = g_file_enumerator_next_file (enumerator, NULL, NULL)))
|
||||
{
|
||||
GFileType file_type = g_file_info_get_file_type (info);
|
||||
|
||||
if (file_type == G_FILE_TYPE_REGULAR &&
|
||||
! g_file_info_get_is_hidden (info))
|
||||
{
|
||||
GFile *child = g_file_enumerator_get_child (enumerator, info);
|
||||
|
||||
pika_module_db_load_module (db, child);
|
||||
|
||||
g_object_unref (child);
|
||||
}
|
||||
|
||||
g_object_unref (info);
|
||||
}
|
||||
|
||||
g_object_unref (enumerator);
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
pika_module_db_load_module (PikaModuleDB *db,
|
||||
GFile *file)
|
||||
{
|
||||
PikaModule *module;
|
||||
gboolean load_inhibit;
|
||||
|
||||
if (! pika_file_has_extension (file, "." G_MODULE_SUFFIX))
|
||||
return;
|
||||
|
||||
/* don't load if we already know about it */
|
||||
if (pika_module_db_module_find_by_file (db, file))
|
||||
return;
|
||||
|
||||
load_inhibit = is_in_inhibit_list (file, db->load_inhibit);
|
||||
|
||||
module = pika_module_new (file,
|
||||
! load_inhibit,
|
||||
db->verbose);
|
||||
|
||||
g_ptr_array_add (db->modules, module);
|
||||
g_list_model_items_changed (G_LIST_MODEL (db), db->modules->len - 1, 0, 1);
|
||||
}
|
||||
|
||||
static PikaModule *
|
||||
pika_module_db_module_find_by_file (PikaModuleDB *db,
|
||||
GFile *file)
|
||||
{
|
||||
guint i;
|
||||
|
||||
for (i = 0; i < db->modules->len; i++)
|
||||
{
|
||||
PikaModule *module = g_ptr_array_index (db->modules, i);
|
||||
|
||||
if (g_file_equal (file, pika_module_get_file (module)))
|
||||
return module;
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static void
|
||||
pika_module_db_module_dump_func (gpointer data,
|
||||
gpointer user_data)
|
||||
{
|
||||
static const gchar * const statenames[] =
|
||||
{
|
||||
N_("Module error"),
|
||||
N_("Loaded"),
|
||||
N_("Load failed"),
|
||||
N_("Not loaded")
|
||||
};
|
||||
|
||||
PikaModule *module = data;
|
||||
const PikaModuleInfo *info = pika_module_get_info (module);
|
||||
|
||||
g_print ("\n%s: %s\n",
|
||||
pika_file_get_utf8_name (pika_module_get_file (module)),
|
||||
gettext (statenames[pika_module_get_state (module)]));
|
||||
|
||||
#if 0
|
||||
g_print (" module: %p lasterr: %s query: %p register: %p\n",
|
||||
module->module,
|
||||
module->last_module_error ? module->last_module_error : "NONE",
|
||||
module->query_module,
|
||||
module->register_module);
|
||||
#endif
|
||||
|
||||
if (info)
|
||||
{
|
||||
g_print (" purpose: %s\n"
|
||||
" author: %s\n"
|
||||
" version: %s\n"
|
||||
" copyright: %s\n"
|
||||
" date: %s\n",
|
||||
info->purpose ? info->purpose : "NONE",
|
||||
info->author ? info->author : "NONE",
|
||||
info->version ? info->version : "NONE",
|
||||
info->copyright ? info->copyright : "NONE",
|
||||
info->date ? info->date : "NONE");
|
||||
}
|
||||
}
|
50
libpikamodule/pikamoduledb.h
Normal file
50
libpikamodule/pikamoduledb.h
Normal file
@ -0,0 +1,50 @@
|
||||
/* LIBPIKA - The PIKA Library
|
||||
* Copyright (C) 1995-1997 Peter Mattis and Spencer Kimball
|
||||
*
|
||||
* This library is free software: you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 3 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
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library. If not, see
|
||||
* <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#if !defined (__PIKA_MODULE_H_INSIDE__) && !defined (PIKA_MODULE_COMPILATION)
|
||||
#error "Only <libpikamodule/pikamodule.h> can be included directly."
|
||||
#endif
|
||||
|
||||
#ifndef __PIKA_MODULE_DB_H__
|
||||
#define __PIKA_MODULE_DB_H__
|
||||
|
||||
G_BEGIN_DECLS
|
||||
|
||||
#define PIKA_TYPE_MODULE_DB (pika_module_db_get_type ())
|
||||
G_DECLARE_FINAL_TYPE (PikaModuleDB, pika_module_db, PIKA, MODULE_DB, GObject)
|
||||
|
||||
|
||||
PikaModuleDB * pika_module_db_new (gboolean verbose);
|
||||
|
||||
void pika_module_db_set_verbose (PikaModuleDB *db,
|
||||
gboolean verbose);
|
||||
gboolean pika_module_db_get_verbose (PikaModuleDB *db);
|
||||
|
||||
void pika_module_db_set_load_inhibit (PikaModuleDB *db,
|
||||
const gchar *load_inhibit);
|
||||
const gchar * pika_module_db_get_load_inhibit (PikaModuleDB *db);
|
||||
|
||||
void pika_module_db_load (PikaModuleDB *db,
|
||||
const gchar *module_path);
|
||||
void pika_module_db_refresh (PikaModuleDB *db,
|
||||
const gchar *module_path);
|
||||
|
||||
|
||||
G_END_DECLS
|
||||
|
||||
#endif /* __PIKA_MODULE_DB_H__ */
|
38
libpikamodule/pikamoduletypes.h
Normal file
38
libpikamodule/pikamoduletypes.h
Normal file
@ -0,0 +1,38 @@
|
||||
/* LIBPIKA - The PIKA Library
|
||||
* Copyright (C) 1995-1997 Peter Mattis and Spencer Kimball
|
||||
*
|
||||
* This library is free software: you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 3 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 Lesser General Public
|
||||
* License along with this library. If not, see
|
||||
* <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#ifndef __PIKA_MODULE_TYPES_H__
|
||||
#define __PIKA_MODULE_TYPES_H__
|
||||
|
||||
|
||||
#include <libpikabase/pikabasetypes.h>
|
||||
|
||||
|
||||
G_BEGIN_DECLS
|
||||
|
||||
/* For information look into the C source or the html documentation */
|
||||
|
||||
|
||||
typedef struct _PikaModule PikaModule;
|
||||
typedef struct _PikaModuleInfo PikaModuleInfo;
|
||||
typedef struct _PikaModuleDB PikaModuleDB;
|
||||
|
||||
|
||||
G_END_DECLS
|
||||
|
||||
#endif /* __PIKA_MODULE_TYPES_H__ */
|
Reference in New Issue
Block a user