Initial checkin of Pika from heckimp
This commit is contained in:
61
app/plug-in/meson.build
Normal file
61
app/plug-in/meson.build
Normal file
@ -0,0 +1,61 @@
|
||||
stamp_plug_in_enums = custom_target('stamp-plug-in-enums.h',
|
||||
input : [
|
||||
files(
|
||||
'plug-in-enums.h'
|
||||
),
|
||||
],
|
||||
output: [ 'stamp-plug-in-enums.h', ],
|
||||
command: [
|
||||
mkenums_wrap, perl,
|
||||
meson.project_source_root(), meson.current_source_dir(),
|
||||
meson.current_build_dir(),
|
||||
'plug-in-',
|
||||
'#include <gio/gio.h>\n' +
|
||||
'#include "libpikabase/pikabase.h"\n',
|
||||
'#include "pika-intl.h"'
|
||||
],
|
||||
build_by_default: true
|
||||
)
|
||||
|
||||
libappplugin_sources = [
|
||||
'pikaenvirontable.c',
|
||||
'pikagpparams.c',
|
||||
'pikainterpreterdb.c',
|
||||
'pikaplugin-cleanup.c',
|
||||
'pikaplugin-context.c',
|
||||
'pikaplugin-message.c',
|
||||
'pikaplugin-proc.c',
|
||||
'pikaplugin-progress.c',
|
||||
'pikaplugin.c',
|
||||
'pikaplugindebug.c',
|
||||
'pikaplugindef.c',
|
||||
'pikapluginerror.c',
|
||||
'pikapluginmanager-call.c',
|
||||
'pikapluginmanager-data.c',
|
||||
'pikapluginmanager-file.c',
|
||||
'pikapluginmanager-help-domain.c',
|
||||
'pikapluginmanager-menu-branch.c',
|
||||
'pikapluginmanager-query.c',
|
||||
'pikapluginmanager-restore.c',
|
||||
'pikapluginmanager.c',
|
||||
'pikapluginprocedure.c',
|
||||
'pikapluginprocframe.c',
|
||||
'pikapluginshm.c',
|
||||
'pikatemporaryprocedure.c',
|
||||
'plug-in-menu-path.c',
|
||||
'plug-in-rc.c',
|
||||
|
||||
'plug-in-enums.c',
|
||||
stamp_plug_in_enums,
|
||||
|
||||
appcoremarshal[1],
|
||||
]
|
||||
|
||||
libappplugin = static_library('appplug-in',
|
||||
libappplugin_sources,
|
||||
include_directories: [ rootInclude, rootAppInclude, ],
|
||||
c_args: '-DG_LOG_DOMAIN="Pika-Plug-In"',
|
||||
dependencies: [
|
||||
cairo, gegl, gdk_pixbuf,
|
||||
],
|
||||
)
|
522
app/plug-in/pikaenvirontable.c
Normal file
522
app/plug-in/pikaenvirontable.c
Normal file
@ -0,0 +1,522 @@
|
||||
/* PIKA - Photo and Image Kooker Application
|
||||
* a rebranding of The GNU Image Manipulation Program (created with heckimp)
|
||||
* A derived work which may be trivial. However, any changes may be (C)2023 by Aldercone Studio
|
||||
*
|
||||
* Original copyright, applying to most contents (license remains unchanged):
|
||||
* Copyright (C) 1995 Spencer Kimball and Peter Mattis
|
||||
*
|
||||
* pikaenvirontable.c
|
||||
* (C) 2002 Manish Singh <yosh@gimp.org>
|
||||
*
|
||||
* 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 3 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, 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 "plug-in-types.h"
|
||||
|
||||
#include "pikaenvirontable.h"
|
||||
|
||||
#include "pika-intl.h"
|
||||
|
||||
|
||||
typedef struct _PikaEnvironValue PikaEnvironValue;
|
||||
|
||||
struct _PikaEnvironValue
|
||||
{
|
||||
gchar *value;
|
||||
gchar *separator;
|
||||
};
|
||||
|
||||
|
||||
static void pika_environ_table_finalize (GObject *object);
|
||||
|
||||
static void pika_environ_table_load_env_file (PikaEnvironTable *environ_table,
|
||||
GFile *file);
|
||||
static gboolean pika_environ_table_legal_name (gchar *name);
|
||||
|
||||
static void pika_environ_table_populate (PikaEnvironTable *environ_table);
|
||||
static void pika_environ_table_populate_one (const gchar *name,
|
||||
PikaEnvironValue *val,
|
||||
GPtrArray *env_array);
|
||||
static gboolean pika_environ_table_pass_through (PikaEnvironTable *environ_table,
|
||||
const gchar *name);
|
||||
|
||||
static void pika_environ_table_clear_vars (PikaEnvironTable *environ_table);
|
||||
static void pika_environ_table_clear_internal (PikaEnvironTable *environ_table);
|
||||
static void pika_environ_table_clear_envp (PikaEnvironTable *environ_table);
|
||||
|
||||
static void pika_environ_table_free_value (PikaEnvironValue *val);
|
||||
|
||||
|
||||
G_DEFINE_TYPE (PikaEnvironTable, pika_environ_table, G_TYPE_OBJECT)
|
||||
|
||||
#define parent_class pika_environ_table_parent_class
|
||||
|
||||
|
||||
static void
|
||||
pika_environ_table_class_init (PikaEnvironTableClass *class)
|
||||
{
|
||||
GObjectClass *object_class = G_OBJECT_CLASS (class);
|
||||
|
||||
object_class->finalize = pika_environ_table_finalize;
|
||||
}
|
||||
|
||||
static void
|
||||
pika_environ_table_init (PikaEnvironTable *environ_table)
|
||||
{
|
||||
}
|
||||
|
||||
static void
|
||||
pika_environ_table_finalize (GObject *object)
|
||||
{
|
||||
PikaEnvironTable *environ_table = PIKA_ENVIRON_TABLE (object);
|
||||
|
||||
pika_environ_table_clear_all (environ_table);
|
||||
|
||||
G_OBJECT_CLASS (parent_class)->finalize (object);
|
||||
}
|
||||
|
||||
PikaEnvironTable *
|
||||
pika_environ_table_new (gboolean verbose)
|
||||
{
|
||||
PikaEnvironTable *table = g_object_new (PIKA_TYPE_ENVIRON_TABLE, NULL);
|
||||
|
||||
table->verbose = verbose;
|
||||
|
||||
return table;
|
||||
}
|
||||
|
||||
static guint
|
||||
pika_environ_table_str_hash (gconstpointer v)
|
||||
{
|
||||
#ifdef G_OS_WIN32
|
||||
gchar *p = g_ascii_strup ((const gchar *) v, -1);
|
||||
guint retval = g_str_hash (p);
|
||||
|
||||
g_free (p);
|
||||
|
||||
return retval;
|
||||
#else
|
||||
return g_str_hash (v);
|
||||
#endif
|
||||
}
|
||||
|
||||
static gboolean
|
||||
pika_environ_table_str_equal (gconstpointer v1,
|
||||
gconstpointer v2)
|
||||
{
|
||||
#ifdef G_OS_WIN32
|
||||
gchar *string1 = g_ascii_strup ((const gchar *) v1, -1);
|
||||
gchar *string2 = g_ascii_strup ((const gchar *) v2, -1);
|
||||
gboolean retval = g_str_equal (string1, string2);
|
||||
|
||||
g_free (string1);
|
||||
g_free (string2);
|
||||
|
||||
return retval;
|
||||
#else
|
||||
return g_str_equal (v1, v2);
|
||||
#endif
|
||||
}
|
||||
|
||||
void
|
||||
pika_environ_table_load (PikaEnvironTable *environ_table,
|
||||
GList *path)
|
||||
{
|
||||
GList *list;
|
||||
|
||||
g_return_if_fail (PIKA_IS_ENVIRON_TABLE (environ_table));
|
||||
|
||||
pika_environ_table_clear (environ_table);
|
||||
|
||||
environ_table->vars =
|
||||
g_hash_table_new_full (pika_environ_table_str_hash,
|
||||
pika_environ_table_str_equal,
|
||||
g_free,
|
||||
(GDestroyNotify) pika_environ_table_free_value);
|
||||
|
||||
for (list = path; list; list = g_list_next (list))
|
||||
{
|
||||
GFile *dir = list->data;
|
||||
GFileEnumerator *enumerator;
|
||||
|
||||
enumerator =
|
||||
g_file_enumerate_children (dir,
|
||||
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)))
|
||||
{
|
||||
if (! g_file_info_get_is_hidden (info) &&
|
||||
g_file_info_get_file_type (info) == G_FILE_TYPE_REGULAR)
|
||||
{
|
||||
GFile *file = g_file_enumerator_get_child (enumerator, info);
|
||||
|
||||
pika_environ_table_load_env_file (environ_table, file);
|
||||
|
||||
g_object_unref (file);
|
||||
}
|
||||
|
||||
g_object_unref (info);
|
||||
}
|
||||
|
||||
g_object_unref (enumerator);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
pika_environ_table_add (PikaEnvironTable *environ_table,
|
||||
const gchar *name,
|
||||
const gchar *value,
|
||||
const gchar *separator)
|
||||
{
|
||||
PikaEnvironValue *val;
|
||||
|
||||
g_return_if_fail (PIKA_IS_ENVIRON_TABLE (environ_table));
|
||||
|
||||
pika_environ_table_clear_envp (environ_table);
|
||||
|
||||
if (! environ_table->internal)
|
||||
environ_table->internal =
|
||||
g_hash_table_new_full (g_str_hash, g_str_equal,
|
||||
g_free,
|
||||
(GDestroyNotify) pika_environ_table_free_value);
|
||||
|
||||
val = g_slice_new (PikaEnvironValue);
|
||||
|
||||
val->value = g_strdup (value);
|
||||
val->separator = g_strdup (separator);
|
||||
|
||||
g_hash_table_insert (environ_table->internal, g_strdup (name), val);
|
||||
}
|
||||
|
||||
void
|
||||
pika_environ_table_remove (PikaEnvironTable *environ_table,
|
||||
const gchar *name)
|
||||
{
|
||||
g_return_if_fail (PIKA_IS_ENVIRON_TABLE (environ_table));
|
||||
|
||||
if (! environ_table->internal)
|
||||
return;
|
||||
|
||||
pika_environ_table_clear_envp (environ_table);
|
||||
|
||||
g_hash_table_remove (environ_table->internal, name);
|
||||
|
||||
if (g_hash_table_size (environ_table->internal) == 0)
|
||||
pika_environ_table_clear_internal (environ_table);
|
||||
}
|
||||
|
||||
void
|
||||
pika_environ_table_clear (PikaEnvironTable *environ_table)
|
||||
{
|
||||
g_return_if_fail (PIKA_IS_ENVIRON_TABLE (environ_table));
|
||||
|
||||
pika_environ_table_clear_envp (environ_table);
|
||||
|
||||
pika_environ_table_clear_vars (environ_table);
|
||||
}
|
||||
|
||||
void
|
||||
pika_environ_table_clear_all (PikaEnvironTable *environ_table)
|
||||
{
|
||||
g_return_if_fail (PIKA_IS_ENVIRON_TABLE (environ_table));
|
||||
|
||||
pika_environ_table_clear_envp (environ_table);
|
||||
|
||||
pika_environ_table_clear_vars (environ_table);
|
||||
pika_environ_table_clear_internal (environ_table);
|
||||
}
|
||||
|
||||
gchar **
|
||||
pika_environ_table_get_envp (PikaEnvironTable *environ_table)
|
||||
{
|
||||
g_return_val_if_fail (PIKA_IS_ENVIRON_TABLE (environ_table), NULL);
|
||||
|
||||
/* Hmm.. should we return a copy here in the future? Not thread safe atm,
|
||||
* but the rest of it isn't either.
|
||||
*/
|
||||
|
||||
if (! environ_table->envp)
|
||||
pika_environ_table_populate (environ_table);
|
||||
|
||||
return environ_table->envp;
|
||||
}
|
||||
|
||||
|
||||
/* private */
|
||||
|
||||
static void
|
||||
pika_environ_table_load_env_file (PikaEnvironTable *environ_table,
|
||||
GFile *file)
|
||||
{
|
||||
GInputStream *input;
|
||||
GDataInputStream *data_input;
|
||||
gchar *buffer;
|
||||
gsize buffer_len;
|
||||
GError *error = NULL;
|
||||
|
||||
if (environ_table->verbose)
|
||||
g_print ("Parsing '%s'\n", pika_file_get_utf8_name (file));
|
||||
|
||||
input = G_INPUT_STREAM (g_file_read (file, NULL, &error));
|
||||
if (! input)
|
||||
{
|
||||
g_message (_("Could not open '%s' for reading: %s"),
|
||||
pika_file_get_utf8_name (file),
|
||||
error->message);
|
||||
g_clear_error (&error);
|
||||
return;
|
||||
}
|
||||
|
||||
data_input = g_data_input_stream_new (input);
|
||||
g_object_unref (input);
|
||||
|
||||
while ((buffer = g_data_input_stream_read_line (data_input, &buffer_len,
|
||||
NULL, &error)))
|
||||
{
|
||||
gchar *name;
|
||||
gchar *value;
|
||||
gchar *separator;
|
||||
gchar *p;
|
||||
gchar *q;
|
||||
|
||||
/* Skip comments */
|
||||
if (buffer[0] == '#')
|
||||
{
|
||||
g_free (buffer);
|
||||
continue;
|
||||
}
|
||||
|
||||
p = strchr (buffer, '=');
|
||||
if (! p)
|
||||
{
|
||||
g_free (buffer);
|
||||
continue;
|
||||
}
|
||||
|
||||
*p = '\0';
|
||||
|
||||
name = buffer;
|
||||
value = p + 1;
|
||||
|
||||
if (name[0] == '\0')
|
||||
{
|
||||
g_message (_("Empty variable name in environment file %s"),
|
||||
pika_file_get_utf8_name (file));
|
||||
g_free (buffer);
|
||||
continue;
|
||||
}
|
||||
|
||||
separator = NULL;
|
||||
|
||||
q = strchr (name, ' ');
|
||||
if (q)
|
||||
{
|
||||
*q = '\0';
|
||||
|
||||
separator = name;
|
||||
name = q + 1;
|
||||
}
|
||||
|
||||
if (! pika_environ_table_legal_name (name))
|
||||
{
|
||||
g_message (_("Illegal variable name in environment file %s: %s"),
|
||||
pika_file_get_utf8_name (file), name);
|
||||
g_free (buffer);
|
||||
continue;
|
||||
}
|
||||
|
||||
if (! g_hash_table_lookup (environ_table->vars, name))
|
||||
{
|
||||
PikaEnvironValue *val = g_slice_new (PikaEnvironValue);
|
||||
|
||||
val->value = pika_config_path_expand (value, FALSE, NULL);
|
||||
val->separator = g_strdup (separator);
|
||||
|
||||
g_hash_table_insert (environ_table->vars, g_strdup (name), val);
|
||||
}
|
||||
|
||||
g_free (buffer);
|
||||
}
|
||||
|
||||
if (error)
|
||||
{
|
||||
g_message (_("Error reading '%s': %s"),
|
||||
pika_file_get_utf8_name (file),
|
||||
error->message);
|
||||
g_clear_error (&error);
|
||||
}
|
||||
|
||||
g_object_unref (data_input);
|
||||
}
|
||||
|
||||
static gboolean
|
||||
pika_environ_table_legal_name (gchar *name)
|
||||
{
|
||||
gchar *s;
|
||||
|
||||
if (! g_ascii_isalpha (*name) && (*name != '_'))
|
||||
return FALSE;
|
||||
|
||||
for (s = name + 1; *s; s++)
|
||||
if (! g_ascii_isalnum (*s) && (*s != '_'))
|
||||
return FALSE;
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static void
|
||||
pika_environ_table_populate (PikaEnvironTable *environ_table)
|
||||
{
|
||||
gchar **env = g_listenv ();
|
||||
gchar **var;
|
||||
GPtrArray *env_array;
|
||||
|
||||
var = env;
|
||||
env_array = g_ptr_array_new ();
|
||||
|
||||
while (*var)
|
||||
{
|
||||
/* g_listenv() only returns the names of environment variables
|
||||
* that are correctly specified (name=value) in the environ
|
||||
* array (Unix) or the process environment string table (Win32).
|
||||
*/
|
||||
|
||||
if (pika_environ_table_pass_through (environ_table, *var))
|
||||
g_ptr_array_add (env_array, g_strconcat (*var, "=", g_getenv (*var), NULL));
|
||||
|
||||
var++;
|
||||
}
|
||||
|
||||
g_strfreev (env);
|
||||
|
||||
if (environ_table->vars)
|
||||
g_hash_table_foreach (environ_table->vars,
|
||||
(GHFunc) pika_environ_table_populate_one,
|
||||
env_array);
|
||||
|
||||
if (environ_table->internal)
|
||||
g_hash_table_foreach (environ_table->internal,
|
||||
(GHFunc) pika_environ_table_populate_one,
|
||||
env_array);
|
||||
|
||||
g_ptr_array_add (env_array, NULL);
|
||||
|
||||
environ_table->envp = (gchar **) g_ptr_array_free (env_array, FALSE);
|
||||
|
||||
#ifdef ENVP_DEBUG
|
||||
var = environ_table->envp;
|
||||
|
||||
g_print ("PikaEnvironTable:\n");
|
||||
while (*var)
|
||||
{
|
||||
g_print ("%s\n", *var);
|
||||
var++;
|
||||
}
|
||||
#endif /* ENVP_DEBUG */
|
||||
}
|
||||
|
||||
static void
|
||||
pika_environ_table_populate_one (const gchar *name,
|
||||
PikaEnvironValue *val,
|
||||
GPtrArray *env_array)
|
||||
{
|
||||
const gchar *old;
|
||||
gchar *var = NULL;
|
||||
|
||||
if (val->separator)
|
||||
{
|
||||
old = g_getenv (name);
|
||||
|
||||
if (old)
|
||||
var = g_strconcat (name, "=", val->value, val->separator, old, NULL);
|
||||
}
|
||||
|
||||
if (! var)
|
||||
var = g_strconcat (name, "=", val->value, NULL);
|
||||
|
||||
g_ptr_array_add (env_array, var);
|
||||
}
|
||||
|
||||
static gboolean
|
||||
pika_environ_table_pass_through (PikaEnvironTable *environ_table,
|
||||
const gchar *name)
|
||||
{
|
||||
gboolean vars, internal;
|
||||
|
||||
vars = environ_table->vars &&
|
||||
g_hash_table_lookup (environ_table->vars, name);
|
||||
|
||||
internal = environ_table->internal &&
|
||||
g_hash_table_lookup (environ_table->internal, name);
|
||||
|
||||
return (!vars && !internal);
|
||||
}
|
||||
|
||||
static void
|
||||
pika_environ_table_clear_vars (PikaEnvironTable *environ_table)
|
||||
{
|
||||
if (environ_table->vars)
|
||||
{
|
||||
g_hash_table_destroy (environ_table->vars);
|
||||
environ_table->vars = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
pika_environ_table_clear_internal (PikaEnvironTable *environ_table)
|
||||
{
|
||||
if (environ_table->internal)
|
||||
{
|
||||
g_hash_table_destroy (environ_table->internal);
|
||||
environ_table->internal = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
pika_environ_table_clear_envp (PikaEnvironTable *environ_table)
|
||||
{
|
||||
if (environ_table->envp)
|
||||
{
|
||||
g_strfreev (environ_table->envp);
|
||||
environ_table->envp = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
pika_environ_table_free_value (PikaEnvironValue *val)
|
||||
{
|
||||
g_free (val->value);
|
||||
g_free (val->separator);
|
||||
|
||||
g_slice_free (PikaEnvironValue, val);
|
||||
}
|
76
app/plug-in/pikaenvirontable.h
Normal file
76
app/plug-in/pikaenvirontable.h
Normal file
@ -0,0 +1,76 @@
|
||||
/* PIKA - Photo and Image Kooker Application
|
||||
* a rebranding of The GNU Image Manipulation Program (created with heckimp)
|
||||
* A derived work which may be trivial. However, any changes may be (C)2023 by Aldercone Studio
|
||||
*
|
||||
* Original copyright, applying to most contents (license remains unchanged):
|
||||
* Copyright (C) 1995 Spencer Kimball and Peter Mattis
|
||||
*
|
||||
* pikaenvirontable.h
|
||||
* (C) 2002 Manish Singh <yosh@gimp.org>
|
||||
*
|
||||
* 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 3 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, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#ifndef __PIKA_ENVIRON_TABLE_H__
|
||||
#define __PIKA_ENVIRON_TABLE_H__
|
||||
|
||||
|
||||
#define PIKA_TYPE_ENVIRON_TABLE (pika_environ_table_get_type ())
|
||||
#define PIKA_ENVIRON_TABLE(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), PIKA_TYPE_ENVIRON_TABLE, PikaEnvironTable))
|
||||
#define PIKA_ENVIRON_TABLE_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), PIKA_TYPE_ENVIRON_TABLE, PikaEnvironTableClass))
|
||||
#define PIKA_IS_ENVIRON_TABLE(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), PIKA_TYPE_ENVIRON_TABLE))
|
||||
#define PIKA_IS_ENVIRON_TABLE_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), PIKA_TYPE_ENVIRON_TABLE))
|
||||
#define PIKA_ENVIRON_TABLE_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), PIKA_TYPE_ENVIRON_TABLE, PikaEnvironTableClass))
|
||||
|
||||
|
||||
typedef struct _PikaEnvironTableClass PikaEnvironTableClass;
|
||||
|
||||
struct _PikaEnvironTable
|
||||
{
|
||||
GObject parent_instance;
|
||||
|
||||
gboolean verbose;
|
||||
|
||||
GHashTable *vars;
|
||||
GHashTable *internal;
|
||||
|
||||
gchar **envp;
|
||||
};
|
||||
|
||||
struct _PikaEnvironTableClass
|
||||
{
|
||||
GObjectClass parent_class;
|
||||
};
|
||||
|
||||
|
||||
GType pika_environ_table_get_type (void) G_GNUC_CONST;
|
||||
PikaEnvironTable * pika_environ_table_new (gboolean verbose);
|
||||
|
||||
void pika_environ_table_load (PikaEnvironTable *environ_table,
|
||||
GList *path);
|
||||
|
||||
void pika_environ_table_add (PikaEnvironTable *environ_table,
|
||||
const gchar *name,
|
||||
const gchar *value,
|
||||
const gchar *separator);
|
||||
void pika_environ_table_remove (PikaEnvironTable *environ_table,
|
||||
const gchar *name);
|
||||
|
||||
void pika_environ_table_clear (PikaEnvironTable *environ_table);
|
||||
void pika_environ_table_clear_all (PikaEnvironTable *environ_table);
|
||||
|
||||
gchar ** pika_environ_table_get_envp (PikaEnvironTable *environ_table);
|
||||
|
||||
|
||||
#endif /* __PIKA_ENVIRON_TABLE_H__ */
|
61
app/plug-in/pikagpparams.c
Normal file
61
app/plug-in/pikagpparams.c
Normal file
@ -0,0 +1,61 @@
|
||||
/* PIKA - Photo and Image Kooker Application
|
||||
* a rebranding of The GNU Image Manipulation Program (created with heckimp)
|
||||
* A derived work which may be trivial. However, any changes may be (C)2023 by Aldercone Studio
|
||||
*
|
||||
* Original copyright, applying to most contents (license remains unchanged):
|
||||
* Copyright (C) 1995 Spencer Kimball and Peter Mattis
|
||||
*
|
||||
* pikagpparams.c
|
||||
* Copyright (C) 2019 Michael Natterer <mitch@gimp.org>
|
||||
*
|
||||
* 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 3 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, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include "config.h"
|
||||
|
||||
#include <cairo.h>
|
||||
#include <gdk-pixbuf/gdk-pixbuf.h>
|
||||
#include <gegl.h>
|
||||
|
||||
#include "libpikabase/pikabase.h"
|
||||
#include "libpikacolor/pikacolor.h"
|
||||
#include "libpikabase/pikaprotocol.h"
|
||||
|
||||
#include "plug-in-types.h"
|
||||
|
||||
#include "core/pika.h"
|
||||
#include "core/pikabrush.h"
|
||||
#include "core/pikadisplay.h"
|
||||
#include "core/pikagradient.h"
|
||||
#include "core/pikaimage.h"
|
||||
#include "core/pikalayer.h"
|
||||
#include "core/pikalayermask.h"
|
||||
#include "core/pikapalette.h"
|
||||
#include "core/pikapattern.h"
|
||||
#include "core/pikaselection.h"
|
||||
#include "text/pikafont.h"
|
||||
|
||||
#include "core/pikaparamspecs.h"
|
||||
|
||||
#include "pdb/pikapdb-utils.h"
|
||||
|
||||
#include "vectors/pikavectors.h"
|
||||
|
||||
#include "libpika/pikagpparams.h"
|
||||
|
||||
|
||||
/* include the implementation, they are shared between app/ and
|
||||
* libpika/ but need different headers.
|
||||
*/
|
||||
#include "../../libpika/pikagpparams-body.c"
|
879
app/plug-in/pikainterpreterdb.c
Normal file
879
app/plug-in/pikainterpreterdb.c
Normal file
@ -0,0 +1,879 @@
|
||||
/* PIKA - Photo and Image Kooker Application
|
||||
* a rebranding of The GNU Image Manipulation Program (created with heckimp)
|
||||
* A derived work which may be trivial. However, any changes may be (C)2023 by Aldercone Studio
|
||||
*
|
||||
* Original copyright, applying to most contents (license remains unchanged):
|
||||
* Copyright (C) 1995 Spencer Kimball and Peter Mattis
|
||||
*
|
||||
* pikainterpreterdb.c
|
||||
* (C) 2005 Manish Singh <yosh@gimp.org>
|
||||
*
|
||||
* 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 3 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, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
/*
|
||||
* The binfmt_misc bits are derived from linux/fs/binfmt_misc.c
|
||||
* Copyright (C) 1997 Richard Günther
|
||||
*/
|
||||
|
||||
/*
|
||||
* The sh-bang code is derived from linux/fs/binfmt_script.c
|
||||
* Copyright (C) 1996 Martin von Löwis
|
||||
* original #!-checking implemented by tytso.
|
||||
*/
|
||||
|
||||
#include "config.h"
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
#include <gio/gio.h>
|
||||
|
||||
#include "libpikabase/pikabase.h"
|
||||
|
||||
#include "plug-in-types.h"
|
||||
|
||||
#include "pikainterpreterdb.h"
|
||||
|
||||
#include "pika-intl.h"
|
||||
|
||||
|
||||
#define BUFSIZE 4096
|
||||
|
||||
|
||||
typedef struct _PikaInterpreterMagic PikaInterpreterMagic;
|
||||
|
||||
struct _PikaInterpreterMagic
|
||||
{
|
||||
gulong offset;
|
||||
gchar *magic;
|
||||
gchar *mask;
|
||||
guint size;
|
||||
gchar *program;
|
||||
};
|
||||
|
||||
|
||||
static void pika_interpreter_db_finalize (GObject *object);
|
||||
|
||||
static void pika_interpreter_db_load_interp_file (PikaInterpreterDB *db,
|
||||
GFile *file);
|
||||
|
||||
static void pika_interpreter_db_add_program (PikaInterpreterDB *db,
|
||||
GFile *file,
|
||||
gchar *buffer);
|
||||
static void pika_interpreter_db_add_binfmt_misc (PikaInterpreterDB *db,
|
||||
GFile *file,
|
||||
gchar *buffer);
|
||||
|
||||
static gboolean pika_interpreter_db_add_extension (GFile *file,
|
||||
PikaInterpreterDB *db,
|
||||
gchar **tokens);
|
||||
static gboolean pika_interpreter_db_add_magic (PikaInterpreterDB *db,
|
||||
gchar **tokens);
|
||||
|
||||
static void pika_interpreter_db_clear_magics (PikaInterpreterDB *db);
|
||||
|
||||
static void pika_interpreter_db_resolve_programs (PikaInterpreterDB *db);
|
||||
|
||||
|
||||
G_DEFINE_TYPE (PikaInterpreterDB, pika_interpreter_db, G_TYPE_OBJECT)
|
||||
|
||||
#define parent_class pika_interpreter_db_parent_class
|
||||
|
||||
|
||||
static void
|
||||
pika_interpreter_db_class_init (PikaInterpreterDBClass *class)
|
||||
{
|
||||
GObjectClass *object_class = G_OBJECT_CLASS (class);
|
||||
|
||||
object_class->finalize = pika_interpreter_db_finalize;
|
||||
}
|
||||
|
||||
static void
|
||||
pika_interpreter_db_init (PikaInterpreterDB *db)
|
||||
{
|
||||
}
|
||||
|
||||
static void
|
||||
pika_interpreter_db_finalize (GObject *object)
|
||||
{
|
||||
PikaInterpreterDB *db = PIKA_INTERPRETER_DB (object);
|
||||
|
||||
pika_interpreter_db_clear (db);
|
||||
|
||||
G_OBJECT_CLASS (parent_class)->finalize (object);
|
||||
}
|
||||
|
||||
PikaInterpreterDB *
|
||||
pika_interpreter_db_new (gboolean verbose)
|
||||
{
|
||||
PikaInterpreterDB *db = g_object_new (PIKA_TYPE_INTERPRETER_DB, NULL);
|
||||
|
||||
db->verbose = verbose;
|
||||
|
||||
return db;
|
||||
}
|
||||
|
||||
void
|
||||
pika_interpreter_db_load (PikaInterpreterDB *db,
|
||||
GList *path)
|
||||
{
|
||||
GList *list;
|
||||
|
||||
g_return_if_fail (PIKA_IS_INTERPRETER_DB (db));
|
||||
|
||||
pika_interpreter_db_clear (db);
|
||||
|
||||
db->programs = g_hash_table_new_full (g_str_hash, g_str_equal,
|
||||
g_free, g_free);
|
||||
|
||||
db->extensions = g_hash_table_new_full (g_str_hash, g_str_equal,
|
||||
g_free, g_free);
|
||||
|
||||
db->magic_names = g_hash_table_new_full (g_str_hash, g_str_equal,
|
||||
g_free, NULL);
|
||||
|
||||
db->extension_names = g_hash_table_new_full (g_str_hash, g_str_equal,
|
||||
g_free, NULL);
|
||||
|
||||
for (list = path; list; list = g_list_next (list))
|
||||
{
|
||||
GFile *dir = list->data;
|
||||
GFileEnumerator *enumerator;
|
||||
|
||||
enumerator =
|
||||
g_file_enumerate_children (dir,
|
||||
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)))
|
||||
{
|
||||
if (! g_file_info_get_is_hidden (info) &&
|
||||
g_file_info_get_file_type (info) == G_FILE_TYPE_REGULAR)
|
||||
{
|
||||
GFile *file = g_file_enumerator_get_child (enumerator, info);
|
||||
|
||||
pika_interpreter_db_load_interp_file (db, file);
|
||||
|
||||
g_object_unref (file);
|
||||
}
|
||||
|
||||
g_object_unref (info);
|
||||
}
|
||||
|
||||
g_object_unref (enumerator);
|
||||
}
|
||||
}
|
||||
|
||||
pika_interpreter_db_resolve_programs (db);
|
||||
}
|
||||
|
||||
void
|
||||
pika_interpreter_db_clear (PikaInterpreterDB *db)
|
||||
{
|
||||
g_return_if_fail (PIKA_IS_INTERPRETER_DB (db));
|
||||
|
||||
if (db->magic_names)
|
||||
{
|
||||
g_hash_table_destroy (db->magic_names);
|
||||
db->magic_names = NULL;
|
||||
}
|
||||
|
||||
if (db->extension_names)
|
||||
{
|
||||
g_hash_table_destroy (db->extension_names);
|
||||
db->extension_names = NULL;
|
||||
}
|
||||
|
||||
if (db->programs)
|
||||
{
|
||||
g_hash_table_destroy (db->programs);
|
||||
db->programs = NULL;
|
||||
}
|
||||
|
||||
if (db->extensions)
|
||||
{
|
||||
g_hash_table_destroy (db->extensions);
|
||||
db->extensions = NULL;
|
||||
}
|
||||
|
||||
pika_interpreter_db_clear_magics (db);
|
||||
}
|
||||
|
||||
static void
|
||||
pika_interpreter_db_load_interp_file (PikaInterpreterDB *db,
|
||||
GFile *file)
|
||||
{
|
||||
GInputStream *input;
|
||||
GDataInputStream *data_input;
|
||||
gchar *buffer;
|
||||
gsize buffer_len;
|
||||
GError *error = NULL;
|
||||
|
||||
if (db->verbose)
|
||||
g_print ("Parsing '%s'\n", pika_file_get_utf8_name (file));
|
||||
|
||||
input = G_INPUT_STREAM (g_file_read (file, NULL, &error));
|
||||
if (! input)
|
||||
{
|
||||
g_message (_("Could not open '%s' for reading: %s"),
|
||||
pika_file_get_utf8_name (file),
|
||||
error->message);
|
||||
g_clear_error (&error);
|
||||
return;
|
||||
}
|
||||
|
||||
data_input = g_data_input_stream_new (input);
|
||||
g_object_unref (input);
|
||||
|
||||
while ((buffer = g_data_input_stream_read_line (data_input, &buffer_len,
|
||||
NULL, &error)))
|
||||
{
|
||||
/* Skip comments */
|
||||
if (buffer[0] == '#')
|
||||
{
|
||||
g_free (buffer);
|
||||
continue;
|
||||
}
|
||||
|
||||
if (g_ascii_isalnum (buffer[0]) || (buffer[0] == '/'))
|
||||
{
|
||||
pika_interpreter_db_add_program (db, file, buffer);
|
||||
}
|
||||
else if (! g_ascii_isspace (buffer[0]) && (buffer[0] != '\0'))
|
||||
{
|
||||
pika_interpreter_db_add_binfmt_misc (db, file, buffer);
|
||||
}
|
||||
|
||||
g_free (buffer);
|
||||
}
|
||||
|
||||
if (error)
|
||||
{
|
||||
g_message (_("Error reading '%s': %s"),
|
||||
pika_file_get_utf8_name (file),
|
||||
error->message);
|
||||
g_clear_error (&error);
|
||||
}
|
||||
|
||||
g_object_unref (data_input);
|
||||
}
|
||||
|
||||
static void
|
||||
pika_interpreter_db_add_program (PikaInterpreterDB *db,
|
||||
GFile *file,
|
||||
gchar *buffer)
|
||||
{
|
||||
gchar *name;
|
||||
gchar *program;
|
||||
gchar *p;
|
||||
|
||||
p = strchr (buffer, '=');
|
||||
if (! p)
|
||||
return;
|
||||
|
||||
*p = '\0';
|
||||
|
||||
name = buffer;
|
||||
program = p + 1;
|
||||
g_strchomp (program);
|
||||
|
||||
if (! g_file_test (program, G_FILE_TEST_IS_EXECUTABLE))
|
||||
{
|
||||
gchar *prog;
|
||||
|
||||
prog = g_find_program_in_path (program);
|
||||
if (! prog || ! g_file_test (prog, G_FILE_TEST_IS_EXECUTABLE))
|
||||
{
|
||||
g_message (_("Bad interpreter referenced in interpreter file %s: %s"),
|
||||
pika_file_get_utf8_name (file),
|
||||
pika_filename_to_utf8 (program));
|
||||
if (prog)
|
||||
g_free (prog);
|
||||
return;
|
||||
}
|
||||
program = prog;
|
||||
}
|
||||
else
|
||||
program = g_strdup (program);
|
||||
|
||||
if (! g_hash_table_lookup (db->programs, name))
|
||||
g_hash_table_insert (db->programs, g_strdup (name), program);
|
||||
}
|
||||
|
||||
static void
|
||||
pika_interpreter_db_add_binfmt_misc (PikaInterpreterDB *db,
|
||||
GFile *file,
|
||||
gchar *buffer)
|
||||
{
|
||||
gchar **tokens = NULL;
|
||||
gchar *name, *type, *program;
|
||||
gsize count;
|
||||
gchar del[2];
|
||||
|
||||
count = strlen (buffer);
|
||||
|
||||
if ((count < 10) || (count > 255))
|
||||
goto bail;
|
||||
|
||||
buffer = g_strndup (buffer, count + 9);
|
||||
|
||||
del[0] = *buffer;
|
||||
del[1] = '\0';
|
||||
|
||||
memset (buffer + count, del[0], 8);
|
||||
|
||||
tokens = g_strsplit (buffer + 1, del, -1);
|
||||
|
||||
g_free (buffer);
|
||||
|
||||
name = tokens[0];
|
||||
type = tokens[1];
|
||||
program = tokens[5];
|
||||
|
||||
if ((name[0] == '\0') || (program[0] == '\0') ||
|
||||
(type[0] == '\0') || (type[1] != '\0'))
|
||||
goto bail;
|
||||
|
||||
switch (type[0])
|
||||
{
|
||||
case 'E':
|
||||
if (! pika_interpreter_db_add_extension (file, db, tokens))
|
||||
goto bail;
|
||||
break;
|
||||
|
||||
case 'M':
|
||||
if (! pika_interpreter_db_add_magic (db, tokens))
|
||||
goto bail;
|
||||
break;
|
||||
|
||||
default:
|
||||
goto bail;
|
||||
}
|
||||
|
||||
goto out;
|
||||
|
||||
bail:
|
||||
g_message (_("Bad binary format string in interpreter file %s"),
|
||||
pika_file_get_utf8_name (file));
|
||||
|
||||
out:
|
||||
g_strfreev (tokens);
|
||||
}
|
||||
|
||||
static gboolean
|
||||
pika_interpreter_db_add_extension (GFile *file,
|
||||
PikaInterpreterDB *db,
|
||||
gchar **tokens)
|
||||
{
|
||||
const gchar *name = tokens[0];
|
||||
const gchar *extension = tokens[3];
|
||||
const gchar *program = tokens[5];
|
||||
|
||||
if (! g_hash_table_lookup (db->extension_names, name))
|
||||
{
|
||||
gchar *prog;
|
||||
|
||||
if (extension[0] == '\0' || extension[0] == '/')
|
||||
return FALSE;
|
||||
|
||||
if (! g_file_test (program, G_FILE_TEST_IS_EXECUTABLE))
|
||||
{
|
||||
prog = g_find_program_in_path (program);
|
||||
if (! prog || ! g_file_test (prog, G_FILE_TEST_IS_EXECUTABLE))
|
||||
{
|
||||
g_message (_("Bad interpreter referenced in interpreter file %s: %s"),
|
||||
pika_file_get_utf8_name (file),
|
||||
pika_filename_to_utf8 (program));
|
||||
if (prog)
|
||||
g_free (prog);
|
||||
return FALSE;
|
||||
}
|
||||
}
|
||||
else
|
||||
prog = g_strdup (program);
|
||||
|
||||
g_hash_table_insert (db->extensions, g_strdup (extension), prog);
|
||||
g_hash_table_insert (db->extension_names, g_strdup (name), prog);
|
||||
}
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static gboolean
|
||||
scanarg (const gchar *s)
|
||||
{
|
||||
gchar c;
|
||||
|
||||
while ((c = *s++) != '\0')
|
||||
{
|
||||
if (c == '\\' && *s == 'x')
|
||||
{
|
||||
s++;
|
||||
|
||||
if (! g_ascii_isxdigit (*s++))
|
||||
return FALSE;
|
||||
|
||||
if (! g_ascii_isxdigit (*s++))
|
||||
return FALSE;
|
||||
}
|
||||
}
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static guint
|
||||
unquote (gchar *from)
|
||||
{
|
||||
gchar *s = from;
|
||||
gchar *p = from;
|
||||
gchar c;
|
||||
|
||||
while ((c = *s++) != '\0')
|
||||
{
|
||||
if (c == '\\' && *s == 'x')
|
||||
{
|
||||
s++;
|
||||
*p = g_ascii_xdigit_value (*s++) << 4;
|
||||
*p++ |= g_ascii_xdigit_value (*s++);
|
||||
continue;
|
||||
}
|
||||
|
||||
*p++ = c;
|
||||
}
|
||||
|
||||
return p - from;
|
||||
}
|
||||
|
||||
static gboolean
|
||||
pika_interpreter_db_add_magic (PikaInterpreterDB *db,
|
||||
gchar **tokens)
|
||||
{
|
||||
PikaInterpreterMagic *interp_magic;
|
||||
gchar *name, *num, *magic, *mask, *program;
|
||||
gulong offset;
|
||||
guint size;
|
||||
|
||||
name = tokens[0];
|
||||
num = tokens[2];
|
||||
magic = tokens[3];
|
||||
mask = tokens[4];
|
||||
program = tokens[5];
|
||||
|
||||
if (! g_hash_table_lookup (db->magic_names, name))
|
||||
{
|
||||
if (num[0] != '\0')
|
||||
{
|
||||
offset = strtoul (num, &num, 10);
|
||||
|
||||
if (num[0] != '\0')
|
||||
return FALSE;
|
||||
|
||||
if (offset > (BUFSIZE / 4))
|
||||
return FALSE;
|
||||
}
|
||||
else
|
||||
{
|
||||
offset = 0;
|
||||
}
|
||||
|
||||
if (! scanarg (magic))
|
||||
return FALSE;
|
||||
|
||||
if (! scanarg (mask))
|
||||
return FALSE;
|
||||
|
||||
size = unquote (magic);
|
||||
|
||||
if ((size + offset) > (BUFSIZE / 2))
|
||||
return FALSE;
|
||||
|
||||
if (mask[0] == '\0')
|
||||
mask = NULL;
|
||||
else if (unquote (mask) != size)
|
||||
return FALSE;
|
||||
|
||||
interp_magic = g_slice_new (PikaInterpreterMagic);
|
||||
|
||||
interp_magic->offset = offset;
|
||||
interp_magic->magic = g_memdup2 (magic, size);
|
||||
interp_magic->mask = g_memdup2 (mask, size);
|
||||
interp_magic->size = size;
|
||||
interp_magic->program = g_strdup (program);
|
||||
|
||||
db->magics = g_slist_append (db->magics, interp_magic);
|
||||
|
||||
g_hash_table_insert (db->magic_names, g_strdup (name), interp_magic);
|
||||
}
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static void
|
||||
pika_interpreter_db_clear_magics (PikaInterpreterDB *db)
|
||||
{
|
||||
PikaInterpreterMagic *magic;
|
||||
GSList *list, *last;
|
||||
|
||||
list = db->magics;
|
||||
db->magics = NULL;
|
||||
|
||||
while (list)
|
||||
{
|
||||
magic = list->data;
|
||||
|
||||
g_free (magic->magic);
|
||||
g_free (magic->mask);
|
||||
g_free (magic->program);
|
||||
|
||||
g_slice_free (PikaInterpreterMagic, magic);
|
||||
|
||||
last = list;
|
||||
list = list->next;
|
||||
|
||||
g_slist_free_1 (last);
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef INTERP_DEBUG
|
||||
static void
|
||||
print_kv (gpointer key,
|
||||
gpointer value,
|
||||
gpointer user_data)
|
||||
{
|
||||
g_print ("%s: %s\n", (gchar *) key, (gchar *) value);
|
||||
}
|
||||
|
||||
static gchar *
|
||||
quote (gchar *s,
|
||||
guint size)
|
||||
{
|
||||
GString *d;
|
||||
guint i;
|
||||
|
||||
if (s == NULL)
|
||||
return "(null)";
|
||||
|
||||
d = g_string_sized_new (size * 4);
|
||||
|
||||
for (i = 0; i < size; i++)
|
||||
g_string_append_printf (d, "\\x%02x", ((guint) s[i]) & 0xff);
|
||||
|
||||
return g_string_free (d, FALSE);
|
||||
}
|
||||
#endif
|
||||
|
||||
static gboolean
|
||||
resolve_program (gpointer key,
|
||||
gpointer value,
|
||||
gpointer user_data)
|
||||
{
|
||||
PikaInterpreterDB *db = user_data;
|
||||
gchar *program;
|
||||
|
||||
program = g_hash_table_lookup (db->programs, value);
|
||||
|
||||
if (program != NULL)
|
||||
{
|
||||
g_free (value);
|
||||
value = g_strdup (program);
|
||||
}
|
||||
|
||||
g_hash_table_insert (db->extensions, key, value);
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static void
|
||||
pika_interpreter_db_resolve_programs (PikaInterpreterDB *db)
|
||||
{
|
||||
GSList *list;
|
||||
GHashTable *extensions;
|
||||
|
||||
for (list = db->magics; list; list = list->next)
|
||||
{
|
||||
PikaInterpreterMagic *magic = list->data;
|
||||
const gchar *program;
|
||||
|
||||
program = g_hash_table_lookup (db->programs, magic->program);
|
||||
|
||||
if (program != NULL)
|
||||
{
|
||||
g_free (magic->program);
|
||||
magic->program = g_strdup (program);
|
||||
}
|
||||
}
|
||||
|
||||
extensions = db->extensions;
|
||||
db->extensions = g_hash_table_new_full (g_str_hash, g_str_equal,
|
||||
g_free, g_free);
|
||||
|
||||
g_hash_table_foreach_steal (extensions, resolve_program, db);
|
||||
|
||||
g_hash_table_destroy (extensions);
|
||||
|
||||
#ifdef INTERP_DEBUG
|
||||
g_print ("Programs:\n");
|
||||
g_hash_table_foreach (db->programs, print_kv, NULL);
|
||||
|
||||
g_print ("\nExtensions:\n");
|
||||
g_hash_table_foreach (db->extensions, print_kv, NULL);
|
||||
|
||||
g_print ("\nMagics:\n");
|
||||
|
||||
list = db->magics;
|
||||
|
||||
while (list)
|
||||
{
|
||||
PikaInterpreterMagic *magic;
|
||||
|
||||
magic = list->data;
|
||||
g_print ("program: %s, offset: %lu, magic: %s, mask: %s\n",
|
||||
magic->program, magic->offset,
|
||||
quote (magic->magic, magic->size),
|
||||
quote (magic->mask, magic->size));
|
||||
|
||||
list = list->next;
|
||||
}
|
||||
|
||||
g_print ("\n");
|
||||
#endif
|
||||
}
|
||||
|
||||
static gchar *
|
||||
resolve_extension (PikaInterpreterDB *db,
|
||||
const gchar *program_path)
|
||||
{
|
||||
gchar *filename;
|
||||
gchar *p;
|
||||
const gchar *program;
|
||||
|
||||
filename = g_path_get_basename (program_path);
|
||||
|
||||
p = strrchr (filename, '.');
|
||||
if (! p)
|
||||
{
|
||||
g_free (filename);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
program = g_hash_table_lookup (db->extensions, p + 1);
|
||||
|
||||
g_free (filename);
|
||||
|
||||
return g_strdup (program);
|
||||
}
|
||||
|
||||
static gchar *
|
||||
resolve_sh_bang (PikaInterpreterDB *db,
|
||||
const gchar *program_path,
|
||||
gchar *buffer,
|
||||
gssize len,
|
||||
gchar **interp_arg)
|
||||
{
|
||||
gchar *cp;
|
||||
gchar *name;
|
||||
gchar *program;
|
||||
|
||||
cp = strchr (buffer, '\n');
|
||||
if (! cp)
|
||||
cp = buffer + len - 1;
|
||||
|
||||
*cp = '\0';
|
||||
|
||||
while (cp > buffer)
|
||||
{
|
||||
cp--;
|
||||
if ((*cp == ' ') || (*cp == '\t') || (*cp == '\r'))
|
||||
*cp = '\0';
|
||||
else
|
||||
break;
|
||||
}
|
||||
|
||||
for (cp = buffer + 2; (*cp == ' ') || (*cp == '\t'); cp++);
|
||||
|
||||
if (*cp == '\0')
|
||||
return NULL;
|
||||
|
||||
name = cp;
|
||||
|
||||
for ( ; *cp && (*cp != ' ') && (*cp != '\t'); cp++)
|
||||
/* nothing */ ;
|
||||
|
||||
while ((*cp == ' ') || (*cp == '\t'))
|
||||
*cp++ = '\0';
|
||||
|
||||
if (*cp)
|
||||
{
|
||||
if (strcmp ("/usr/bin/env", name) == 0)
|
||||
{
|
||||
program = g_hash_table_lookup (db->programs, cp);
|
||||
|
||||
if (program)
|
||||
{
|
||||
/* Shift program name and arguments to the right, if and
|
||||
* only if we recorded a specific interpreter for such
|
||||
* script. Otherwise let `env` tool do its job.
|
||||
*/
|
||||
name = cp;
|
||||
|
||||
for ( ; *cp && (*cp != ' ') && (*cp != '\t'); cp++)
|
||||
;
|
||||
|
||||
while ((*cp == ' ') || (*cp == '\t'))
|
||||
*cp++ = '\0';
|
||||
}
|
||||
}
|
||||
|
||||
if (*cp)
|
||||
*interp_arg = g_strdup (cp);
|
||||
}
|
||||
|
||||
program = g_hash_table_lookup (db->programs, name);
|
||||
if (! program)
|
||||
program = name;
|
||||
|
||||
return g_strdup (program);
|
||||
}
|
||||
|
||||
static gchar *
|
||||
resolve_magic (PikaInterpreterDB *db,
|
||||
const gchar *program_path,
|
||||
gchar *buffer)
|
||||
{
|
||||
GSList *list;
|
||||
PikaInterpreterMagic *magic;
|
||||
gchar *s;
|
||||
guint i;
|
||||
|
||||
list = db->magics;
|
||||
|
||||
while (list)
|
||||
{
|
||||
magic = list->data;
|
||||
|
||||
s = buffer + magic->offset;
|
||||
|
||||
if (magic->mask)
|
||||
{
|
||||
for (i = 0; i < magic->size; i++)
|
||||
if ((*s++ ^ magic->magic[i]) & magic->mask[i])
|
||||
break;
|
||||
}
|
||||
else
|
||||
{
|
||||
for (i = 0; i < magic->size; i++)
|
||||
if ((*s++ ^ magic->magic[i]))
|
||||
break;
|
||||
}
|
||||
|
||||
if (i == magic->size)
|
||||
return g_strdup (magic->program);
|
||||
|
||||
list = list->next;
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
gchar *
|
||||
pika_interpreter_db_resolve (PikaInterpreterDB *db,
|
||||
const gchar *program_path,
|
||||
gchar **interp_arg)
|
||||
{
|
||||
GFile *file;
|
||||
GInputStream *input;
|
||||
gchar *program = NULL;
|
||||
|
||||
g_return_val_if_fail (PIKA_IS_INTERPRETER_DB (db), NULL);
|
||||
g_return_val_if_fail (program_path != NULL, NULL);
|
||||
g_return_val_if_fail (interp_arg != NULL, NULL);
|
||||
|
||||
*interp_arg = NULL;
|
||||
|
||||
file = g_file_new_for_path (program_path);
|
||||
input = G_INPUT_STREAM (g_file_read (file, NULL, NULL));
|
||||
g_object_unref (file);
|
||||
|
||||
if (input)
|
||||
{
|
||||
gsize bytes_read;
|
||||
gchar buffer[BUFSIZE];
|
||||
|
||||
memset (buffer, 0, sizeof (buffer));
|
||||
g_input_stream_read_all (input, buffer,
|
||||
sizeof (buffer) - 1, /* leave one nul at the end */
|
||||
&bytes_read, NULL, NULL);
|
||||
g_object_unref (input);
|
||||
|
||||
if (bytes_read)
|
||||
{
|
||||
if (bytes_read > 3 && buffer[0] == '#' && buffer[1] == '!')
|
||||
program = resolve_sh_bang (db, program_path, buffer, bytes_read, interp_arg);
|
||||
|
||||
if (! program)
|
||||
program = resolve_magic (db, program_path, buffer);
|
||||
}
|
||||
}
|
||||
|
||||
if (! program)
|
||||
program = resolve_extension (db, program_path);
|
||||
|
||||
return program;
|
||||
}
|
||||
|
||||
static void
|
||||
collect_extensions (const gchar *ext,
|
||||
const gchar *program G_GNUC_UNUSED,
|
||||
GString *str)
|
||||
{
|
||||
if (str->len)
|
||||
g_string_append_c (str, G_SEARCHPATH_SEPARATOR);
|
||||
|
||||
g_string_append_c (str, '.');
|
||||
g_string_append (str, ext);
|
||||
}
|
||||
|
||||
/**
|
||||
* pika_interpreter_db_get_extensions:
|
||||
* @db:
|
||||
*
|
||||
* Returns: a newly allocated string with all registered file
|
||||
* extensions separated by %G_SEARCHPATH_SEPARATOR;
|
||||
* or %NULL if no extensions are registered
|
||||
**/
|
||||
gchar *
|
||||
pika_interpreter_db_get_extensions (PikaInterpreterDB *db)
|
||||
{
|
||||
GString *str;
|
||||
|
||||
g_return_val_if_fail (PIKA_IS_INTERPRETER_DB (db), NULL);
|
||||
|
||||
if (g_hash_table_size (db->extensions) == 0)
|
||||
return NULL;
|
||||
|
||||
str = g_string_new (NULL);
|
||||
|
||||
g_hash_table_foreach (db->extensions, (GHFunc) collect_extensions, str);
|
||||
|
||||
return g_string_free (str, FALSE);
|
||||
}
|
74
app/plug-in/pikainterpreterdb.h
Normal file
74
app/plug-in/pikainterpreterdb.h
Normal file
@ -0,0 +1,74 @@
|
||||
/* PIKA - Photo and Image Kooker Application
|
||||
* a rebranding of The GNU Image Manipulation Program (created with heckimp)
|
||||
* A derived work which may be trivial. However, any changes may be (C)2023 by Aldercone Studio
|
||||
*
|
||||
* Original copyright, applying to most contents (license remains unchanged):
|
||||
* Copyright (C) 1995 Spencer Kimball and Peter Mattis
|
||||
*
|
||||
* pikainterpreterdb.h
|
||||
* (C) 2005 Manish Singh <yosh@gimp.org>
|
||||
*
|
||||
* 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 3 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, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#ifndef __PIKA_INTERPRETER_DB_H__
|
||||
#define __PIKA_INTERPRETER_DB_H__
|
||||
|
||||
|
||||
#define PIKA_TYPE_INTERPRETER_DB (pika_interpreter_db_get_type ())
|
||||
#define PIKA_INTERPRETER_DB(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), PIKA_TYPE_INTERPRETER_DB, PikaInterpreterDB))
|
||||
#define PIKA_INTERPRETER_DB_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), PIKA_TYPE_INTERPRETER_DB, PikaInterpreterDBClass))
|
||||
#define PIKA_IS_INTERPRETER_DB(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), PIKA_TYPE_INTERPRETER_DB))
|
||||
#define PIKA_IS_INTERPRETER_DB_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), PIKA_TYPE_INTERPRETER_DB))
|
||||
#define PIKA_INTERPRETER_DB_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), PIKA_TYPE_INTERPRETER_DB, PikaInterpreterDBClass))
|
||||
|
||||
|
||||
typedef struct _PikaInterpreterDBClass PikaInterpreterDBClass;
|
||||
|
||||
struct _PikaInterpreterDB
|
||||
{
|
||||
GObject parent_instance;
|
||||
|
||||
gboolean verbose;
|
||||
|
||||
GHashTable *programs;
|
||||
|
||||
GSList *magics;
|
||||
GHashTable *magic_names;
|
||||
|
||||
GHashTable *extensions;
|
||||
GHashTable *extension_names;
|
||||
};
|
||||
|
||||
struct _PikaInterpreterDBClass
|
||||
{
|
||||
GObjectClass parent_class;
|
||||
};
|
||||
|
||||
|
||||
GType pika_interpreter_db_get_type (void) G_GNUC_CONST;
|
||||
PikaInterpreterDB * pika_interpreter_db_new (gboolean verbose);
|
||||
|
||||
void pika_interpreter_db_load (PikaInterpreterDB *db,
|
||||
GList *path);
|
||||
|
||||
void pika_interpreter_db_clear (PikaInterpreterDB *db);
|
||||
|
||||
gchar * pika_interpreter_db_resolve (PikaInterpreterDB *db,
|
||||
const gchar *program_path,
|
||||
gchar **interp_arg);
|
||||
gchar * pika_interpreter_db_get_extensions (PikaInterpreterDB *db);
|
||||
|
||||
|
||||
#endif /* __PIKA_INTERPRETER_DB_H__ */
|
582
app/plug-in/pikaplugin-cleanup.c
Normal file
582
app/plug-in/pikaplugin-cleanup.c
Normal file
@ -0,0 +1,582 @@
|
||||
/* PIKA - Photo and Image Kooker Application
|
||||
* a rebranding of The GNU Image Manipulation Program (created with heckimp)
|
||||
* A derived work which may be trivial. However, any changes may be (C)2023 by Aldercone Studio
|
||||
*
|
||||
* Original copyright, applying to most contents (license remains unchanged):
|
||||
* Copyright (C) 1995 Spencer Kimball and Peter Mattis
|
||||
*
|
||||
* pikaplugin-cleanup.c
|
||||
*
|
||||
* 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 3 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, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include "config.h"
|
||||
|
||||
#include <gdk-pixbuf/gdk-pixbuf.h>
|
||||
#include <gegl.h>
|
||||
|
||||
#include "plug-in-types.h"
|
||||
|
||||
#include "core/pika.h"
|
||||
#include "core/pikacontainer.h"
|
||||
#include "core/pikadrawable.h"
|
||||
#include "core/pikadrawable-shadow.h"
|
||||
#include "core/pikaimage.h"
|
||||
#include "core/pikaimage-undo.h"
|
||||
#include "core/pikaundostack.h"
|
||||
|
||||
#include "pikaplugin.h"
|
||||
#include "pikaplugin-cleanup.h"
|
||||
#include "pikapluginmanager.h"
|
||||
#include "pikapluginprocedure.h"
|
||||
|
||||
#include "pika-log.h"
|
||||
|
||||
|
||||
typedef struct _PikaPlugInCleanupImage PikaPlugInCleanupImage;
|
||||
|
||||
struct _PikaPlugInCleanupImage
|
||||
{
|
||||
PikaImage *image;
|
||||
gint image_id;
|
||||
|
||||
gint undo_group_count;
|
||||
gint layers_freeze_count;
|
||||
gint channels_freeze_count;
|
||||
gint vectors_freeze_count;
|
||||
};
|
||||
|
||||
|
||||
typedef struct _PikaPlugInCleanupItem PikaPlugInCleanupItem;
|
||||
|
||||
struct _PikaPlugInCleanupItem
|
||||
{
|
||||
PikaItem *item;
|
||||
gint item_id;
|
||||
|
||||
gboolean shadow_buffer;
|
||||
};
|
||||
|
||||
|
||||
/* local function prototypes */
|
||||
|
||||
static PikaPlugInCleanupImage *
|
||||
pika_plug_in_cleanup_image_new (PikaPlugInProcFrame *proc_frame,
|
||||
PikaImage *image);
|
||||
static void pika_plug_in_cleanup_image_free (PikaPlugInProcFrame *proc_frame,
|
||||
PikaPlugInCleanupImage *cleanup);
|
||||
static gboolean
|
||||
pika_plug_in_cleanup_image_is_clean (PikaPlugInCleanupImage *cleanup);
|
||||
static PikaPlugInCleanupImage *
|
||||
pika_plug_in_cleanup_image_get (PikaPlugInProcFrame *proc_frame,
|
||||
PikaImage *image);
|
||||
static void pika_plug_in_cleanup_image (PikaPlugInProcFrame *proc_frame,
|
||||
PikaPlugInCleanupImage *cleanup);
|
||||
|
||||
static PikaPlugInCleanupItem *
|
||||
pika_plug_in_cleanup_item_new (PikaPlugInProcFrame *proc_frame,
|
||||
PikaItem *item);
|
||||
static void pika_plug_in_cleanup_item_free (PikaPlugInProcFrame *proc_frame,
|
||||
PikaPlugInCleanupItem *cleanup);
|
||||
static gboolean
|
||||
pika_plug_in_cleanup_item_is_clean (PikaPlugInCleanupItem *cleanup);
|
||||
static PikaPlugInCleanupItem *
|
||||
pika_plug_in_cleanup_item_get (PikaPlugInProcFrame *proc_frame,
|
||||
PikaItem *item);
|
||||
static void pika_plug_in_cleanup_item (PikaPlugInProcFrame *proc_frame,
|
||||
PikaPlugInCleanupItem *cleanup);
|
||||
|
||||
|
||||
/* public functions */
|
||||
|
||||
gboolean
|
||||
pika_plug_in_cleanup_undo_group_start (PikaPlugIn *plug_in,
|
||||
PikaImage *image)
|
||||
{
|
||||
PikaPlugInProcFrame *proc_frame;
|
||||
PikaPlugInCleanupImage *cleanup;
|
||||
|
||||
g_return_val_if_fail (PIKA_IS_PLUG_IN (plug_in), FALSE);
|
||||
g_return_val_if_fail (PIKA_IS_IMAGE (image), FALSE);
|
||||
|
||||
proc_frame = pika_plug_in_get_proc_frame (plug_in);
|
||||
cleanup = pika_plug_in_cleanup_image_get (proc_frame, image);
|
||||
|
||||
if (! cleanup)
|
||||
cleanup = pika_plug_in_cleanup_image_new (proc_frame, image);
|
||||
|
||||
cleanup->undo_group_count++;
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
gboolean
|
||||
pika_plug_in_cleanup_undo_group_end (PikaPlugIn *plug_in,
|
||||
PikaImage *image)
|
||||
{
|
||||
PikaPlugInProcFrame *proc_frame;
|
||||
PikaPlugInCleanupImage *cleanup;
|
||||
|
||||
g_return_val_if_fail (PIKA_IS_PLUG_IN (plug_in), FALSE);
|
||||
g_return_val_if_fail (PIKA_IS_IMAGE (image), FALSE);
|
||||
|
||||
proc_frame = pika_plug_in_get_proc_frame (plug_in);
|
||||
cleanup = pika_plug_in_cleanup_image_get (proc_frame, image);
|
||||
|
||||
if (! cleanup)
|
||||
return FALSE;
|
||||
|
||||
if (cleanup->undo_group_count > 0)
|
||||
{
|
||||
cleanup->undo_group_count--;
|
||||
|
||||
if (pika_plug_in_cleanup_image_is_clean (cleanup))
|
||||
pika_plug_in_cleanup_image_free (proc_frame, cleanup);
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
gboolean
|
||||
pika_plug_in_cleanup_layers_freeze (PikaPlugIn *plug_in,
|
||||
PikaImage *image)
|
||||
{
|
||||
PikaPlugInProcFrame *proc_frame;
|
||||
PikaPlugInCleanupImage *cleanup;
|
||||
|
||||
g_return_val_if_fail (PIKA_IS_PLUG_IN (plug_in), FALSE);
|
||||
g_return_val_if_fail (PIKA_IS_IMAGE (image), FALSE);
|
||||
|
||||
proc_frame = pika_plug_in_get_proc_frame (plug_in);
|
||||
cleanup = pika_plug_in_cleanup_image_get (proc_frame, image);
|
||||
|
||||
if (! cleanup)
|
||||
cleanup = pika_plug_in_cleanup_image_new (proc_frame, image);
|
||||
|
||||
cleanup->layers_freeze_count++;
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
gboolean
|
||||
pika_plug_in_cleanup_layers_thaw (PikaPlugIn *plug_in,
|
||||
PikaImage *image)
|
||||
{
|
||||
PikaPlugInProcFrame *proc_frame;
|
||||
PikaPlugInCleanupImage *cleanup;
|
||||
|
||||
g_return_val_if_fail (PIKA_IS_PLUG_IN (plug_in), FALSE);
|
||||
g_return_val_if_fail (PIKA_IS_IMAGE (image), FALSE);
|
||||
|
||||
proc_frame = pika_plug_in_get_proc_frame (plug_in);
|
||||
cleanup = pika_plug_in_cleanup_image_get (proc_frame, image);
|
||||
|
||||
if (! cleanup)
|
||||
return FALSE;
|
||||
|
||||
if (cleanup->layers_freeze_count > 0)
|
||||
{
|
||||
cleanup->layers_freeze_count--;
|
||||
|
||||
if (pika_plug_in_cleanup_image_is_clean (cleanup))
|
||||
pika_plug_in_cleanup_image_free (proc_frame, cleanup);
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
gboolean
|
||||
pika_plug_in_cleanup_channels_freeze (PikaPlugIn *plug_in,
|
||||
PikaImage *image)
|
||||
{
|
||||
PikaPlugInProcFrame *proc_frame;
|
||||
PikaPlugInCleanupImage *cleanup;
|
||||
|
||||
g_return_val_if_fail (PIKA_IS_PLUG_IN (plug_in), FALSE);
|
||||
g_return_val_if_fail (PIKA_IS_IMAGE (image), FALSE);
|
||||
|
||||
proc_frame = pika_plug_in_get_proc_frame (plug_in);
|
||||
cleanup = pika_plug_in_cleanup_image_get (proc_frame, image);
|
||||
|
||||
if (! cleanup)
|
||||
cleanup = pika_plug_in_cleanup_image_new (proc_frame, image);
|
||||
|
||||
cleanup->channels_freeze_count++;
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
gboolean
|
||||
pika_plug_in_cleanup_channels_thaw (PikaPlugIn *plug_in,
|
||||
PikaImage *image)
|
||||
{
|
||||
PikaPlugInProcFrame *proc_frame;
|
||||
PikaPlugInCleanupImage *cleanup;
|
||||
|
||||
g_return_val_if_fail (PIKA_IS_PLUG_IN (plug_in), FALSE);
|
||||
g_return_val_if_fail (PIKA_IS_IMAGE (image), FALSE);
|
||||
|
||||
proc_frame = pika_plug_in_get_proc_frame (plug_in);
|
||||
cleanup = pika_plug_in_cleanup_image_get (proc_frame, image);
|
||||
|
||||
if (! cleanup)
|
||||
return FALSE;
|
||||
|
||||
if (cleanup->channels_freeze_count > 0)
|
||||
{
|
||||
cleanup->channels_freeze_count--;
|
||||
|
||||
if (pika_plug_in_cleanup_image_is_clean (cleanup))
|
||||
pika_plug_in_cleanup_image_free (proc_frame, cleanup);
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
gboolean
|
||||
pika_plug_in_cleanup_vectors_freeze (PikaPlugIn *plug_in,
|
||||
PikaImage *image)
|
||||
{
|
||||
PikaPlugInProcFrame *proc_frame;
|
||||
PikaPlugInCleanupImage *cleanup;
|
||||
|
||||
g_return_val_if_fail (PIKA_IS_PLUG_IN (plug_in), FALSE);
|
||||
g_return_val_if_fail (PIKA_IS_IMAGE (image), FALSE);
|
||||
|
||||
proc_frame = pika_plug_in_get_proc_frame (plug_in);
|
||||
cleanup = pika_plug_in_cleanup_image_get (proc_frame, image);
|
||||
|
||||
if (! cleanup)
|
||||
cleanup = pika_plug_in_cleanup_image_new (proc_frame, image);
|
||||
|
||||
cleanup->vectors_freeze_count++;
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
gboolean
|
||||
pika_plug_in_cleanup_vectors_thaw (PikaPlugIn *plug_in,
|
||||
PikaImage *image)
|
||||
{
|
||||
PikaPlugInProcFrame *proc_frame;
|
||||
PikaPlugInCleanupImage *cleanup;
|
||||
|
||||
g_return_val_if_fail (PIKA_IS_PLUG_IN (plug_in), FALSE);
|
||||
g_return_val_if_fail (PIKA_IS_IMAGE (image), FALSE);
|
||||
|
||||
proc_frame = pika_plug_in_get_proc_frame (plug_in);
|
||||
cleanup = pika_plug_in_cleanup_image_get (proc_frame, image);
|
||||
|
||||
if (! cleanup)
|
||||
return FALSE;
|
||||
|
||||
if (cleanup->vectors_freeze_count > 0)
|
||||
{
|
||||
cleanup->vectors_freeze_count--;
|
||||
|
||||
if (pika_plug_in_cleanup_image_is_clean (cleanup))
|
||||
pika_plug_in_cleanup_image_free (proc_frame, cleanup);
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
gboolean
|
||||
pika_plug_in_cleanup_add_shadow (PikaPlugIn *plug_in,
|
||||
PikaDrawable *drawable)
|
||||
{
|
||||
PikaPlugInProcFrame *proc_frame;
|
||||
PikaPlugInCleanupItem *cleanup;
|
||||
|
||||
g_return_val_if_fail (PIKA_IS_PLUG_IN (plug_in), FALSE);
|
||||
g_return_val_if_fail (PIKA_IS_DRAWABLE (drawable), FALSE);
|
||||
|
||||
proc_frame = pika_plug_in_get_proc_frame (plug_in);
|
||||
cleanup = pika_plug_in_cleanup_item_get (proc_frame, PIKA_ITEM (drawable));
|
||||
|
||||
if (! cleanup)
|
||||
cleanup = pika_plug_in_cleanup_item_new (proc_frame, PIKA_ITEM (drawable));
|
||||
|
||||
cleanup->shadow_buffer = TRUE;
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
gboolean
|
||||
pika_plug_in_cleanup_remove_shadow (PikaPlugIn *plug_in,
|
||||
PikaDrawable *drawable)
|
||||
{
|
||||
PikaPlugInProcFrame *proc_frame;
|
||||
PikaPlugInCleanupItem *cleanup;
|
||||
|
||||
g_return_val_if_fail (PIKA_IS_PLUG_IN (plug_in), FALSE);
|
||||
g_return_val_if_fail (PIKA_IS_DRAWABLE (drawable), FALSE);
|
||||
|
||||
proc_frame = pika_plug_in_get_proc_frame (plug_in);
|
||||
cleanup = pika_plug_in_cleanup_item_get (proc_frame, PIKA_ITEM (drawable));
|
||||
|
||||
if (! cleanup)
|
||||
return FALSE;
|
||||
|
||||
if (cleanup->shadow_buffer)
|
||||
{
|
||||
cleanup->shadow_buffer = FALSE;
|
||||
|
||||
if (pika_plug_in_cleanup_item_is_clean (cleanup))
|
||||
pika_plug_in_cleanup_item_free (proc_frame, cleanup);
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
void
|
||||
pika_plug_in_cleanup (PikaPlugIn *plug_in,
|
||||
PikaPlugInProcFrame *proc_frame)
|
||||
{
|
||||
g_return_if_fail (PIKA_IS_PLUG_IN (plug_in));
|
||||
g_return_if_fail (proc_frame != NULL);
|
||||
|
||||
while (proc_frame->image_cleanups)
|
||||
{
|
||||
PikaPlugInCleanupImage *cleanup = proc_frame->image_cleanups->data;
|
||||
|
||||
if (pika_image_get_by_id (plug_in->manager->pika,
|
||||
cleanup->image_id) == cleanup->image)
|
||||
{
|
||||
pika_plug_in_cleanup_image (proc_frame, cleanup);
|
||||
}
|
||||
|
||||
pika_plug_in_cleanup_image_free (proc_frame, cleanup);
|
||||
}
|
||||
|
||||
while (proc_frame->item_cleanups)
|
||||
{
|
||||
PikaPlugInCleanupItem *cleanup = proc_frame->item_cleanups->data;
|
||||
|
||||
if (pika_item_get_by_id (plug_in->manager->pika,
|
||||
cleanup->item_id) == cleanup->item)
|
||||
{
|
||||
pika_plug_in_cleanup_item (proc_frame, cleanup);
|
||||
}
|
||||
|
||||
pika_plug_in_cleanup_item_free (proc_frame, cleanup);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/* private functions */
|
||||
|
||||
static PikaPlugInCleanupImage *
|
||||
pika_plug_in_cleanup_image_new (PikaPlugInProcFrame *proc_frame,
|
||||
PikaImage *image)
|
||||
{
|
||||
PikaPlugInCleanupImage *cleanup = g_slice_new0 (PikaPlugInCleanupImage);
|
||||
|
||||
cleanup->image = image;
|
||||
cleanup->image_id = pika_image_get_id (image);
|
||||
|
||||
proc_frame->image_cleanups = g_list_prepend (proc_frame->image_cleanups,
|
||||
cleanup);
|
||||
|
||||
return cleanup;
|
||||
}
|
||||
|
||||
static void
|
||||
pika_plug_in_cleanup_image_free (PikaPlugInProcFrame *proc_frame,
|
||||
PikaPlugInCleanupImage *cleanup)
|
||||
{
|
||||
proc_frame->image_cleanups = g_list_remove (proc_frame->image_cleanups,
|
||||
cleanup);
|
||||
|
||||
g_slice_free (PikaPlugInCleanupImage, cleanup);
|
||||
}
|
||||
|
||||
static gboolean
|
||||
pika_plug_in_cleanup_image_is_clean (PikaPlugInCleanupImage *cleanup)
|
||||
{
|
||||
if (cleanup->undo_group_count > 0)
|
||||
return FALSE;
|
||||
|
||||
if (cleanup->layers_freeze_count > 0)
|
||||
return FALSE;
|
||||
|
||||
if (cleanup->channels_freeze_count > 0)
|
||||
return FALSE;
|
||||
|
||||
if (cleanup->vectors_freeze_count > 0)
|
||||
return FALSE;
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static PikaPlugInCleanupImage *
|
||||
pika_plug_in_cleanup_image_get (PikaPlugInProcFrame *proc_frame,
|
||||
PikaImage *image)
|
||||
{
|
||||
GList *list;
|
||||
|
||||
for (list = proc_frame->image_cleanups; list; list = g_list_next (list))
|
||||
{
|
||||
PikaPlugInCleanupImage *cleanup = list->data;
|
||||
|
||||
if (cleanup->image == image)
|
||||
return cleanup;
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static void
|
||||
pika_plug_in_cleanup_image (PikaPlugInProcFrame *proc_frame,
|
||||
PikaPlugInCleanupImage *cleanup)
|
||||
{
|
||||
PikaImage *image = cleanup->image;
|
||||
PikaContainer *container;
|
||||
|
||||
if (cleanup->undo_group_count > 0)
|
||||
{
|
||||
g_message ("Plug-in '%s' left image undo in inconsistent state, "
|
||||
"closing open undo groups.",
|
||||
pika_procedure_get_label (proc_frame->procedure));
|
||||
|
||||
while (cleanup->undo_group_count--)
|
||||
if (! pika_image_undo_group_end (image))
|
||||
break;
|
||||
}
|
||||
|
||||
container = pika_image_get_layers (image);
|
||||
|
||||
if (cleanup->layers_freeze_count > 0)
|
||||
{
|
||||
g_message ("Plug-in '%s' left image's layers frozen, "
|
||||
"thawing layers.",
|
||||
pika_procedure_get_label (proc_frame->procedure));
|
||||
|
||||
while (cleanup->layers_freeze_count-- > 0 &&
|
||||
pika_container_frozen (container))
|
||||
{
|
||||
pika_container_thaw (container);
|
||||
}
|
||||
}
|
||||
|
||||
container = pika_image_get_channels (image);
|
||||
|
||||
if (cleanup->channels_freeze_count > 0)
|
||||
{
|
||||
g_message ("Plug-in '%s' left image's channels frozen, "
|
||||
"thawing channels.",
|
||||
pika_procedure_get_label (proc_frame->procedure));
|
||||
|
||||
while (cleanup->channels_freeze_count-- > 0 &&
|
||||
pika_container_frozen (container))
|
||||
{
|
||||
pika_container_thaw (container);
|
||||
}
|
||||
}
|
||||
|
||||
container = pika_image_get_vectors (image);
|
||||
|
||||
if (cleanup->vectors_freeze_count > 0)
|
||||
{
|
||||
g_message ("Plug-in '%s' left image's vectors frozen, "
|
||||
"thawing vectors.",
|
||||
pika_procedure_get_label (proc_frame->procedure));
|
||||
|
||||
while (cleanup->vectors_freeze_count > 0 &&
|
||||
pika_container_frozen (container))
|
||||
{
|
||||
pika_container_thaw (container);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static PikaPlugInCleanupItem *
|
||||
pika_plug_in_cleanup_item_new (PikaPlugInProcFrame *proc_frame,
|
||||
PikaItem *item)
|
||||
{
|
||||
PikaPlugInCleanupItem *cleanup = g_slice_new0 (PikaPlugInCleanupItem);
|
||||
|
||||
cleanup->item = item;
|
||||
cleanup->item_id = pika_item_get_id (item);
|
||||
|
||||
proc_frame->item_cleanups = g_list_prepend (proc_frame->item_cleanups,
|
||||
cleanup);
|
||||
|
||||
return cleanup;
|
||||
}
|
||||
|
||||
static void
|
||||
pika_plug_in_cleanup_item_free (PikaPlugInProcFrame *proc_frame,
|
||||
PikaPlugInCleanupItem *cleanup)
|
||||
{
|
||||
proc_frame->item_cleanups = g_list_remove (proc_frame->item_cleanups,
|
||||
cleanup);
|
||||
|
||||
g_slice_free (PikaPlugInCleanupItem, cleanup);
|
||||
}
|
||||
|
||||
static gboolean
|
||||
pika_plug_in_cleanup_item_is_clean (PikaPlugInCleanupItem *cleanup)
|
||||
{
|
||||
if (cleanup->shadow_buffer)
|
||||
return FALSE;
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static PikaPlugInCleanupItem *
|
||||
pika_plug_in_cleanup_item_get (PikaPlugInProcFrame *proc_frame,
|
||||
PikaItem *item)
|
||||
{
|
||||
GList *list;
|
||||
|
||||
for (list = proc_frame->item_cleanups; list; list = g_list_next (list))
|
||||
{
|
||||
PikaPlugInCleanupItem *cleanup = list->data;
|
||||
|
||||
if (cleanup->item == item)
|
||||
return cleanup;
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static void
|
||||
pika_plug_in_cleanup_item (PikaPlugInProcFrame *proc_frame,
|
||||
PikaPlugInCleanupItem *cleanup)
|
||||
{
|
||||
PikaItem *item = cleanup->item;
|
||||
|
||||
if (cleanup->shadow_buffer)
|
||||
{
|
||||
PIKA_LOG (SHADOW_TILES,
|
||||
"Freeing shadow buffer of drawable '%s' on behalf of '%s'.",
|
||||
pika_object_get_name (item),
|
||||
pika_procedure_get_label (proc_frame->procedure));
|
||||
|
||||
pika_drawable_free_shadow_buffer (PIKA_DRAWABLE (item));
|
||||
|
||||
cleanup->shadow_buffer = FALSE;
|
||||
}
|
||||
}
|
57
app/plug-in/pikaplugin-cleanup.h
Normal file
57
app/plug-in/pikaplugin-cleanup.h
Normal file
@ -0,0 +1,57 @@
|
||||
/* PIKA - Photo and Image Kooker Application
|
||||
* a rebranding of The GNU Image Manipulation Program (created with heckimp)
|
||||
* A derived work which may be trivial. However, any changes may be (C)2023 by Aldercone Studio
|
||||
*
|
||||
* Original copyright, applying to most contents (license remains unchanged):
|
||||
* Copyright (C) 1995 Spencer Kimball and Peter Mattis
|
||||
*
|
||||
* pikaplugin-cleanup.h
|
||||
*
|
||||
* 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 3 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, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#ifndef __PIKA_PLUG_IN_CLEANUP_H__
|
||||
#define __PIKA_PLUG_IN_CLEANUP_H__
|
||||
|
||||
|
||||
gboolean pika_plug_in_cleanup_undo_group_start (PikaPlugIn *plug_in,
|
||||
PikaImage *image);
|
||||
gboolean pika_plug_in_cleanup_undo_group_end (PikaPlugIn *plug_in,
|
||||
PikaImage *image);
|
||||
|
||||
gboolean pika_plug_in_cleanup_layers_freeze (PikaPlugIn *plug_in,
|
||||
PikaImage *image);
|
||||
gboolean pika_plug_in_cleanup_layers_thaw (PikaPlugIn *plug_in,
|
||||
PikaImage *image);
|
||||
|
||||
gboolean pika_plug_in_cleanup_channels_freeze (PikaPlugIn *plug_in,
|
||||
PikaImage *image);
|
||||
gboolean pika_plug_in_cleanup_channels_thaw (PikaPlugIn *plug_in,
|
||||
PikaImage *image);
|
||||
|
||||
gboolean pika_plug_in_cleanup_vectors_freeze (PikaPlugIn *plug_in,
|
||||
PikaImage *image);
|
||||
gboolean pika_plug_in_cleanup_vectors_thaw (PikaPlugIn *plug_in,
|
||||
PikaImage *image);
|
||||
|
||||
gboolean pika_plug_in_cleanup_add_shadow (PikaPlugIn *plug_in,
|
||||
PikaDrawable *drawable);
|
||||
gboolean pika_plug_in_cleanup_remove_shadow (PikaPlugIn *plug_in,
|
||||
PikaDrawable *drawable);
|
||||
|
||||
void pika_plug_in_cleanup (PikaPlugIn *plug_in,
|
||||
PikaPlugInProcFrame *proc_frame);
|
||||
|
||||
|
||||
#endif /* __PIKA_PLUG_IN_CLEANUP_H__ */
|
85
app/plug-in/pikaplugin-context.c
Normal file
85
app/plug-in/pikaplugin-context.c
Normal file
@ -0,0 +1,85 @@
|
||||
/* PIKA - Photo and Image Kooker Application
|
||||
* a rebranding of The GNU Image Manipulation Program (created with heckimp)
|
||||
* A derived work which may be trivial. However, any changes may be (C)2023 by Aldercone Studio
|
||||
*
|
||||
* Original copyright, applying to most contents (license remains unchanged):
|
||||
* Copyright (C) 1995 Spencer Kimball and Peter Mattis
|
||||
*
|
||||
* pikaplugin-context.c
|
||||
*
|
||||
* 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 3 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, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include "config.h"
|
||||
|
||||
#include <gdk-pixbuf/gdk-pixbuf.h>
|
||||
#include <gegl.h>
|
||||
|
||||
#include "plug-in-types.h"
|
||||
|
||||
#include "core/pika.h"
|
||||
|
||||
#include "pdb/pikapdbcontext.h"
|
||||
|
||||
#include "pikaplugin.h"
|
||||
#include "pikaplugin-context.h"
|
||||
#include "pikapluginmanager.h"
|
||||
|
||||
|
||||
gboolean
|
||||
pika_plug_in_context_push (PikaPlugIn *plug_in)
|
||||
{
|
||||
PikaPlugInProcFrame *proc_frame;
|
||||
PikaContext *parent;
|
||||
PikaContext *context;
|
||||
|
||||
g_return_val_if_fail (PIKA_IS_PLUG_IN (plug_in), FALSE);
|
||||
|
||||
proc_frame = pika_plug_in_get_proc_frame (plug_in);
|
||||
|
||||
if (proc_frame->context_stack)
|
||||
parent = proc_frame->context_stack->data;
|
||||
else
|
||||
parent = proc_frame->main_context;
|
||||
|
||||
context = pika_pdb_context_new (plug_in->manager->pika, parent, FALSE);
|
||||
|
||||
proc_frame->context_stack = g_list_prepend (proc_frame->context_stack,
|
||||
context);
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
gboolean
|
||||
pika_plug_in_context_pop (PikaPlugIn *plug_in)
|
||||
{
|
||||
PikaPlugInProcFrame *proc_frame;
|
||||
|
||||
g_return_val_if_fail (PIKA_IS_PLUG_IN (plug_in), FALSE);
|
||||
|
||||
proc_frame = pika_plug_in_get_proc_frame (plug_in);
|
||||
|
||||
if (proc_frame->context_stack)
|
||||
{
|
||||
PikaContext *context = proc_frame->context_stack->data;
|
||||
|
||||
proc_frame->context_stack = g_list_remove (proc_frame->context_stack,
|
||||
context);
|
||||
g_object_unref (context);
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
return FALSE;
|
||||
}
|
32
app/plug-in/pikaplugin-context.h
Normal file
32
app/plug-in/pikaplugin-context.h
Normal file
@ -0,0 +1,32 @@
|
||||
/* PIKA - Photo and Image Kooker Application
|
||||
* a rebranding of The GNU Image Manipulation Program (created with heckimp)
|
||||
* A derived work which may be trivial. However, any changes may be (C)2023 by Aldercone Studio
|
||||
*
|
||||
* Original copyright, applying to most contents (license remains unchanged):
|
||||
* Copyright (C) 1995 Spencer Kimball and Peter Mattis
|
||||
*
|
||||
* pikaplugin-context.h
|
||||
*
|
||||
* 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 3 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, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#ifndef __PIKA_PLUG_IN_CONTEXT_H__
|
||||
#define __PIKA_PLUG_IN_CONTEXT_H__
|
||||
|
||||
|
||||
gboolean pika_plug_in_context_push (PikaPlugIn *plug_in);
|
||||
gboolean pika_plug_in_context_pop (PikaPlugIn *plug_in);
|
||||
|
||||
|
||||
#endif /* __PIKA_PLUG_IN_CONTEXT_H__ */
|
933
app/plug-in/pikaplugin-message.c
Normal file
933
app/plug-in/pikaplugin-message.c
Normal file
@ -0,0 +1,933 @@
|
||||
/* PIKA - Photo and Image Kooker Application
|
||||
* a rebranding of The GNU Image Manipulation Program (created with heckimp)
|
||||
* A derived work which may be trivial. However, any changes may be (C)2023 by Aldercone Studio
|
||||
*
|
||||
* Original copyright, applying to most contents (license remains unchanged):
|
||||
* Copyright (C) 1995 Spencer Kimball and Peter Mattis
|
||||
*
|
||||
* pikaplugin-message.c
|
||||
*
|
||||
* 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 3 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, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include "config.h"
|
||||
|
||||
#include <string.h>
|
||||
|
||||
#include <gdk-pixbuf/gdk-pixbuf.h>
|
||||
#include <gegl.h>
|
||||
|
||||
#include "libpikabase/pikabase.h"
|
||||
#include "libpikabase/pikaprotocol.h"
|
||||
#include "libpikabase/pikawire.h"
|
||||
|
||||
#include "libpika/pikagpparams.h"
|
||||
|
||||
#include "plug-in-types.h"
|
||||
|
||||
#include "gegl/pika-babl.h"
|
||||
#include "gegl/pika-gegl-tile-compat.h"
|
||||
|
||||
#include "core/pika.h"
|
||||
#include "core/pikadrawable.h"
|
||||
#include "core/pikadrawable-shadow.h"
|
||||
|
||||
#include "pdb/pika-pdb-compat.h"
|
||||
#include "pdb/pikapdb.h"
|
||||
#include "pdb/pikapdberror.h"
|
||||
|
||||
#include "pikaplugin.h"
|
||||
#include "pikaplugin-cleanup.h"
|
||||
#include "pikaplugin-message.h"
|
||||
#include "pikapluginmanager.h"
|
||||
#include "pikaplugindef.h"
|
||||
#include "pikapluginshm.h"
|
||||
#include "pikatemporaryprocedure.h"
|
||||
|
||||
#include "pika-intl.h"
|
||||
|
||||
|
||||
/* local function prototypes */
|
||||
|
||||
static void pika_plug_in_handle_quit (PikaPlugIn *plug_in);
|
||||
static void pika_plug_in_handle_tile_request (PikaPlugIn *plug_in,
|
||||
GPTileReq *request);
|
||||
static void pika_plug_in_handle_tile_put (PikaPlugIn *plug_in,
|
||||
GPTileReq *request);
|
||||
static void pika_plug_in_handle_tile_get (PikaPlugIn *plug_in,
|
||||
GPTileReq *request);
|
||||
static void pika_plug_in_handle_proc_run (PikaPlugIn *plug_in,
|
||||
GPProcRun *proc_run);
|
||||
static void pika_plug_in_handle_proc_return (PikaPlugIn *plug_in,
|
||||
GPProcReturn *proc_return);
|
||||
static void pika_plug_in_handle_temp_proc_return (PikaPlugIn *plug_in,
|
||||
GPProcReturn *proc_return);
|
||||
static void pika_plug_in_handle_proc_install (PikaPlugIn *plug_in,
|
||||
GPProcInstall *proc_install);
|
||||
static void pika_plug_in_handle_proc_uninstall (PikaPlugIn *plug_in,
|
||||
GPProcUninstall *proc_uninstall);
|
||||
static void pika_plug_in_handle_extension_ack (PikaPlugIn *plug_in);
|
||||
static void pika_plug_in_handle_has_init (PikaPlugIn *plug_in);
|
||||
|
||||
|
||||
/* public functions */
|
||||
|
||||
void
|
||||
pika_plug_in_handle_message (PikaPlugIn *plug_in,
|
||||
PikaWireMessage *msg)
|
||||
{
|
||||
g_return_if_fail (PIKA_IS_PLUG_IN (plug_in));
|
||||
g_return_if_fail (plug_in->open == TRUE);
|
||||
g_return_if_fail (msg != NULL);
|
||||
|
||||
switch (msg->type)
|
||||
{
|
||||
case GP_QUIT:
|
||||
pika_plug_in_handle_quit (plug_in);
|
||||
break;
|
||||
|
||||
case GP_CONFIG:
|
||||
pika_message (plug_in->manager->pika, NULL, PIKA_MESSAGE_ERROR,
|
||||
"Plug-in \"%s\"\n(%s)\n\n"
|
||||
"sent a CONFIG message. This should not happen.",
|
||||
pika_object_get_name (plug_in),
|
||||
pika_file_get_utf8_name (plug_in->file));
|
||||
pika_plug_in_close (plug_in, TRUE);
|
||||
break;
|
||||
|
||||
case GP_TILE_REQ:
|
||||
pika_plug_in_handle_tile_request (plug_in, msg->data);
|
||||
break;
|
||||
|
||||
case GP_TILE_ACK:
|
||||
pika_message (plug_in->manager->pika, NULL, PIKA_MESSAGE_ERROR,
|
||||
"Plug-in \"%s\"\n(%s)\n\n"
|
||||
"sent a TILE_ACK message. This should not happen.",
|
||||
pika_object_get_name (plug_in),
|
||||
pika_file_get_utf8_name (plug_in->file));
|
||||
pika_plug_in_close (plug_in, TRUE);
|
||||
break;
|
||||
|
||||
case GP_TILE_DATA:
|
||||
pika_message (plug_in->manager->pika, NULL, PIKA_MESSAGE_ERROR,
|
||||
"Plug-in \"%s\"\n(%s)\n\n"
|
||||
"sent a TILE_DATA message. This should not happen.",
|
||||
pika_object_get_name (plug_in),
|
||||
pika_file_get_utf8_name (plug_in->file));
|
||||
pika_plug_in_close (plug_in, TRUE);
|
||||
break;
|
||||
|
||||
case GP_PROC_RUN:
|
||||
pika_plug_in_handle_proc_run (plug_in, msg->data);
|
||||
break;
|
||||
|
||||
case GP_PROC_RETURN:
|
||||
pika_plug_in_handle_proc_return (plug_in, msg->data);
|
||||
break;
|
||||
|
||||
case GP_TEMP_PROC_RUN:
|
||||
pika_message (plug_in->manager->pika, NULL, PIKA_MESSAGE_ERROR,
|
||||
"Plug-in \"%s\"\n(%s)\n\n"
|
||||
"sent a TEMP_PROC_RUN message. This should not happen.",
|
||||
pika_object_get_name (plug_in),
|
||||
pika_file_get_utf8_name (plug_in->file));
|
||||
pika_plug_in_close (plug_in, TRUE);
|
||||
break;
|
||||
|
||||
case GP_TEMP_PROC_RETURN:
|
||||
pika_plug_in_handle_temp_proc_return (plug_in, msg->data);
|
||||
break;
|
||||
|
||||
case GP_PROC_INSTALL:
|
||||
pika_plug_in_handle_proc_install (plug_in, msg->data);
|
||||
break;
|
||||
|
||||
case GP_PROC_UNINSTALL:
|
||||
pika_plug_in_handle_proc_uninstall (plug_in, msg->data);
|
||||
break;
|
||||
|
||||
case GP_EXTENSION_ACK:
|
||||
pika_plug_in_handle_extension_ack (plug_in);
|
||||
break;
|
||||
|
||||
case GP_HAS_INIT:
|
||||
pika_plug_in_handle_has_init (plug_in);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/* private functions */
|
||||
|
||||
static void
|
||||
pika_plug_in_handle_quit (PikaPlugIn *plug_in)
|
||||
{
|
||||
pika_plug_in_close (plug_in, FALSE);
|
||||
}
|
||||
|
||||
static void
|
||||
pika_plug_in_handle_tile_request (PikaPlugIn *plug_in,
|
||||
GPTileReq *request)
|
||||
{
|
||||
g_return_if_fail (request != NULL);
|
||||
|
||||
if (request->drawable_id == -1)
|
||||
pika_plug_in_handle_tile_put (plug_in, request);
|
||||
else
|
||||
pika_plug_in_handle_tile_get (plug_in, request);
|
||||
}
|
||||
|
||||
static void
|
||||
pika_plug_in_handle_tile_put (PikaPlugIn *plug_in,
|
||||
GPTileReq *request)
|
||||
{
|
||||
GPTileData tile_data;
|
||||
GPTileData *tile_info;
|
||||
PikaWireMessage msg;
|
||||
PikaDrawable *drawable;
|
||||
GeglBuffer *buffer;
|
||||
const Babl *format;
|
||||
GeglRectangle tile_rect;
|
||||
|
||||
tile_data.drawable_id = -1;
|
||||
tile_data.tile_num = 0;
|
||||
tile_data.shadow = 0;
|
||||
tile_data.bpp = 0;
|
||||
tile_data.width = 0;
|
||||
tile_data.height = 0;
|
||||
tile_data.use_shm = (plug_in->manager->shm != NULL);
|
||||
tile_data.data = NULL;
|
||||
|
||||
if (! gp_tile_data_write (plug_in->my_write, &tile_data, plug_in))
|
||||
{
|
||||
pika_message (plug_in->manager->pika, NULL, PIKA_MESSAGE_ERROR,
|
||||
"%s: ERROR", G_STRFUNC);
|
||||
pika_plug_in_close (plug_in, TRUE);
|
||||
return;
|
||||
}
|
||||
|
||||
if (! pika_wire_read_msg (plug_in->my_read, &msg, plug_in))
|
||||
{
|
||||
pika_message (plug_in->manager->pika, NULL, PIKA_MESSAGE_ERROR,
|
||||
"%s: ERROR", G_STRFUNC);
|
||||
pika_plug_in_close (plug_in, TRUE);
|
||||
return;
|
||||
}
|
||||
|
||||
if (msg.type != GP_TILE_DATA)
|
||||
{
|
||||
pika_message (plug_in->manager->pika, NULL, PIKA_MESSAGE_ERROR,
|
||||
"expected tile data and received: %d", msg.type);
|
||||
pika_plug_in_close (plug_in, TRUE);
|
||||
return;
|
||||
}
|
||||
|
||||
tile_info = msg.data;
|
||||
|
||||
drawable = (PikaDrawable *) pika_item_get_by_id (plug_in->manager->pika,
|
||||
tile_info->drawable_id);
|
||||
|
||||
if (! PIKA_IS_DRAWABLE (drawable))
|
||||
{
|
||||
pika_message (plug_in->manager->pika, NULL, PIKA_MESSAGE_ERROR,
|
||||
"Plug-in \"%s\"\n(%s)\n\n"
|
||||
"tried writing to invalid drawable %d (killing)",
|
||||
pika_object_get_name (plug_in),
|
||||
pika_file_get_utf8_name (plug_in->file),
|
||||
tile_info->drawable_id);
|
||||
pika_plug_in_close (plug_in, TRUE);
|
||||
return;
|
||||
}
|
||||
else if (pika_item_is_removed (PIKA_ITEM (drawable)))
|
||||
{
|
||||
pika_message (plug_in->manager->pika, NULL, PIKA_MESSAGE_ERROR,
|
||||
"Plug-in \"%s\"\n(%s)\n\n"
|
||||
"tried writing to drawable %d which was removed "
|
||||
"from the image (killing)",
|
||||
pika_object_get_name (plug_in),
|
||||
pika_file_get_utf8_name (plug_in->file),
|
||||
tile_info->drawable_id);
|
||||
pika_plug_in_close (plug_in, TRUE);
|
||||
return;
|
||||
}
|
||||
|
||||
if (tile_info->shadow)
|
||||
{
|
||||
|
||||
/* don't check whether the drawable is a group or locked here,
|
||||
* the plugin will get a proper error message when it tries to
|
||||
* merge the shadow tiles, which is much better than just
|
||||
* killing it.
|
||||
*/
|
||||
buffer = pika_drawable_get_shadow_buffer (drawable);
|
||||
|
||||
pika_plug_in_cleanup_add_shadow (plug_in, drawable);
|
||||
}
|
||||
else
|
||||
{
|
||||
if (pika_item_is_content_locked (PIKA_ITEM (drawable), NULL))
|
||||
{
|
||||
pika_message (plug_in->manager->pika, NULL, PIKA_MESSAGE_ERROR,
|
||||
"Plug-in \"%s\"\n(%s)\n\n"
|
||||
"tried writing to a locked drawable %d (killing)",
|
||||
pika_object_get_name (plug_in),
|
||||
pika_file_get_utf8_name (plug_in->file),
|
||||
tile_info->drawable_id);
|
||||
pika_plug_in_close (plug_in, TRUE);
|
||||
return;
|
||||
}
|
||||
else if (pika_viewable_get_children (PIKA_VIEWABLE (drawable)))
|
||||
{
|
||||
pika_message (plug_in->manager->pika, NULL, PIKA_MESSAGE_ERROR,
|
||||
"Plug-in \"%s\"\n(%s)\n\n"
|
||||
"tried writing to a group layer %d (killing)",
|
||||
pika_object_get_name (plug_in),
|
||||
pika_file_get_utf8_name (plug_in->file),
|
||||
tile_info->drawable_id);
|
||||
pika_plug_in_close (plug_in, TRUE);
|
||||
return;
|
||||
}
|
||||
|
||||
buffer = pika_drawable_get_buffer (drawable);
|
||||
}
|
||||
|
||||
if (! pika_gegl_buffer_get_tile_rect (buffer,
|
||||
PIKA_PLUG_IN_TILE_WIDTH,
|
||||
PIKA_PLUG_IN_TILE_HEIGHT,
|
||||
tile_info->tile_num,
|
||||
&tile_rect))
|
||||
{
|
||||
pika_message (plug_in->manager->pika, NULL, PIKA_MESSAGE_ERROR,
|
||||
"Plug-in \"%s\"\n(%s)\n\n"
|
||||
"requested invalid tile #%d for writing (killing)",
|
||||
pika_object_get_name (plug_in),
|
||||
pika_file_get_utf8_name (plug_in->file),
|
||||
tile_info->tile_num);
|
||||
pika_plug_in_close (plug_in, TRUE);
|
||||
return;
|
||||
}
|
||||
|
||||
format = gegl_buffer_get_format (buffer);
|
||||
|
||||
if (tile_data.use_shm)
|
||||
{
|
||||
gegl_buffer_set (buffer, &tile_rect, 0, format,
|
||||
pika_plug_in_shm_get_addr (plug_in->manager->shm),
|
||||
GEGL_AUTO_ROWSTRIDE);
|
||||
}
|
||||
else
|
||||
{
|
||||
gegl_buffer_set (buffer, &tile_rect, 0, format,
|
||||
tile_info->data,
|
||||
GEGL_AUTO_ROWSTRIDE);
|
||||
}
|
||||
|
||||
pika_wire_destroy (&msg);
|
||||
|
||||
if (! gp_tile_ack_write (plug_in->my_write, plug_in))
|
||||
{
|
||||
pika_message (plug_in->manager->pika, NULL, PIKA_MESSAGE_ERROR,
|
||||
"%s: ERROR", G_STRFUNC);
|
||||
pika_plug_in_close (plug_in, TRUE);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
pika_plug_in_handle_tile_get (PikaPlugIn *plug_in,
|
||||
GPTileReq *request)
|
||||
{
|
||||
GPTileData tile_data;
|
||||
PikaWireMessage msg;
|
||||
PikaDrawable *drawable;
|
||||
GeglBuffer *buffer;
|
||||
const Babl *format;
|
||||
GeglRectangle tile_rect;
|
||||
gint tile_size;
|
||||
|
||||
drawable = (PikaDrawable *) pika_item_get_by_id (plug_in->manager->pika,
|
||||
request->drawable_id);
|
||||
|
||||
if (! PIKA_IS_DRAWABLE (drawable))
|
||||
{
|
||||
pika_message (plug_in->manager->pika, NULL, PIKA_MESSAGE_ERROR,
|
||||
"Plug-in \"%s\"\n(%s)\n\n"
|
||||
"tried reading from invalid drawable %d (killing)",
|
||||
pika_object_get_name (plug_in),
|
||||
pika_file_get_utf8_name (plug_in->file),
|
||||
request->drawable_id);
|
||||
pika_plug_in_close (plug_in, TRUE);
|
||||
return;
|
||||
}
|
||||
else if (pika_item_is_removed (PIKA_ITEM (drawable)))
|
||||
{
|
||||
pika_message (plug_in->manager->pika, NULL, PIKA_MESSAGE_ERROR,
|
||||
"Plug-in \"%s\"\n(%s)\n\n"
|
||||
"tried reading from drawable %d which was removed "
|
||||
"from the image (killing)",
|
||||
pika_object_get_name (plug_in),
|
||||
pika_file_get_utf8_name (plug_in->file),
|
||||
request->drawable_id);
|
||||
pika_plug_in_close (plug_in, TRUE);
|
||||
return;
|
||||
}
|
||||
|
||||
if (request->shadow)
|
||||
{
|
||||
buffer = pika_drawable_get_shadow_buffer (drawable);
|
||||
|
||||
pika_plug_in_cleanup_add_shadow (plug_in, drawable);
|
||||
}
|
||||
else
|
||||
{
|
||||
buffer = pika_drawable_get_buffer (drawable);
|
||||
}
|
||||
|
||||
if (! pika_gegl_buffer_get_tile_rect (buffer,
|
||||
PIKA_PLUG_IN_TILE_WIDTH,
|
||||
PIKA_PLUG_IN_TILE_HEIGHT,
|
||||
request->tile_num,
|
||||
&tile_rect))
|
||||
{
|
||||
pika_message (plug_in->manager->pika, NULL, PIKA_MESSAGE_ERROR,
|
||||
"Plug-in \"%s\"\n(%s)\n\n"
|
||||
"requested invalid tile #%d for reading (killing)",
|
||||
pika_object_get_name (plug_in),
|
||||
pika_file_get_utf8_name (plug_in->file),
|
||||
request->tile_num);
|
||||
pika_plug_in_close (plug_in, TRUE);
|
||||
return;
|
||||
}
|
||||
|
||||
format = gegl_buffer_get_format (buffer);
|
||||
|
||||
tile_size = (babl_format_get_bytes_per_pixel (format) *
|
||||
tile_rect.width * tile_rect.height);
|
||||
|
||||
tile_data.drawable_id = request->drawable_id;
|
||||
tile_data.tile_num = request->tile_num;
|
||||
tile_data.shadow = request->shadow;
|
||||
tile_data.bpp = babl_format_get_bytes_per_pixel (format);
|
||||
tile_data.width = tile_rect.width;
|
||||
tile_data.height = tile_rect.height;
|
||||
tile_data.use_shm = (plug_in->manager->shm != NULL);
|
||||
|
||||
if (tile_data.use_shm)
|
||||
{
|
||||
gegl_buffer_get (buffer, &tile_rect, 1.0, format,
|
||||
pika_plug_in_shm_get_addr (plug_in->manager->shm),
|
||||
GEGL_AUTO_ROWSTRIDE, GEGL_ABYSS_NONE);
|
||||
}
|
||||
else
|
||||
{
|
||||
tile_data.data = g_malloc (tile_size);
|
||||
|
||||
gegl_buffer_get (buffer, &tile_rect, 1.0, format,
|
||||
tile_data.data,
|
||||
GEGL_AUTO_ROWSTRIDE, GEGL_ABYSS_NONE);
|
||||
}
|
||||
|
||||
if (! gp_tile_data_write (plug_in->my_write, &tile_data, plug_in))
|
||||
{
|
||||
pika_message (plug_in->manager->pika, NULL, PIKA_MESSAGE_ERROR,
|
||||
"%s: ERROR", G_STRFUNC);
|
||||
pika_plug_in_close (plug_in, TRUE);
|
||||
return;
|
||||
}
|
||||
|
||||
if (! pika_wire_read_msg (plug_in->my_read, &msg, plug_in))
|
||||
{
|
||||
pika_message (plug_in->manager->pika, NULL, PIKA_MESSAGE_ERROR,
|
||||
"%s: ERROR", G_STRFUNC);
|
||||
pika_plug_in_close (plug_in, TRUE);
|
||||
return;
|
||||
}
|
||||
|
||||
if (msg.type != GP_TILE_ACK)
|
||||
{
|
||||
pika_message (plug_in->manager->pika, NULL, PIKA_MESSAGE_ERROR,
|
||||
"expected tile ack and received: %d", msg.type);
|
||||
pika_plug_in_close (plug_in, TRUE);
|
||||
return;
|
||||
}
|
||||
|
||||
pika_wire_destroy (&msg);
|
||||
}
|
||||
|
||||
static void
|
||||
pika_plug_in_handle_proc_error (PikaPlugIn *plug_in,
|
||||
PikaPlugInProcFrame *proc_frame,
|
||||
const gchar *name,
|
||||
const GError *error)
|
||||
{
|
||||
switch (proc_frame->error_handler)
|
||||
{
|
||||
case PIKA_PDB_ERROR_HANDLER_INTERNAL:
|
||||
if (error->domain == PIKA_PDB_ERROR)
|
||||
{
|
||||
pika_message (plug_in->manager->pika,
|
||||
G_OBJECT (proc_frame->progress),
|
||||
PIKA_MESSAGE_ERROR,
|
||||
_("Calling error for procedure '%s':\n"
|
||||
"%s"),
|
||||
name, error->message);
|
||||
}
|
||||
else
|
||||
{
|
||||
pika_message (plug_in->manager->pika,
|
||||
G_OBJECT (proc_frame->progress),
|
||||
PIKA_MESSAGE_ERROR,
|
||||
_("Execution error for procedure '%s':\n"
|
||||
"%s"),
|
||||
name, error->message);
|
||||
}
|
||||
break;
|
||||
|
||||
case PIKA_PDB_ERROR_HANDLER_PLUGIN:
|
||||
/* the plug-in is responsible for handling this error */
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
pika_plug_in_handle_proc_run (PikaPlugIn *plug_in,
|
||||
GPProcRun *proc_run)
|
||||
{
|
||||
PikaPlugInProcFrame *proc_frame;
|
||||
gchar *canonical;
|
||||
const gchar *proc_name = NULL;
|
||||
PikaProcedure *procedure;
|
||||
PikaValueArray *args = NULL;
|
||||
PikaValueArray *return_vals = NULL;
|
||||
GError *error = NULL;
|
||||
|
||||
g_return_if_fail (proc_run != NULL);
|
||||
g_return_if_fail (proc_run->name != NULL);
|
||||
|
||||
canonical = pika_canonicalize_identifier (proc_run->name);
|
||||
|
||||
proc_frame = pika_plug_in_get_proc_frame (plug_in);
|
||||
|
||||
procedure = pika_pdb_lookup_procedure (plug_in->manager->pika->pdb,
|
||||
canonical);
|
||||
|
||||
if (! procedure)
|
||||
{
|
||||
proc_name = pika_pdb_lookup_compat_proc_name (plug_in->manager->pika->pdb,
|
||||
canonical);
|
||||
|
||||
if (proc_name)
|
||||
{
|
||||
procedure = pika_pdb_lookup_procedure (plug_in->manager->pika->pdb,
|
||||
proc_name);
|
||||
|
||||
if (plug_in->manager->pika->pdb_compat_mode == PIKA_PDB_COMPAT_WARN)
|
||||
{
|
||||
pika_message (plug_in->manager->pika, NULL, PIKA_MESSAGE_WARNING,
|
||||
"Plug-in \"%s\"\n(%s)\n"
|
||||
"called deprecated procedure '%s'.\n"
|
||||
"It should call '%s' instead!",
|
||||
pika_object_get_name (plug_in),
|
||||
pika_file_get_utf8_name (plug_in->file),
|
||||
canonical, proc_name);
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (procedure->deprecated)
|
||||
{
|
||||
if (plug_in->manager->pika->pdb_compat_mode == PIKA_PDB_COMPAT_WARN)
|
||||
{
|
||||
if (! strcmp (procedure->deprecated, "NONE"))
|
||||
{
|
||||
pika_message (plug_in->manager->pika, NULL, PIKA_MESSAGE_WARNING,
|
||||
"Plug-in \"%s\"\n(%s)\n"
|
||||
"called deprecated procedure '%s'.",
|
||||
pika_object_get_name (plug_in),
|
||||
pika_file_get_utf8_name (plug_in->file),
|
||||
canonical);
|
||||
}
|
||||
else
|
||||
{
|
||||
pika_message (plug_in->manager->pika, NULL, PIKA_MESSAGE_WARNING,
|
||||
"WARNING: Plug-in \"%s\"\n(%s)\n"
|
||||
"called deprecated procedure '%s'.\n"
|
||||
"It should call '%s' instead!",
|
||||
pika_object_get_name (plug_in),
|
||||
pika_file_get_utf8_name (plug_in->file),
|
||||
canonical, procedure->deprecated);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (! proc_name)
|
||||
proc_name = canonical;
|
||||
|
||||
args = _pika_gp_params_to_value_array (plug_in->manager->pika,
|
||||
procedure ? procedure->args : NULL,
|
||||
procedure ? procedure->num_args : 0,
|
||||
proc_run->params,
|
||||
proc_run->n_params,
|
||||
FALSE);
|
||||
|
||||
/* Execute the procedure even if pika_pdb_lookup_procedure()
|
||||
* returned NULL, pika_pdb_execute_procedure_by_name_args() will
|
||||
* return appropriate error return_vals.
|
||||
*/
|
||||
pika_plug_in_manager_plug_in_push (plug_in->manager, plug_in);
|
||||
return_vals = pika_pdb_execute_procedure_by_name_args (plug_in->manager->pika->pdb,
|
||||
proc_frame->context_stack ?
|
||||
proc_frame->context_stack->data :
|
||||
proc_frame->main_context,
|
||||
proc_frame->progress,
|
||||
&error,
|
||||
proc_name,
|
||||
args);
|
||||
pika_plug_in_manager_plug_in_pop (plug_in->manager);
|
||||
|
||||
pika_value_array_unref (args);
|
||||
|
||||
if (error)
|
||||
{
|
||||
pika_plug_in_handle_proc_error (plug_in, proc_frame,
|
||||
canonical, error);
|
||||
g_error_free (error);
|
||||
}
|
||||
|
||||
g_free (canonical);
|
||||
|
||||
/* Don't bother to send the return value if executing the procedure
|
||||
* closed the plug-in (e.g. if the procedure is pika-quit)
|
||||
*/
|
||||
if (plug_in->open)
|
||||
{
|
||||
GPProcReturn proc_return;
|
||||
|
||||
/* Return the name we got called with, *not* proc_name or canonical,
|
||||
* since proc_name may have been remapped by pika->procedural_compat_ht
|
||||
* and canonical may be different too.
|
||||
*/
|
||||
proc_return.name = proc_run->name;
|
||||
proc_return.n_params = pika_value_array_length (return_vals);
|
||||
proc_return.params = _pika_value_array_to_gp_params (return_vals, FALSE);
|
||||
|
||||
if (! gp_proc_return_write (plug_in->my_write, &proc_return, plug_in))
|
||||
{
|
||||
pika_message (plug_in->manager->pika, NULL, PIKA_MESSAGE_ERROR,
|
||||
"%s: ERROR", G_STRFUNC);
|
||||
pika_plug_in_close (plug_in, TRUE);
|
||||
}
|
||||
|
||||
_pika_gp_params_free (proc_return.params, proc_return.n_params, FALSE);
|
||||
}
|
||||
|
||||
pika_value_array_unref (return_vals);
|
||||
}
|
||||
|
||||
static void
|
||||
pika_plug_in_handle_proc_return (PikaPlugIn *plug_in,
|
||||
GPProcReturn *proc_return)
|
||||
{
|
||||
PikaPlugInProcFrame *proc_frame = &plug_in->main_proc_frame;
|
||||
|
||||
g_return_if_fail (proc_return != NULL);
|
||||
|
||||
proc_frame->return_vals =
|
||||
_pika_gp_params_to_value_array (plug_in->manager->pika,
|
||||
proc_frame->procedure->values,
|
||||
proc_frame->procedure->num_values,
|
||||
proc_return->params,
|
||||
proc_return->n_params,
|
||||
TRUE);
|
||||
|
||||
if (proc_frame->main_loop)
|
||||
{
|
||||
g_main_loop_quit (proc_frame->main_loop);
|
||||
}
|
||||
else
|
||||
{
|
||||
/* the plug-in is run asynchronously, so display its error
|
||||
* messages here because nobody else will do it
|
||||
*/
|
||||
pika_plug_in_procedure_handle_return_values (PIKA_PLUG_IN_PROCEDURE (proc_frame->procedure),
|
||||
plug_in->manager->pika,
|
||||
proc_frame->progress,
|
||||
proc_frame->return_vals);
|
||||
}
|
||||
|
||||
pika_plug_in_close (plug_in, FALSE);
|
||||
}
|
||||
|
||||
static void
|
||||
pika_plug_in_handle_temp_proc_return (PikaPlugIn *plug_in,
|
||||
GPProcReturn *proc_return)
|
||||
{
|
||||
g_return_if_fail (proc_return != NULL);
|
||||
|
||||
if (plug_in->temp_proc_frames)
|
||||
{
|
||||
PikaPlugInProcFrame *proc_frame = plug_in->temp_proc_frames->data;
|
||||
|
||||
proc_frame->return_vals =
|
||||
_pika_gp_params_to_value_array (plug_in->manager->pika,
|
||||
proc_frame->procedure->values,
|
||||
proc_frame->procedure->num_values,
|
||||
proc_return->params,
|
||||
proc_return->n_params,
|
||||
TRUE);
|
||||
|
||||
pika_plug_in_main_loop_quit (plug_in);
|
||||
pika_plug_in_proc_frame_pop (plug_in);
|
||||
}
|
||||
else
|
||||
{
|
||||
pika_message (plug_in->manager->pika, NULL, PIKA_MESSAGE_ERROR,
|
||||
"Plug-in \"%s\"\n(%s)\n\n"
|
||||
"sent a TEMP_PROC_RETURN message while not running "
|
||||
"a temporary procedure. This should not happen.",
|
||||
pika_object_get_name (plug_in),
|
||||
pika_file_get_utf8_name (plug_in->file));
|
||||
pika_plug_in_close (plug_in, TRUE);
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
pika_plug_in_handle_proc_install (PikaPlugIn *plug_in,
|
||||
GPProcInstall *proc_install)
|
||||
{
|
||||
PikaPlugInProcedure *proc = NULL;
|
||||
PikaProcedure *procedure = NULL;
|
||||
gboolean null_name = FALSE;
|
||||
gboolean valid_utf8 = TRUE;
|
||||
gint i;
|
||||
|
||||
g_return_if_fail (proc_install != NULL);
|
||||
g_return_if_fail (proc_install->name != NULL);
|
||||
|
||||
if (! pika_is_canonical_identifier (proc_install->name))
|
||||
{
|
||||
pika_message (plug_in->manager->pika, NULL, PIKA_MESSAGE_ERROR,
|
||||
"Plug-in \"%s\"\n(%s)\n\n"
|
||||
"attempted to install procedure \"%s\" with a "
|
||||
"non-canonical name.",
|
||||
pika_object_get_name (plug_in),
|
||||
pika_file_get_utf8_name (plug_in->file),
|
||||
proc_install->name);
|
||||
return;
|
||||
}
|
||||
|
||||
/* Sanity check for array arguments */
|
||||
|
||||
for (i = 1; i < proc_install->n_params; i++)
|
||||
{
|
||||
GPParamDef *param_def = &proc_install->params[i];
|
||||
GPParamDef *prev_param_def = &proc_install->params[i - 1];
|
||||
|
||||
if ((! strcmp (param_def->type_name, "PikaParamInt32Array") ||
|
||||
! strcmp (param_def->type_name, "PikaParamIntFloatArray") ||
|
||||
! strcmp (param_def->type_name, "PikaParamIntColorArray"))
|
||||
&&
|
||||
strcmp (prev_param_def->type_name, "GParamInt"))
|
||||
{
|
||||
pika_message (plug_in->manager->pika, NULL, PIKA_MESSAGE_ERROR,
|
||||
"Plug-in \"%s\"\n(%s)\n\n"
|
||||
"attempted to install procedure \"%s\" "
|
||||
"which fails to comply with the array parameter "
|
||||
"passing standard. Argument %d is noncompliant.",
|
||||
pika_object_get_name (plug_in),
|
||||
pika_file_get_utf8_name (plug_in->file),
|
||||
proc_install->name, i);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
/* Sanity check strings for UTF-8 validity */
|
||||
|
||||
#define VALIDATE(str) ((str) == NULL || g_utf8_validate ((str), -1, NULL))
|
||||
|
||||
for (i = 0; i < proc_install->n_params && valid_utf8 && ! null_name; i++)
|
||||
{
|
||||
if (! proc_install->params[i].name)
|
||||
{
|
||||
null_name = TRUE;
|
||||
}
|
||||
else if (! (VALIDATE (proc_install->params[i].name) &&
|
||||
VALIDATE (proc_install->params[i].nick) &&
|
||||
VALIDATE (proc_install->params[i].blurb)))
|
||||
{
|
||||
valid_utf8 = FALSE;
|
||||
}
|
||||
}
|
||||
|
||||
for (i = 0; i < proc_install->n_return_vals && valid_utf8 && !null_name; i++)
|
||||
{
|
||||
if (! proc_install->return_vals[i].name)
|
||||
{
|
||||
null_name = TRUE;
|
||||
}
|
||||
else if (! (VALIDATE (proc_install->return_vals[i].name) &&
|
||||
VALIDATE (proc_install->return_vals[i].nick) &&
|
||||
VALIDATE (proc_install->return_vals[i].blurb)))
|
||||
{
|
||||
valid_utf8 = FALSE;
|
||||
}
|
||||
}
|
||||
|
||||
#undef VALIDATE
|
||||
|
||||
if (null_name)
|
||||
{
|
||||
pika_message (plug_in->manager->pika, NULL, PIKA_MESSAGE_ERROR,
|
||||
"Plug-in \"%s\"\n(%s)\n\n"
|
||||
"attempted to install procedure \"%s\" with a "
|
||||
"NULL parameter name.",
|
||||
pika_object_get_name (plug_in),
|
||||
pika_file_get_utf8_name (plug_in->file),
|
||||
proc_install->name);
|
||||
return;
|
||||
}
|
||||
|
||||
if (! valid_utf8)
|
||||
{
|
||||
pika_message (plug_in->manager->pika, NULL, PIKA_MESSAGE_ERROR,
|
||||
"Plug-in \"%s\"\n(%s)\n\n"
|
||||
"attempted to install procedure \"%s\" with "
|
||||
"invalid UTF-8 strings.",
|
||||
pika_object_get_name (plug_in),
|
||||
pika_file_get_utf8_name (plug_in->file),
|
||||
proc_install->name);
|
||||
return;
|
||||
}
|
||||
|
||||
/* Create the procedure object */
|
||||
|
||||
switch (proc_install->type)
|
||||
{
|
||||
case PIKA_PDB_PROC_TYPE_PLUGIN:
|
||||
case PIKA_PDB_PROC_TYPE_EXTENSION:
|
||||
procedure = pika_plug_in_procedure_new (proc_install->type,
|
||||
plug_in->file);
|
||||
break;
|
||||
|
||||
case PIKA_PDB_PROC_TYPE_TEMPORARY:
|
||||
procedure = pika_temporary_procedure_new (plug_in);
|
||||
break;
|
||||
}
|
||||
|
||||
proc = PIKA_PLUG_IN_PROCEDURE (procedure);
|
||||
|
||||
proc->mtime = time (NULL);
|
||||
proc->installed_during_init = (plug_in->call_mode == PIKA_PLUG_IN_CALL_INIT);
|
||||
|
||||
pika_object_set_name (PIKA_OBJECT (procedure), proc_install->name);
|
||||
|
||||
for (i = 0; i < proc_install->n_params; i++)
|
||||
{
|
||||
GParamSpec *pspec =
|
||||
_pika_gp_param_def_to_param_spec (&proc_install->params[i]);
|
||||
|
||||
if (pspec)
|
||||
pika_procedure_add_argument (procedure, pspec);
|
||||
}
|
||||
|
||||
for (i = 0; i < proc_install->n_return_vals; i++)
|
||||
{
|
||||
GParamSpec *pspec =
|
||||
_pika_gp_param_def_to_param_spec (&proc_install->return_vals[i]);
|
||||
|
||||
if (pspec)
|
||||
pika_procedure_add_return_value (procedure, pspec);
|
||||
}
|
||||
|
||||
/* Install the procedure */
|
||||
|
||||
switch (proc_install->type)
|
||||
{
|
||||
case PIKA_PDB_PROC_TYPE_PLUGIN:
|
||||
case PIKA_PDB_PROC_TYPE_EXTENSION:
|
||||
pika_plug_in_def_add_procedure (plug_in->plug_in_def, proc);
|
||||
break;
|
||||
|
||||
case PIKA_PDB_PROC_TYPE_TEMPORARY:
|
||||
pika_plug_in_add_temp_proc (plug_in, PIKA_TEMPORARY_PROCEDURE (proc));
|
||||
break;
|
||||
}
|
||||
|
||||
g_object_unref (proc);
|
||||
}
|
||||
|
||||
static void
|
||||
pika_plug_in_handle_proc_uninstall (PikaPlugIn *plug_in,
|
||||
GPProcUninstall *proc_uninstall)
|
||||
{
|
||||
PikaPlugInProcedure *proc;
|
||||
|
||||
g_return_if_fail (proc_uninstall != NULL);
|
||||
g_return_if_fail (proc_uninstall->name != NULL);
|
||||
|
||||
if (! pika_is_canonical_identifier (proc_uninstall->name))
|
||||
{
|
||||
pika_message (plug_in->manager->pika, NULL, PIKA_MESSAGE_ERROR,
|
||||
"Plug-in \"%s\"\n(%s)\n\n"
|
||||
"attempted to uninstall procedure \"%s\" with a "
|
||||
"non-canonical name.",
|
||||
pika_object_get_name (plug_in),
|
||||
pika_file_get_utf8_name (plug_in->file),
|
||||
proc_uninstall->name);
|
||||
return;
|
||||
}
|
||||
|
||||
proc = pika_plug_in_procedure_find (plug_in->temp_procedures,
|
||||
proc_uninstall->name);
|
||||
|
||||
if (proc)
|
||||
pika_plug_in_remove_temp_proc (plug_in, PIKA_TEMPORARY_PROCEDURE (proc));
|
||||
}
|
||||
|
||||
static void
|
||||
pika_plug_in_handle_extension_ack (PikaPlugIn *plug_in)
|
||||
{
|
||||
if (plug_in->ext_main_loop)
|
||||
{
|
||||
g_main_loop_quit (plug_in->ext_main_loop);
|
||||
}
|
||||
else
|
||||
{
|
||||
pika_message (plug_in->manager->pika, NULL, PIKA_MESSAGE_ERROR,
|
||||
"Plug-in \"%s\"\n(%s)\n\n"
|
||||
"sent an EXTENSION_ACK message while not being started "
|
||||
"as an extension. This should not happen.",
|
||||
pika_object_get_name (plug_in),
|
||||
pika_file_get_utf8_name (plug_in->file));
|
||||
pika_plug_in_close (plug_in, TRUE);
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
pika_plug_in_handle_has_init (PikaPlugIn *plug_in)
|
||||
{
|
||||
if (plug_in->call_mode == PIKA_PLUG_IN_CALL_QUERY)
|
||||
{
|
||||
pika_plug_in_def_set_has_init (plug_in->plug_in_def, TRUE);
|
||||
}
|
||||
else
|
||||
{
|
||||
pika_message (plug_in->manager->pika, NULL, PIKA_MESSAGE_ERROR,
|
||||
"Plug-in \"%s\"\n(%s)\n\n"
|
||||
"sent an HAS_INIT message while not in query(). "
|
||||
"This should not happen.",
|
||||
pika_object_get_name (plug_in),
|
||||
pika_file_get_utf8_name (plug_in->file));
|
||||
pika_plug_in_close (plug_in, TRUE);
|
||||
}
|
||||
}
|
32
app/plug-in/pikaplugin-message.h
Normal file
32
app/plug-in/pikaplugin-message.h
Normal file
@ -0,0 +1,32 @@
|
||||
/* PIKA - Photo and Image Kooker Application
|
||||
* a rebranding of The GNU Image Manipulation Program (created with heckimp)
|
||||
* A derived work which may be trivial. However, any changes may be (C)2023 by Aldercone Studio
|
||||
*
|
||||
* Original copyright, applying to most contents (license remains unchanged):
|
||||
* Copyright (C) 1995 Spencer Kimball and Peter Mattis
|
||||
*
|
||||
* pikaplugin-message.h
|
||||
*
|
||||
* 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 3 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, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#ifndef __PIKA_PLUG_IN_MESSAGE_H__
|
||||
#define __PIKA_PLUG_IN_MESSAGE_H__
|
||||
|
||||
|
||||
void pika_plug_in_handle_message (PikaPlugIn *plug_in,
|
||||
PikaWireMessage *msg);
|
||||
|
||||
|
||||
#endif /* __PIKA_PLUG_IN_MESSAGE_H__ */
|
676
app/plug-in/pikaplugin-proc.c
Normal file
676
app/plug-in/pikaplugin-proc.c
Normal file
@ -0,0 +1,676 @@
|
||||
/* PIKA - Photo and Image Kooker Application
|
||||
* a rebranding of The GNU Image Manipulation Program (created with heckimp)
|
||||
* A derived work which may be trivial. However, any changes may be (C)2023 by Aldercone Studio
|
||||
*
|
||||
* Original copyright, applying to most contents (license remains unchanged):
|
||||
* Copyright (C) 1995 Spencer Kimball and Peter Mattis
|
||||
*
|
||||
* pikaplugin-proc.c
|
||||
*
|
||||
* 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 3 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, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include "config.h"
|
||||
|
||||
#include <gdk-pixbuf/gdk-pixbuf.h>
|
||||
#include <gegl.h>
|
||||
|
||||
#include "libpikabase/pikabase.h"
|
||||
|
||||
#include "plug-in-types.h"
|
||||
|
||||
#include "core/pikaparamspecs.h"
|
||||
|
||||
#include "pdb/pikapdberror.h"
|
||||
|
||||
#include "pikaplugin.h"
|
||||
#include "pikaplugin-proc.h"
|
||||
#include "pikaplugindef.h"
|
||||
#include "pikapluginmanager.h"
|
||||
#include "pikapluginmanager-file.h"
|
||||
#include "pikapluginprocedure.h"
|
||||
|
||||
#include "pika-intl.h"
|
||||
|
||||
|
||||
/* local function prototypes */
|
||||
|
||||
static PikaPlugInProcedure * pika_plug_in_proc_find (PikaPlugIn *plug_in,
|
||||
const gchar *proc_name);
|
||||
|
||||
|
||||
/* public functions */
|
||||
|
||||
gboolean
|
||||
pika_plug_in_set_proc_image_types (PikaPlugIn *plug_in,
|
||||
const gchar *proc_name,
|
||||
const gchar *image_types,
|
||||
GError **error)
|
||||
{
|
||||
PikaPlugInProcedure *proc;
|
||||
|
||||
g_return_val_if_fail (PIKA_IS_PLUG_IN (plug_in), FALSE);
|
||||
g_return_val_if_fail (proc_name != NULL, FALSE);
|
||||
|
||||
proc = pika_plug_in_proc_find (plug_in, proc_name);
|
||||
|
||||
if (! proc)
|
||||
{
|
||||
g_set_error (error, PIKA_PDB_ERROR, PIKA_PDB_ERROR_PROCEDURE_NOT_FOUND,
|
||||
"Plug-in \"%s\"\n(%s)\n"
|
||||
"attempted to register images types "
|
||||
"for procedure \"%s\".\n"
|
||||
"It has however not installed that procedure. "
|
||||
"This is not allowed.",
|
||||
pika_object_get_name (plug_in),
|
||||
pika_file_get_utf8_name (plug_in->file),
|
||||
proc_name);
|
||||
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
pika_plug_in_procedure_set_image_types (proc, image_types);
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
gboolean
|
||||
pika_plug_in_set_proc_sensitivity_mask (PikaPlugIn *plug_in,
|
||||
const gchar *proc_name,
|
||||
gint sensitivity_mask,
|
||||
GError **error)
|
||||
{
|
||||
PikaPlugInProcedure *proc;
|
||||
|
||||
g_return_val_if_fail (PIKA_IS_PLUG_IN (plug_in), FALSE);
|
||||
g_return_val_if_fail (proc_name != NULL, FALSE);
|
||||
|
||||
proc = pika_plug_in_proc_find (plug_in, proc_name);
|
||||
|
||||
if (! proc)
|
||||
{
|
||||
g_set_error (error, PIKA_PDB_ERROR, PIKA_PDB_ERROR_PROCEDURE_NOT_FOUND,
|
||||
"Plug-in \"%s\"\n(%s)\n"
|
||||
"attempted to register the sensitivity mask \"%x\" "
|
||||
"for procedure \"%s\".\n"
|
||||
"It has however not installed that procedure. "
|
||||
"This is not allowed.",
|
||||
pika_object_get_name (plug_in),
|
||||
pika_file_get_utf8_name (plug_in->file),
|
||||
sensitivity_mask, proc_name);
|
||||
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
pika_plug_in_procedure_set_sensitivity_mask (proc, sensitivity_mask);
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
gboolean
|
||||
pika_plug_in_set_proc_menu_label (PikaPlugIn *plug_in,
|
||||
const gchar *proc_name,
|
||||
const gchar *menu_label,
|
||||
GError **error)
|
||||
{
|
||||
PikaPlugInProcedure *proc;
|
||||
|
||||
g_return_val_if_fail (PIKA_IS_PLUG_IN (plug_in), FALSE);
|
||||
g_return_val_if_fail (proc_name != NULL, FALSE);
|
||||
g_return_val_if_fail (menu_label != NULL && strlen (menu_label), FALSE);
|
||||
|
||||
proc = pika_plug_in_proc_find (plug_in, proc_name);
|
||||
|
||||
if (! proc)
|
||||
{
|
||||
g_set_error (error, PIKA_PDB_ERROR, PIKA_PDB_ERROR_PROCEDURE_NOT_FOUND,
|
||||
"Plug-in \"%s\"\n(%s)\n"
|
||||
"attempted to register the menu label \"%s\" "
|
||||
"for procedure \"%s\".\n"
|
||||
"It has however not installed that procedure. "
|
||||
"This is not allowed.",
|
||||
pika_object_get_name (plug_in),
|
||||
pika_file_get_utf8_name (plug_in->file),
|
||||
menu_label, proc_name);
|
||||
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
return pika_plug_in_procedure_set_menu_label (proc, menu_label, error);
|
||||
}
|
||||
|
||||
gboolean
|
||||
pika_plug_in_add_proc_menu_path (PikaPlugIn *plug_in,
|
||||
const gchar *proc_name,
|
||||
const gchar *menu_path,
|
||||
GError **error)
|
||||
{
|
||||
PikaPlugInProcedure *proc;
|
||||
|
||||
g_return_val_if_fail (PIKA_IS_PLUG_IN (plug_in), FALSE);
|
||||
g_return_val_if_fail (proc_name != NULL, FALSE);
|
||||
g_return_val_if_fail (menu_path != NULL, FALSE);
|
||||
|
||||
proc = pika_plug_in_proc_find (plug_in, proc_name);
|
||||
|
||||
if (! proc)
|
||||
{
|
||||
g_set_error (error, PIKA_PDB_ERROR, PIKA_PDB_ERROR_PROCEDURE_NOT_FOUND,
|
||||
"Plug-in \"%s\"\n(%s)\n"
|
||||
"attempted to register the menu item \"%s\" "
|
||||
"for procedure \"%s\".\n"
|
||||
"It has however not installed that procedure. "
|
||||
"This is not allowed.",
|
||||
pika_object_get_name (plug_in),
|
||||
pika_file_get_utf8_name (plug_in->file),
|
||||
menu_path, proc_name);
|
||||
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
return pika_plug_in_procedure_add_menu_path (proc, menu_path, error);
|
||||
}
|
||||
|
||||
gboolean
|
||||
pika_plug_in_set_proc_icon (PikaPlugIn *plug_in,
|
||||
const gchar *proc_name,
|
||||
PikaIconType type,
|
||||
const guint8 *data,
|
||||
gint data_length,
|
||||
GError **error)
|
||||
{
|
||||
PikaPlugInProcedure *proc;
|
||||
|
||||
g_return_val_if_fail (PIKA_IS_PLUG_IN (plug_in), FALSE);
|
||||
g_return_val_if_fail (proc_name != NULL, FALSE);
|
||||
|
||||
proc = pika_plug_in_proc_find (plug_in, proc_name);
|
||||
|
||||
if (! proc)
|
||||
{
|
||||
g_set_error (error, PIKA_PDB_ERROR, PIKA_PDB_ERROR_PROCEDURE_NOT_FOUND,
|
||||
"Plug-in \"%s\"\n(%s)\n"
|
||||
"attempted to set the icon "
|
||||
"for procedure \"%s\".\n"
|
||||
"It has however not installed that procedure. "
|
||||
"This is not allowed.",
|
||||
pika_object_get_name (plug_in),
|
||||
pika_file_get_utf8_name (plug_in->file),
|
||||
proc_name);
|
||||
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
return pika_plug_in_procedure_set_icon (proc, type, data, data_length,
|
||||
error);
|
||||
}
|
||||
|
||||
gboolean
|
||||
pika_plug_in_set_proc_help (PikaPlugIn *plug_in,
|
||||
const gchar *proc_name,
|
||||
const gchar *blurb,
|
||||
const gchar *help,
|
||||
const gchar *help_id,
|
||||
GError **error)
|
||||
{
|
||||
PikaPlugInProcedure *proc;
|
||||
|
||||
g_return_val_if_fail (PIKA_IS_PLUG_IN (plug_in), FALSE);
|
||||
g_return_val_if_fail (proc_name != NULL, FALSE);
|
||||
|
||||
proc = pika_plug_in_proc_find (plug_in, proc_name);
|
||||
|
||||
if (! proc)
|
||||
{
|
||||
g_set_error (error, PIKA_PDB_ERROR, PIKA_PDB_ERROR_PROCEDURE_NOT_FOUND,
|
||||
"Plug-in \"%s\"\n(%s)\n"
|
||||
"attempted to register help "
|
||||
"for procedure \"%s\".\n"
|
||||
"It has however not installed that procedure. "
|
||||
"This is not allowed.",
|
||||
pika_object_get_name (plug_in),
|
||||
pika_file_get_utf8_name (plug_in->file),
|
||||
proc_name);
|
||||
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
pika_procedure_set_help (PIKA_PROCEDURE (proc),
|
||||
blurb, help, help_id);
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
gboolean
|
||||
pika_plug_in_set_proc_attribution (PikaPlugIn *plug_in,
|
||||
const gchar *proc_name,
|
||||
const gchar *authors,
|
||||
const gchar *copyright,
|
||||
const gchar *date,
|
||||
GError **error)
|
||||
{
|
||||
PikaPlugInProcedure *proc;
|
||||
|
||||
g_return_val_if_fail (PIKA_IS_PLUG_IN (plug_in), FALSE);
|
||||
g_return_val_if_fail (proc_name != NULL, FALSE);
|
||||
|
||||
proc = pika_plug_in_proc_find (plug_in, proc_name);
|
||||
|
||||
if (! proc)
|
||||
{
|
||||
g_set_error (error, PIKA_PDB_ERROR, PIKA_PDB_ERROR_PROCEDURE_NOT_FOUND,
|
||||
"Plug-in \"%s\"\n(%s)\n"
|
||||
"attempted to register the attribution "
|
||||
"for procedure \"%s\".\n"
|
||||
"It has however not installed that procedure. "
|
||||
"This is not allowed.",
|
||||
pika_object_get_name (plug_in),
|
||||
pika_file_get_utf8_name (plug_in->file),
|
||||
proc_name);
|
||||
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
pika_procedure_set_attribution (PIKA_PROCEDURE (proc),
|
||||
authors, copyright, date);
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static inline gboolean
|
||||
PIKA_IS_PARAM_SPEC_RUN_MODE (GParamSpec *pspec)
|
||||
{
|
||||
return (G_IS_PARAM_SPEC_ENUM (pspec) &&
|
||||
pspec->value_type == PIKA_TYPE_RUN_MODE);
|
||||
}
|
||||
|
||||
static inline gboolean
|
||||
PIKA_IS_PARAM_SPEC_FILE (GParamSpec *pspec)
|
||||
{
|
||||
return (G_IS_PARAM_SPEC_OBJECT (pspec) &&
|
||||
pspec->value_type == G_TYPE_FILE);
|
||||
}
|
||||
|
||||
gboolean
|
||||
pika_plug_in_set_file_proc_load_handler (PikaPlugIn *plug_in,
|
||||
const gchar *proc_name,
|
||||
const gchar *extensions,
|
||||
const gchar *prefixes,
|
||||
const gchar *magics,
|
||||
GError **error)
|
||||
{
|
||||
PikaPlugInProcedure *proc;
|
||||
PikaProcedure *procedure;
|
||||
|
||||
g_return_val_if_fail (PIKA_IS_PLUG_IN (plug_in), FALSE);
|
||||
g_return_val_if_fail (proc_name != NULL, FALSE);
|
||||
|
||||
proc = pika_plug_in_proc_find (plug_in, proc_name);
|
||||
|
||||
if (! proc)
|
||||
{
|
||||
g_set_error (error, PIKA_PDB_ERROR, PIKA_PDB_ERROR_PROCEDURE_NOT_FOUND,
|
||||
"Plug-in \"%s\"\n(%s)\n"
|
||||
"attempted to register procedure \"%s\" "
|
||||
"as load handler.\n"
|
||||
"It has however not installed that procedure. "
|
||||
"This is not allowed.",
|
||||
pika_object_get_name (plug_in),
|
||||
pika_file_get_utf8_name (plug_in->file),
|
||||
proc_name);
|
||||
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
procedure = PIKA_PROCEDURE (proc);
|
||||
|
||||
if (((procedure->num_args < 2) ||
|
||||
(procedure->num_values < 1) ||
|
||||
! PIKA_IS_PARAM_SPEC_RUN_MODE (procedure->args[0]) ||
|
||||
! PIKA_IS_PARAM_SPEC_FILE (procedure->args[1]) ||
|
||||
(! proc->generic_file_proc &&
|
||||
! PIKA_IS_PARAM_SPEC_IMAGE (procedure->values[0]))))
|
||||
{
|
||||
g_set_error (error, PIKA_PDB_ERROR, PIKA_PDB_ERROR_FAILED,
|
||||
"Plug-in \"%s\"\n(%s)\n"
|
||||
"attempted to register procedure \"%s\" "
|
||||
"as load handler which does not take the standard "
|
||||
"load procedure arguments: "
|
||||
"(PikaRunMode, GFile) -> (PikaImage)",
|
||||
pika_object_get_name (plug_in),
|
||||
pika_file_get_utf8_name (plug_in->file),
|
||||
proc_name);
|
||||
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
pika_plug_in_procedure_set_file_proc (proc, extensions, prefixes, magics);
|
||||
|
||||
pika_plug_in_manager_add_load_procedure (plug_in->manager, proc);
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
gboolean
|
||||
pika_plug_in_set_file_proc_save_handler (PikaPlugIn *plug_in,
|
||||
const gchar *proc_name,
|
||||
const gchar *extensions,
|
||||
const gchar *prefixes,
|
||||
GError **error)
|
||||
{
|
||||
PikaPlugInProcedure *proc;
|
||||
PikaProcedure *procedure;
|
||||
|
||||
g_return_val_if_fail (PIKA_IS_PLUG_IN (plug_in), FALSE);
|
||||
g_return_val_if_fail (proc_name != NULL, FALSE);
|
||||
|
||||
proc = pika_plug_in_proc_find (plug_in, proc_name);
|
||||
|
||||
if (! proc)
|
||||
{
|
||||
g_set_error (error, PIKA_PDB_ERROR, PIKA_PDB_ERROR_PROCEDURE_NOT_FOUND,
|
||||
"Plug-in \"%s\"\n(%s)\n"
|
||||
"attempted to register procedure \"%s\" "
|
||||
"as save handler.\n"
|
||||
"It has however not installed that procedure. "
|
||||
"This is not allowed.",
|
||||
pika_object_get_name (plug_in),
|
||||
pika_file_get_utf8_name (plug_in->file),
|
||||
proc_name);
|
||||
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
procedure = PIKA_PROCEDURE (proc);
|
||||
|
||||
if ((procedure->num_args < 5) ||
|
||||
! PIKA_IS_PARAM_SPEC_RUN_MODE (procedure->args[0]) ||
|
||||
! PIKA_IS_PARAM_SPEC_IMAGE (procedure->args[1]) ||
|
||||
! G_IS_PARAM_SPEC_INT (procedure->args[2]) ||
|
||||
! PIKA_IS_PARAM_SPEC_OBJECT_ARRAY (procedure->args[3]) ||
|
||||
! PIKA_IS_PARAM_SPEC_FILE (procedure->args[4]))
|
||||
{
|
||||
g_set_error (error, PIKA_PDB_ERROR, PIKA_PDB_ERROR_FAILED,
|
||||
"Plug-in \"%s\"\n(%s)\n"
|
||||
"attempted to register procedure \"%s\" "
|
||||
"as save handler which does not take the standard "
|
||||
"save procedure arguments:\n"
|
||||
"(PikaRunMode, PikaImage, int [array size], PikaDrawable Array, GFile)",
|
||||
pika_object_get_name (plug_in),
|
||||
pika_file_get_utf8_name (plug_in->file),
|
||||
proc_name);
|
||||
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
pika_plug_in_procedure_set_file_proc (proc, extensions, prefixes, NULL);
|
||||
|
||||
pika_plug_in_manager_add_save_procedure (plug_in->manager, proc);
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
gboolean
|
||||
pika_plug_in_set_file_proc_priority (PikaPlugIn *plug_in,
|
||||
const gchar *proc_name,
|
||||
gint priority,
|
||||
GError **error)
|
||||
{
|
||||
PikaPlugInProcedure *proc;
|
||||
|
||||
g_return_val_if_fail (PIKA_IS_PLUG_IN (plug_in), FALSE);
|
||||
g_return_val_if_fail (proc_name != NULL, FALSE);
|
||||
|
||||
proc = pika_plug_in_proc_find (plug_in, proc_name);
|
||||
|
||||
if (! proc)
|
||||
{
|
||||
g_set_error (error, PIKA_PDB_ERROR, PIKA_PDB_ERROR_PROCEDURE_NOT_FOUND,
|
||||
"Plug-in \"%s\"\n(%s)\n"
|
||||
"attempted to register the priority "
|
||||
"for procedure \"%s\".\n"
|
||||
"It has however not installed that procedure. "
|
||||
"This is not allowed.",
|
||||
pika_object_get_name (plug_in),
|
||||
pika_file_get_utf8_name (plug_in->file),
|
||||
proc_name);
|
||||
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
pika_plug_in_procedure_set_priority (proc, priority);
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
gboolean
|
||||
pika_plug_in_set_file_proc_mime_types (PikaPlugIn *plug_in,
|
||||
const gchar *proc_name,
|
||||
const gchar *mime_types,
|
||||
GError **error)
|
||||
{
|
||||
PikaPlugInProcedure *proc;
|
||||
|
||||
g_return_val_if_fail (PIKA_IS_PLUG_IN (plug_in), FALSE);
|
||||
g_return_val_if_fail (proc_name != NULL, FALSE);
|
||||
|
||||
proc = pika_plug_in_proc_find (plug_in, proc_name);
|
||||
|
||||
if (! proc)
|
||||
{
|
||||
g_set_error (error, PIKA_PDB_ERROR, PIKA_PDB_ERROR_PROCEDURE_NOT_FOUND,
|
||||
"Plug-in \"%s\"\n(%s)\n"
|
||||
"attempted to register mime types "
|
||||
"for procedure \"%s\".\n"
|
||||
"It has however not installed that procedure. "
|
||||
"This is not allowed.",
|
||||
pika_object_get_name (plug_in),
|
||||
pika_file_get_utf8_name (plug_in->file),
|
||||
proc_name);
|
||||
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
pika_plug_in_procedure_set_mime_types (proc, mime_types);
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
gboolean
|
||||
pika_plug_in_set_file_proc_handles_remote (PikaPlugIn *plug_in,
|
||||
const gchar *proc_name,
|
||||
GError **error)
|
||||
{
|
||||
PikaPlugInProcedure *proc;
|
||||
|
||||
g_return_val_if_fail (PIKA_IS_PLUG_IN (plug_in), FALSE);
|
||||
g_return_val_if_fail (proc_name != NULL, FALSE);
|
||||
|
||||
proc = pika_plug_in_proc_find (plug_in, proc_name);
|
||||
|
||||
if (! proc)
|
||||
{
|
||||
g_set_error (error, PIKA_PDB_ERROR, PIKA_PDB_ERROR_PROCEDURE_NOT_FOUND,
|
||||
"Plug-in \"%s\"\n(%s)\n"
|
||||
"attempted to register 'handles remote' "
|
||||
"for procedure \"%s\".\n"
|
||||
"It has however not installed that procedure. "
|
||||
"This is not allowed.",
|
||||
pika_object_get_name (plug_in),
|
||||
pika_file_get_utf8_name (plug_in->file),
|
||||
proc_name);
|
||||
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
pika_plug_in_procedure_set_handles_remote (proc);
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
gboolean
|
||||
pika_plug_in_set_file_proc_handles_raw (PikaPlugIn *plug_in,
|
||||
const gchar *proc_name,
|
||||
GError **error)
|
||||
{
|
||||
PikaPlugInProcedure *proc;
|
||||
|
||||
g_return_val_if_fail (PIKA_IS_PLUG_IN (plug_in), FALSE);
|
||||
g_return_val_if_fail (proc_name != NULL, FALSE);
|
||||
|
||||
proc = pika_plug_in_proc_find (plug_in, proc_name);
|
||||
|
||||
if (! proc)
|
||||
{
|
||||
g_set_error (error, PIKA_PDB_ERROR, PIKA_PDB_ERROR_PROCEDURE_NOT_FOUND,
|
||||
"Plug-in \"%s\"\n(%s)\n"
|
||||
"attempted to register 'handles raw' "
|
||||
"for procedure \"%s\".\n"
|
||||
"It has however not installed that procedure. "
|
||||
"This is not allowed.",
|
||||
pika_object_get_name (plug_in),
|
||||
pika_file_get_utf8_name (plug_in->file),
|
||||
proc_name);
|
||||
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
pika_plug_in_procedure_set_handles_raw (proc);
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
gboolean
|
||||
pika_plug_in_set_file_proc_thumb_loader (PikaPlugIn *plug_in,
|
||||
const gchar *proc_name,
|
||||
const gchar *thumb_proc_name,
|
||||
GError **error)
|
||||
{
|
||||
PikaPlugInProcedure *proc;
|
||||
PikaPlugInProcedure *thumb_proc;
|
||||
|
||||
g_return_val_if_fail (PIKA_IS_PLUG_IN (plug_in), FALSE);
|
||||
g_return_val_if_fail (proc_name != NULL, FALSE);
|
||||
g_return_val_if_fail (thumb_proc_name != NULL, FALSE);
|
||||
|
||||
proc = pika_plug_in_proc_find (plug_in, proc_name);
|
||||
thumb_proc = pika_plug_in_proc_find (plug_in, thumb_proc_name);
|
||||
|
||||
if (! proc)
|
||||
{
|
||||
g_set_error (error, PIKA_PDB_ERROR, PIKA_PDB_ERROR_PROCEDURE_NOT_FOUND,
|
||||
"Plug-in \"%s\"\n(%s)\n"
|
||||
"attempted to register a thumbnail loader "
|
||||
"for procedure \"%s\".\n"
|
||||
"It has however not installed that procedure. "
|
||||
"This is not allowed.",
|
||||
pika_object_get_name (plug_in),
|
||||
pika_file_get_utf8_name (plug_in->file),
|
||||
proc_name);
|
||||
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
if (! thumb_proc)
|
||||
{
|
||||
g_set_error (error, PIKA_PDB_ERROR, PIKA_PDB_ERROR_PROCEDURE_NOT_FOUND,
|
||||
"Plug-in \"%s\"\n(%s)\n"
|
||||
"attempted to register a procedure \"%s\" "
|
||||
"as thumbnail loader.\n"
|
||||
"It has however not installed that procedure. "
|
||||
"This is not allowed.",
|
||||
pika_object_get_name (plug_in),
|
||||
pika_file_get_utf8_name (plug_in->file),
|
||||
thumb_proc_name);
|
||||
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
pika_plug_in_procedure_set_thumb_loader (proc, thumb_proc_name);
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
gboolean
|
||||
pika_plug_in_set_batch_interpreter (PikaPlugIn *plug_in,
|
||||
const gchar *proc_name,
|
||||
const gchar *interpreter_name,
|
||||
GError **error)
|
||||
{
|
||||
PikaPlugInProcedure *proc;
|
||||
PikaProcedure *procedure;
|
||||
|
||||
g_return_val_if_fail (PIKA_IS_PLUG_IN (plug_in), FALSE);
|
||||
g_return_val_if_fail (proc_name != NULL, FALSE);
|
||||
|
||||
proc = pika_plug_in_proc_find (plug_in, proc_name);
|
||||
|
||||
if (! proc)
|
||||
{
|
||||
g_set_error (error, PIKA_PDB_ERROR, PIKA_PDB_ERROR_PROCEDURE_NOT_FOUND,
|
||||
"Plug-in \"%s\"\n(%s)\n"
|
||||
"attempted to register procedure \"%s\" "
|
||||
"as a 'batch interpreter'.\n"
|
||||
"It has however not installed that procedure. "
|
||||
"This is not allowed.",
|
||||
pika_object_get_name (plug_in),
|
||||
pika_file_get_utf8_name (plug_in->file),
|
||||
proc_name);
|
||||
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
procedure = PIKA_PROCEDURE (proc);
|
||||
|
||||
if (procedure->num_args < 2 ||
|
||||
! PIKA_IS_PARAM_SPEC_RUN_MODE (procedure->args[0]) ||
|
||||
! G_IS_PARAM_SPEC_STRING (procedure->args[1]))
|
||||
{
|
||||
g_set_error (error, PIKA_PDB_ERROR, PIKA_PDB_ERROR_FAILED,
|
||||
"Plug-in \"%s\"\n(%s)\n"
|
||||
"attempted to register procedure \"%s\" "
|
||||
"as a batch interpreter which does not take the standard "
|
||||
"batch interpreter procedure arguments: "
|
||||
"(PikaRunMode, gchar *) -> ()",
|
||||
pika_object_get_name (plug_in),
|
||||
pika_file_get_utf8_name (plug_in->file),
|
||||
proc_name);
|
||||
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
pika_plug_in_procedure_set_batch_interpreter (proc, interpreter_name);
|
||||
pika_plug_in_manager_add_batch_procedure (plug_in->manager, proc);
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
|
||||
/* private functions */
|
||||
|
||||
static PikaPlugInProcedure *
|
||||
pika_plug_in_proc_find (PikaPlugIn *plug_in,
|
||||
const gchar *proc_name)
|
||||
{
|
||||
PikaPlugInProcedure *proc = NULL;
|
||||
|
||||
if (plug_in->plug_in_def)
|
||||
proc = pika_plug_in_procedure_find (plug_in->plug_in_def->procedures,
|
||||
proc_name);
|
||||
|
||||
if (! proc)
|
||||
proc = pika_plug_in_procedure_find (plug_in->temp_procedures, proc_name);
|
||||
|
||||
return proc;
|
||||
}
|
98
app/plug-in/pikaplugin-proc.h
Normal file
98
app/plug-in/pikaplugin-proc.h
Normal file
@ -0,0 +1,98 @@
|
||||
/* PIKA - Photo and Image Kooker Application
|
||||
* a rebranding of The GNU Image Manipulation Program (created with heckimp)
|
||||
* A derived work which may be trivial. However, any changes may be (C)2023 by Aldercone Studio
|
||||
*
|
||||
* Original copyright, applying to most contents (license remains unchanged):
|
||||
* Copyright (C) 1995 Spencer Kimball and Peter Mattis
|
||||
*
|
||||
* pikaplugin-proc.h
|
||||
*
|
||||
* 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 3 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, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#ifndef __PIKA_PLUG_IN_PROC_H__
|
||||
#define __PIKA_PLUG_IN_PROC_H__
|
||||
|
||||
|
||||
gboolean pika_plug_in_set_proc_image_types (PikaPlugIn *plug_in,
|
||||
const gchar *proc_name,
|
||||
const gchar *image_types,
|
||||
GError **error);
|
||||
gboolean pika_plug_in_set_proc_sensitivity_mask (PikaPlugIn *plug_in,
|
||||
const gchar *proc_name,
|
||||
gint sensitivity_mask,
|
||||
GError **error);
|
||||
gboolean pika_plug_in_set_proc_menu_label (PikaPlugIn *plug_in,
|
||||
const gchar *proc_name,
|
||||
const gchar *menu_label,
|
||||
GError **error);
|
||||
gboolean pika_plug_in_add_proc_menu_path (PikaPlugIn *plug_in,
|
||||
const gchar *proc_name,
|
||||
const gchar *menu_path,
|
||||
GError **error);
|
||||
gboolean pika_plug_in_set_proc_icon (PikaPlugIn *plug_in,
|
||||
const gchar *proc_name,
|
||||
PikaIconType type,
|
||||
const guint8 *data,
|
||||
gint data_length,
|
||||
GError **error);
|
||||
gboolean pika_plug_in_set_proc_help (PikaPlugIn *plug_in,
|
||||
const gchar *proc_name,
|
||||
const gchar *blurb,
|
||||
const gchar *help,
|
||||
const gchar *help_id,
|
||||
GError **error);
|
||||
gboolean pika_plug_in_set_proc_attribution (PikaPlugIn *plug_in,
|
||||
const gchar *proc_name,
|
||||
const gchar *authors,
|
||||
const gchar *copyright,
|
||||
const gchar *date,
|
||||
GError **error);
|
||||
|
||||
gboolean pika_plug_in_set_file_proc_load_handler (PikaPlugIn *plug_in,
|
||||
const gchar *proc_name,
|
||||
const gchar *extensions,
|
||||
const gchar *prefixes,
|
||||
const gchar *magics,
|
||||
GError **error);
|
||||
gboolean pika_plug_in_set_file_proc_save_handler (PikaPlugIn *plug_in,
|
||||
const gchar *proc_name,
|
||||
const gchar *extensions,
|
||||
const gchar *prefixes,
|
||||
GError **error);
|
||||
gboolean pika_plug_in_set_file_proc_priority (PikaPlugIn *plug_in,
|
||||
const gchar *proc_name,
|
||||
gint priority,
|
||||
GError **error);
|
||||
gboolean pika_plug_in_set_file_proc_mime_types (PikaPlugIn *plug_in,
|
||||
const gchar *proc_name,
|
||||
const gchar *mime_types,
|
||||
GError **error);
|
||||
gboolean pika_plug_in_set_file_proc_handles_remote (PikaPlugIn *plug_in,
|
||||
const gchar *proc_name,
|
||||
GError **error);
|
||||
gboolean pika_plug_in_set_file_proc_handles_raw (PikaPlugIn *plug_in,
|
||||
const gchar *proc_name,
|
||||
GError **error);
|
||||
gboolean pika_plug_in_set_file_proc_thumb_loader (PikaPlugIn *plug_in,
|
||||
const gchar *proc_name,
|
||||
const gchar *thumb_proc,
|
||||
GError **error);
|
||||
gboolean pika_plug_in_set_batch_interpreter (PikaPlugIn *plug_in,
|
||||
const gchar *proc_name,
|
||||
const gchar *interpreter_name,
|
||||
GError **error);
|
||||
|
||||
|
||||
#endif /* __PIKA_PLUG_IN_PROC_H__ */
|
373
app/plug-in/pikaplugin-progress.c
Normal file
373
app/plug-in/pikaplugin-progress.c
Normal file
@ -0,0 +1,373 @@
|
||||
/* PIKA - Photo and Image Kooker Application
|
||||
* a rebranding of The GNU Image Manipulation Program (created with heckimp)
|
||||
* A derived work which may be trivial. However, any changes may be (C)2023 by Aldercone Studio
|
||||
*
|
||||
* Original copyright, applying to most contents (license remains unchanged):
|
||||
* Copyright (C) 1995 Spencer Kimball and Peter Mattis
|
||||
*
|
||||
* pikaplugin-progress.c
|
||||
*
|
||||
* 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 3 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, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include "config.h"
|
||||
|
||||
#include <gdk-pixbuf/gdk-pixbuf.h>
|
||||
#include <gegl.h>
|
||||
|
||||
#include "libpikabase/pikabase.h"
|
||||
|
||||
#include "plug-in-types.h"
|
||||
|
||||
#include "core/pika.h"
|
||||
#include "core/pikadisplay.h"
|
||||
#include "core/pikaparamspecs.h"
|
||||
#include "core/pikapdbprogress.h"
|
||||
#include "core/pikaprogress.h"
|
||||
|
||||
#include "pdb/pikapdb.h"
|
||||
#include "pdb/pikapdberror.h"
|
||||
|
||||
#include "pikaplugin.h"
|
||||
#include "pikaplugin-progress.h"
|
||||
#include "pikapluginmanager.h"
|
||||
#include "pikatemporaryprocedure.h"
|
||||
|
||||
#include "pika-intl.h"
|
||||
|
||||
|
||||
/* local function prototypes */
|
||||
|
||||
static void pika_plug_in_progress_cancel_callback (PikaProgress *progress,
|
||||
PikaPlugIn *plug_in);
|
||||
|
||||
|
||||
/* public functions */
|
||||
|
||||
gint
|
||||
pika_plug_in_progress_attach (PikaProgress *progress)
|
||||
{
|
||||
gint attach_count;
|
||||
|
||||
g_return_val_if_fail (PIKA_IS_PROGRESS (progress), 0);
|
||||
|
||||
attach_count =
|
||||
GPOINTER_TO_INT (g_object_get_data (G_OBJECT (progress),
|
||||
"plug-in-progress-attach-count"));
|
||||
|
||||
attach_count++;
|
||||
|
||||
g_object_set_data (G_OBJECT (progress), "plug-in-progress-attach-count",
|
||||
GINT_TO_POINTER (attach_count));
|
||||
|
||||
return attach_count;
|
||||
}
|
||||
|
||||
gint
|
||||
pika_plug_in_progress_detach (PikaProgress *progress)
|
||||
{
|
||||
gint attach_count;
|
||||
|
||||
g_return_val_if_fail (PIKA_IS_PROGRESS (progress), 0);
|
||||
|
||||
attach_count =
|
||||
GPOINTER_TO_INT (g_object_get_data (G_OBJECT (progress),
|
||||
"plug-in-progress-attach-count"));
|
||||
|
||||
attach_count--;
|
||||
|
||||
g_object_set_data (G_OBJECT (progress), "plug-in-progress-attach-count",
|
||||
GINT_TO_POINTER (attach_count));
|
||||
|
||||
return attach_count;
|
||||
}
|
||||
|
||||
void
|
||||
pika_plug_in_progress_start (PikaPlugIn *plug_in,
|
||||
const gchar *message,
|
||||
PikaDisplay *display)
|
||||
{
|
||||
PikaPlugInProcFrame *proc_frame;
|
||||
|
||||
g_return_if_fail (PIKA_IS_PLUG_IN (plug_in));
|
||||
g_return_if_fail (display == NULL || PIKA_IS_DISPLAY (display));
|
||||
|
||||
proc_frame = pika_plug_in_get_proc_frame (plug_in);
|
||||
|
||||
if (! proc_frame->progress)
|
||||
{
|
||||
proc_frame->progress = pika_new_progress (plug_in->manager->pika,
|
||||
display);
|
||||
|
||||
if (proc_frame->progress)
|
||||
{
|
||||
proc_frame->progress_created = TRUE;
|
||||
|
||||
g_object_ref (proc_frame->progress);
|
||||
|
||||
pika_plug_in_progress_attach (proc_frame->progress);
|
||||
}
|
||||
}
|
||||
|
||||
if (proc_frame->progress)
|
||||
{
|
||||
if (! proc_frame->progress_cancel_id)
|
||||
{
|
||||
g_object_add_weak_pointer (G_OBJECT (proc_frame->progress),
|
||||
(gpointer) &proc_frame->progress);
|
||||
|
||||
proc_frame->progress_cancel_id =
|
||||
g_signal_connect (proc_frame->progress, "cancel",
|
||||
G_CALLBACK (pika_plug_in_progress_cancel_callback),
|
||||
plug_in);
|
||||
}
|
||||
|
||||
if (pika_progress_is_active (proc_frame->progress))
|
||||
{
|
||||
if (message)
|
||||
pika_progress_set_text_literal (proc_frame->progress, message);
|
||||
|
||||
if (pika_progress_get_value (proc_frame->progress) > 0.0)
|
||||
pika_progress_set_value (proc_frame->progress, 0.0);
|
||||
}
|
||||
else
|
||||
{
|
||||
pika_progress_start (proc_frame->progress, TRUE,
|
||||
"%s", message ? message : "");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
pika_plug_in_progress_end (PikaPlugIn *plug_in,
|
||||
PikaPlugInProcFrame *proc_frame)
|
||||
{
|
||||
g_return_if_fail (PIKA_IS_PLUG_IN (plug_in));
|
||||
g_return_if_fail (proc_frame != NULL);
|
||||
|
||||
if (proc_frame->progress)
|
||||
{
|
||||
if (proc_frame->progress_cancel_id)
|
||||
{
|
||||
g_signal_handler_disconnect (proc_frame->progress,
|
||||
proc_frame->progress_cancel_id);
|
||||
proc_frame->progress_cancel_id = 0;
|
||||
|
||||
g_object_remove_weak_pointer (G_OBJECT (proc_frame->progress),
|
||||
(gpointer) &proc_frame->progress);
|
||||
}
|
||||
|
||||
if (pika_plug_in_progress_detach (proc_frame->progress) < 1 &&
|
||||
pika_progress_is_active (proc_frame->progress))
|
||||
{
|
||||
pika_progress_end (proc_frame->progress);
|
||||
}
|
||||
|
||||
if (proc_frame->progress_created)
|
||||
{
|
||||
pika_free_progress (plug_in->manager->pika, proc_frame->progress);
|
||||
g_clear_object (&proc_frame->progress);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
pika_plug_in_progress_set_text (PikaPlugIn *plug_in,
|
||||
const gchar *message)
|
||||
{
|
||||
PikaPlugInProcFrame *proc_frame;
|
||||
|
||||
g_return_if_fail (PIKA_IS_PLUG_IN (plug_in));
|
||||
|
||||
proc_frame = pika_plug_in_get_proc_frame (plug_in);
|
||||
|
||||
if (proc_frame->progress)
|
||||
pika_progress_set_text_literal (proc_frame->progress, message);
|
||||
}
|
||||
|
||||
void
|
||||
pika_plug_in_progress_set_value (PikaPlugIn *plug_in,
|
||||
gdouble percentage)
|
||||
{
|
||||
PikaPlugInProcFrame *proc_frame;
|
||||
|
||||
g_return_if_fail (PIKA_IS_PLUG_IN (plug_in));
|
||||
|
||||
proc_frame = pika_plug_in_get_proc_frame (plug_in);
|
||||
|
||||
if (! proc_frame->progress ||
|
||||
! pika_progress_is_active (proc_frame->progress) ||
|
||||
! proc_frame->progress_cancel_id)
|
||||
{
|
||||
pika_plug_in_progress_start (plug_in, NULL, NULL);
|
||||
}
|
||||
|
||||
if (proc_frame->progress && pika_progress_is_active (proc_frame->progress))
|
||||
pika_progress_set_value (proc_frame->progress, percentage);
|
||||
}
|
||||
|
||||
void
|
||||
pika_plug_in_progress_pulse (PikaPlugIn *plug_in)
|
||||
{
|
||||
PikaPlugInProcFrame *proc_frame;
|
||||
|
||||
g_return_if_fail (PIKA_IS_PLUG_IN (plug_in));
|
||||
|
||||
proc_frame = pika_plug_in_get_proc_frame (plug_in);
|
||||
|
||||
if (! proc_frame->progress ||
|
||||
! pika_progress_is_active (proc_frame->progress) ||
|
||||
! proc_frame->progress_cancel_id)
|
||||
{
|
||||
pika_plug_in_progress_start (plug_in, NULL, NULL);
|
||||
}
|
||||
|
||||
if (proc_frame->progress && pika_progress_is_active (proc_frame->progress))
|
||||
pika_progress_pulse (proc_frame->progress);
|
||||
}
|
||||
|
||||
guint32
|
||||
pika_plug_in_progress_get_window_id (PikaPlugIn *plug_in)
|
||||
{
|
||||
PikaPlugInProcFrame *proc_frame;
|
||||
|
||||
g_return_val_if_fail (PIKA_IS_PLUG_IN (plug_in), 0);
|
||||
|
||||
proc_frame = pika_plug_in_get_proc_frame (plug_in);
|
||||
|
||||
if (proc_frame->progress)
|
||||
return pika_progress_get_window_id (proc_frame->progress);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
gboolean
|
||||
pika_plug_in_progress_install (PikaPlugIn *plug_in,
|
||||
const gchar *progress_callback)
|
||||
{
|
||||
PikaPlugInProcFrame *proc_frame;
|
||||
PikaProcedure *procedure;
|
||||
|
||||
g_return_val_if_fail (PIKA_IS_PLUG_IN (plug_in), FALSE);
|
||||
g_return_val_if_fail (progress_callback != NULL, FALSE);
|
||||
|
||||
procedure = pika_pdb_lookup_procedure (plug_in->manager->pika->pdb,
|
||||
progress_callback);
|
||||
|
||||
if (! PIKA_IS_TEMPORARY_PROCEDURE (procedure) ||
|
||||
PIKA_TEMPORARY_PROCEDURE (procedure)->plug_in != plug_in ||
|
||||
procedure->num_args != 3 ||
|
||||
! G_IS_PARAM_SPEC_INT (procedure->args[0]) ||
|
||||
! G_IS_PARAM_SPEC_STRING (procedure->args[1]) ||
|
||||
! G_IS_PARAM_SPEC_DOUBLE (procedure->args[2]))
|
||||
{
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
proc_frame = pika_plug_in_get_proc_frame (plug_in);
|
||||
|
||||
if (proc_frame->progress)
|
||||
{
|
||||
pika_plug_in_progress_end (plug_in, proc_frame);
|
||||
|
||||
g_clear_object (&proc_frame->progress);
|
||||
}
|
||||
|
||||
proc_frame->progress = g_object_new (PIKA_TYPE_PDB_PROGRESS,
|
||||
"pdb", plug_in->manager->pika->pdb,
|
||||
"context", proc_frame->main_context,
|
||||
"callback-name", progress_callback,
|
||||
NULL);
|
||||
|
||||
pika_plug_in_progress_attach (proc_frame->progress);
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
gboolean
|
||||
pika_plug_in_progress_uninstall (PikaPlugIn *plug_in,
|
||||
const gchar *progress_callback)
|
||||
{
|
||||
PikaPlugInProcFrame *proc_frame;
|
||||
|
||||
g_return_val_if_fail (PIKA_IS_PLUG_IN (plug_in), FALSE);
|
||||
g_return_val_if_fail (progress_callback != NULL, FALSE);
|
||||
|
||||
proc_frame = pika_plug_in_get_proc_frame (plug_in);
|
||||
|
||||
if (PIKA_IS_PDB_PROGRESS (proc_frame->progress))
|
||||
{
|
||||
pika_plug_in_progress_end (plug_in, proc_frame);
|
||||
|
||||
g_clear_object (&proc_frame->progress);
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
gboolean
|
||||
pika_plug_in_progress_cancel (PikaPlugIn *plug_in,
|
||||
const gchar *progress_callback)
|
||||
{
|
||||
g_return_val_if_fail (PIKA_IS_PLUG_IN (plug_in), FALSE);
|
||||
g_return_val_if_fail (progress_callback != NULL, FALSE);
|
||||
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
|
||||
/* private functions */
|
||||
|
||||
static PikaValueArray *
|
||||
get_cancel_return_values (PikaProcedure *procedure)
|
||||
{
|
||||
PikaValueArray *return_vals;
|
||||
GError *error;
|
||||
|
||||
error = g_error_new_literal (PIKA_PDB_ERROR, PIKA_PDB_ERROR_CANCELLED,
|
||||
_("Cancelled"));
|
||||
return_vals = pika_procedure_get_return_values (procedure, FALSE, error);
|
||||
g_error_free (error);
|
||||
|
||||
return return_vals;
|
||||
}
|
||||
|
||||
static void
|
||||
pika_plug_in_progress_cancel_callback (PikaProgress *progress,
|
||||
PikaPlugIn *plug_in)
|
||||
{
|
||||
PikaPlugInProcFrame *proc_frame = &plug_in->main_proc_frame;
|
||||
GList *list;
|
||||
|
||||
if (proc_frame->main_loop)
|
||||
{
|
||||
proc_frame->return_vals =
|
||||
get_cancel_return_values (proc_frame->procedure);
|
||||
}
|
||||
|
||||
for (list = plug_in->temp_proc_frames; list; list = g_list_next (list))
|
||||
{
|
||||
proc_frame = list->data;
|
||||
|
||||
if (proc_frame->main_loop)
|
||||
{
|
||||
proc_frame->return_vals =
|
||||
get_cancel_return_values (proc_frame->procedure);
|
||||
}
|
||||
}
|
||||
|
||||
pika_plug_in_close (plug_in, TRUE);
|
||||
}
|
51
app/plug-in/pikaplugin-progress.h
Normal file
51
app/plug-in/pikaplugin-progress.h
Normal file
@ -0,0 +1,51 @@
|
||||
/* PIKA - Photo and Image Kooker Application
|
||||
* a rebranding of The GNU Image Manipulation Program (created with heckimp)
|
||||
* A derived work which may be trivial. However, any changes may be (C)2023 by Aldercone Studio
|
||||
*
|
||||
* Original copyright, applying to most contents (license remains unchanged):
|
||||
* Copyright (C) 1995 Spencer Kimball and Peter Mattis
|
||||
*
|
||||
* pikaplugin-progress.h
|
||||
*
|
||||
* 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 3 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, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#ifndef __PIKA_PLUG_IN_PROGRESS_H__
|
||||
#define __PIKA_PLUG_IN_PROGRESS_H__
|
||||
|
||||
|
||||
gint pika_plug_in_progress_attach (PikaProgress *progress);
|
||||
gint pika_plug_in_progress_detach (PikaProgress *progress);
|
||||
|
||||
void pika_plug_in_progress_start (PikaPlugIn *plug_in,
|
||||
const gchar *message,
|
||||
PikaDisplay *display);
|
||||
void pika_plug_in_progress_end (PikaPlugIn *plug_in,
|
||||
PikaPlugInProcFrame *proc_frame);
|
||||
void pika_plug_in_progress_set_text (PikaPlugIn *plug_in,
|
||||
const gchar *message);
|
||||
void pika_plug_in_progress_set_value (PikaPlugIn *plug_in,
|
||||
gdouble percentage);
|
||||
void pika_plug_in_progress_pulse (PikaPlugIn *plug_in);
|
||||
guint32 pika_plug_in_progress_get_window_id (PikaPlugIn *plug_in);
|
||||
|
||||
gboolean pika_plug_in_progress_install (PikaPlugIn *plug_in,
|
||||
const gchar *progress_callback);
|
||||
gboolean pika_plug_in_progress_uninstall (PikaPlugIn *plug_in,
|
||||
const gchar *progress_callback);
|
||||
gboolean pika_plug_in_progress_cancel (PikaPlugIn *plug_in,
|
||||
const gchar *progress_callback);
|
||||
|
||||
|
||||
#endif /* __PIKA_PLUG_IN_PROGRESS_H__ */
|
990
app/plug-in/pikaplugin.c
Normal file
990
app/plug-in/pikaplugin.c
Normal file
@ -0,0 +1,990 @@
|
||||
/* PIKA - Photo and Image Kooker Application
|
||||
* a rebranding of The GNU Image Manipulation Program (created with heckimp)
|
||||
* A derived work which may be trivial. However, any changes may be (C)2023 by Aldercone Studio
|
||||
*
|
||||
* Original copyright, applying to most contents (license remains unchanged):
|
||||
* Copyright (C) 1995 Spencer Kimball and Peter Mattis
|
||||
*
|
||||
* pikaplugin.c
|
||||
*
|
||||
* 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 3 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, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include "config.h"
|
||||
|
||||
#ifndef _WIN32
|
||||
#define _GNU_SOURCE
|
||||
#endif
|
||||
|
||||
#include <errno.h>
|
||||
#include <signal.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
#ifdef HAVE_UNISTD_H
|
||||
#include <unistd.h>
|
||||
#endif
|
||||
|
||||
#ifdef HAVE_SYS_WAIT_H
|
||||
#include <sys/wait.h>
|
||||
#endif
|
||||
|
||||
#ifdef HAVE_SYS_PARAM_H
|
||||
#include <sys/param.h>
|
||||
#endif
|
||||
|
||||
#include <gdk-pixbuf/gdk-pixbuf.h>
|
||||
#include <gegl.h>
|
||||
|
||||
#if defined(G_OS_WIN32) || defined(G_WITH_CYGWIN)
|
||||
|
||||
#define STRICT
|
||||
#include <windows.h>
|
||||
#include <process.h>
|
||||
|
||||
#ifdef G_OS_WIN32
|
||||
#include <fcntl.h>
|
||||
#include <io.h>
|
||||
|
||||
#ifndef pipe
|
||||
#define pipe(fds) _pipe(fds, 4096, _O_BINARY)
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
||||
#ifdef G_WITH_CYGWIN
|
||||
#define O_TEXT 0x0100 /* text file */
|
||||
#define _O_TEXT 0x0100 /* text file */
|
||||
#define O_BINARY 0x0200 /* binary file */
|
||||
#define _O_BINARY 0x0200 /* binary file */
|
||||
#endif
|
||||
|
||||
#endif /* G_OS_WIN32 || G_WITH_CYGWIN */
|
||||
|
||||
#include "libpikabase/pikabase.h"
|
||||
#include "libpikabase/pikaprotocol.h"
|
||||
#include "libpikabase/pikawire.h"
|
||||
|
||||
#include "plug-in-types.h"
|
||||
|
||||
#include "core/pika.h"
|
||||
#include "core/pika-spawn.h"
|
||||
#include "core/pikaprogress.h"
|
||||
|
||||
#include "pdb/pikapdbcontext.h"
|
||||
|
||||
#include "pikaenvirontable.h"
|
||||
#include "pikainterpreterdb.h"
|
||||
#include "pikaplugin.h"
|
||||
#include "pikaplugin-message.h"
|
||||
#include "pikaplugin-progress.h"
|
||||
#include "pikaplugindebug.h"
|
||||
#include "pikaplugindef.h"
|
||||
#include "pikapluginmanager.h"
|
||||
#include "pikapluginmanager-help-domain.h"
|
||||
#include "pikatemporaryprocedure.h"
|
||||
|
||||
#include "pika-intl.h"
|
||||
|
||||
|
||||
static void pika_plug_in_finalize (GObject *object);
|
||||
|
||||
static gboolean pika_plug_in_recv_message (GIOChannel *channel,
|
||||
GIOCondition cond,
|
||||
gpointer data);
|
||||
static gboolean pika_plug_in_write (GIOChannel *channel,
|
||||
const guint8 *buf,
|
||||
gulong count,
|
||||
gpointer data);
|
||||
static gboolean pika_plug_in_flush (GIOChannel *channel,
|
||||
gpointer data);
|
||||
|
||||
#if defined G_OS_WIN32 && defined WIN32_32BIT_DLL_FOLDER
|
||||
static void pika_plug_in_set_dll_directory (const gchar *path);
|
||||
#endif
|
||||
|
||||
#ifndef G_OS_WIN32
|
||||
static void pika_plug_in_close_waitpid (GPid pid,
|
||||
gint status,
|
||||
PikaPlugIn *plug_in);
|
||||
#endif
|
||||
|
||||
|
||||
G_DEFINE_TYPE (PikaPlugIn, pika_plug_in, PIKA_TYPE_OBJECT)
|
||||
|
||||
#define parent_class pika_plug_in_parent_class
|
||||
|
||||
|
||||
static void
|
||||
pika_plug_in_class_init (PikaPlugInClass *klass)
|
||||
{
|
||||
GObjectClass *object_class = G_OBJECT_CLASS (klass);
|
||||
|
||||
object_class->finalize = pika_plug_in_finalize;
|
||||
|
||||
/* initialize the pika protocol library and set the read and
|
||||
* write handlers.
|
||||
*/
|
||||
gp_init ();
|
||||
pika_wire_set_writer (pika_plug_in_write);
|
||||
pika_wire_set_flusher (pika_plug_in_flush);
|
||||
}
|
||||
|
||||
static void
|
||||
pika_plug_in_init (PikaPlugIn *plug_in)
|
||||
{
|
||||
plug_in->manager = NULL;
|
||||
plug_in->file = NULL;
|
||||
|
||||
plug_in->call_mode = PIKA_PLUG_IN_CALL_NONE;
|
||||
plug_in->open = FALSE;
|
||||
plug_in->hup = FALSE;
|
||||
plug_in->pid = 0;
|
||||
|
||||
plug_in->my_read = NULL;
|
||||
plug_in->my_write = NULL;
|
||||
plug_in->his_read = NULL;
|
||||
plug_in->his_write = NULL;
|
||||
|
||||
plug_in->input_id = 0;
|
||||
plug_in->write_buffer_index = 0;
|
||||
|
||||
plug_in->temp_procedures = NULL;
|
||||
|
||||
plug_in->ext_main_loop = NULL;
|
||||
|
||||
plug_in->temp_proc_frames = NULL;
|
||||
|
||||
plug_in->plug_in_def = NULL;
|
||||
}
|
||||
|
||||
static void
|
||||
pika_plug_in_finalize (GObject *object)
|
||||
{
|
||||
PikaPlugIn *plug_in = PIKA_PLUG_IN (object);
|
||||
|
||||
g_clear_object (&plug_in->file);
|
||||
|
||||
pika_plug_in_proc_frame_dispose (&plug_in->main_proc_frame, plug_in);
|
||||
|
||||
G_OBJECT_CLASS (parent_class)->finalize (object);
|
||||
}
|
||||
|
||||
static gboolean
|
||||
pika_plug_in_recv_message (GIOChannel *channel,
|
||||
GIOCondition cond,
|
||||
gpointer data)
|
||||
{
|
||||
PikaPlugIn *plug_in = data;
|
||||
gboolean got_message = FALSE;
|
||||
|
||||
#ifdef G_OS_WIN32
|
||||
/* Workaround for GLib bug #137968: sometimes we are called for no
|
||||
* reason...
|
||||
*/
|
||||
if (cond == 0)
|
||||
return TRUE;
|
||||
#endif
|
||||
|
||||
if (plug_in->my_read == NULL)
|
||||
return TRUE;
|
||||
|
||||
g_object_ref (plug_in);
|
||||
|
||||
if (cond & (G_IO_IN | G_IO_PRI))
|
||||
{
|
||||
PikaWireMessage msg;
|
||||
|
||||
memset (&msg, 0, sizeof (PikaWireMessage));
|
||||
|
||||
if (! pika_wire_read_msg (plug_in->my_read, &msg, plug_in))
|
||||
{
|
||||
pika_plug_in_close (plug_in, TRUE);
|
||||
}
|
||||
else
|
||||
{
|
||||
pika_plug_in_handle_message (plug_in, &msg);
|
||||
pika_wire_destroy (&msg);
|
||||
got_message = TRUE;
|
||||
}
|
||||
}
|
||||
|
||||
if (cond & (G_IO_ERR | G_IO_HUP))
|
||||
{
|
||||
if (cond & G_IO_HUP)
|
||||
plug_in->hup = TRUE;
|
||||
|
||||
if (plug_in->open)
|
||||
pika_plug_in_close (plug_in, TRUE);
|
||||
}
|
||||
|
||||
if (! got_message)
|
||||
{
|
||||
PikaPlugInProcFrame *frame = pika_plug_in_get_proc_frame (plug_in);
|
||||
PikaProgress *progress = frame ? frame->progress : NULL;
|
||||
|
||||
pika_message (plug_in->manager->pika, G_OBJECT (progress),
|
||||
PIKA_MESSAGE_ERROR,
|
||||
_("Plug-in crashed: \"%s\"\n(%s)\n\n"
|
||||
"The dying plug-in may have messed up PIKA's internal "
|
||||
"state. You may want to save your images and restart "
|
||||
"PIKA to be on the safe side."),
|
||||
pika_object_get_name (plug_in),
|
||||
pika_file_get_utf8_name (plug_in->file));
|
||||
}
|
||||
|
||||
g_object_unref (plug_in);
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static gboolean
|
||||
pika_plug_in_write (GIOChannel *channel,
|
||||
const guint8 *buf,
|
||||
gulong count,
|
||||
gpointer data)
|
||||
{
|
||||
PikaPlugIn *plug_in = data;
|
||||
gulong bytes;
|
||||
|
||||
while (count > 0)
|
||||
{
|
||||
if ((plug_in->write_buffer_index + count) >= WRITE_BUFFER_SIZE)
|
||||
{
|
||||
bytes = WRITE_BUFFER_SIZE - plug_in->write_buffer_index;
|
||||
memcpy (&plug_in->write_buffer[plug_in->write_buffer_index],
|
||||
buf, bytes);
|
||||
plug_in->write_buffer_index += bytes;
|
||||
if (! pika_wire_flush (channel, plug_in))
|
||||
return FALSE;
|
||||
}
|
||||
else
|
||||
{
|
||||
bytes = count;
|
||||
memcpy (&plug_in->write_buffer[plug_in->write_buffer_index],
|
||||
buf, bytes);
|
||||
plug_in->write_buffer_index += bytes;
|
||||
}
|
||||
|
||||
buf += bytes;
|
||||
count -= bytes;
|
||||
}
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static gboolean
|
||||
pika_plug_in_flush (GIOChannel *channel,
|
||||
gpointer data)
|
||||
{
|
||||
PikaPlugIn *plug_in = data;
|
||||
|
||||
if (plug_in->write_buffer_index > 0)
|
||||
{
|
||||
GIOStatus status;
|
||||
GError *error = NULL;
|
||||
gint count;
|
||||
gsize bytes;
|
||||
|
||||
count = 0;
|
||||
while (count != plug_in->write_buffer_index)
|
||||
{
|
||||
do
|
||||
{
|
||||
bytes = 0;
|
||||
status = g_io_channel_write_chars (channel,
|
||||
&plug_in->write_buffer[count],
|
||||
(plug_in->write_buffer_index - count),
|
||||
&bytes,
|
||||
&error);
|
||||
}
|
||||
while (status == G_IO_STATUS_AGAIN);
|
||||
|
||||
if (status != G_IO_STATUS_NORMAL)
|
||||
{
|
||||
if (error)
|
||||
{
|
||||
g_warning ("%s: plug_in_flush(): error: %s",
|
||||
pika_filename_to_utf8 (g_get_prgname ()),
|
||||
error->message);
|
||||
g_error_free (error);
|
||||
}
|
||||
else
|
||||
{
|
||||
g_warning ("%s: plug_in_flush(): error",
|
||||
pika_filename_to_utf8 (g_get_prgname ()));
|
||||
}
|
||||
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
count += bytes;
|
||||
}
|
||||
|
||||
plug_in->write_buffer_index = 0;
|
||||
}
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
#if defined G_OS_WIN32 && defined WIN32_32BIT_DLL_FOLDER
|
||||
static void
|
||||
pika_plug_in_set_dll_directory (const gchar *path)
|
||||
{
|
||||
LPWSTR w_path;
|
||||
const gchar *install_dir;
|
||||
gchar *bin_dir;
|
||||
LPWSTR w_bin_dir;
|
||||
DWORD BinaryType;
|
||||
|
||||
w_path = NULL;
|
||||
w_bin_dir = NULL;
|
||||
install_dir = pika_installation_directory ();
|
||||
if (path &&
|
||||
(w_path = g_utf8_to_utf16 (path, -1, NULL, NULL, NULL)) &&
|
||||
GetBinaryTypeW (w_path, &BinaryType) &&
|
||||
BinaryType == SCS_32BIT_BINARY)
|
||||
bin_dir = g_build_filename (install_dir, WIN32_32BIT_DLL_FOLDER, NULL);
|
||||
else
|
||||
bin_dir = g_build_filename (install_dir, "bin", NULL);
|
||||
|
||||
w_bin_dir = g_utf8_to_utf16 (bin_dir, -1, NULL, NULL, NULL);
|
||||
if (w_bin_dir)
|
||||
{
|
||||
SetDllDirectoryW (w_bin_dir);
|
||||
g_free (w_bin_dir);
|
||||
}
|
||||
|
||||
g_free (bin_dir);
|
||||
g_free (w_path);
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifndef G_OS_WIN32
|
||||
static void
|
||||
pika_plug_in_close_waitpid (GPid pid,
|
||||
gint status,
|
||||
PikaPlugIn *plug_in)
|
||||
{
|
||||
GError *error = NULL;
|
||||
|
||||
if (plug_in->manager->pika->be_verbose &&
|
||||
! g_spawn_check_wait_status (status, &error))
|
||||
{
|
||||
g_printerr ("Process for plug-in '%s' terminated with error: %s\n",
|
||||
pika_object_get_name (plug_in),
|
||||
error->message);
|
||||
}
|
||||
g_clear_error (&error);
|
||||
|
||||
g_spawn_close_pid (pid);
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
/* public functions */
|
||||
|
||||
PikaPlugIn *
|
||||
pika_plug_in_new (PikaPlugInManager *manager,
|
||||
PikaContext *context,
|
||||
PikaProgress *progress,
|
||||
PikaPlugInProcedure *procedure,
|
||||
GFile *file)
|
||||
{
|
||||
PikaPlugIn *plug_in;
|
||||
|
||||
g_return_val_if_fail (PIKA_IS_PLUG_IN_MANAGER (manager), NULL);
|
||||
g_return_val_if_fail (PIKA_IS_PDB_CONTEXT (context), NULL);
|
||||
g_return_val_if_fail (progress == NULL || PIKA_IS_PROGRESS (progress), NULL);
|
||||
g_return_val_if_fail (procedure == NULL ||
|
||||
PIKA_IS_PLUG_IN_PROCEDURE (procedure), NULL);
|
||||
g_return_val_if_fail (file == NULL || G_IS_FILE (file), NULL);
|
||||
g_return_val_if_fail ((procedure != NULL || file != NULL) &&
|
||||
! (procedure != NULL && file != NULL), NULL);
|
||||
|
||||
plug_in = g_object_new (PIKA_TYPE_PLUG_IN, NULL);
|
||||
|
||||
if (! file)
|
||||
file = pika_plug_in_procedure_get_file (procedure);
|
||||
|
||||
pika_object_take_name (PIKA_OBJECT (plug_in),
|
||||
g_path_get_basename (pika_file_get_utf8_name (file)));
|
||||
|
||||
plug_in->manager = manager;
|
||||
plug_in->file = g_object_ref (file);
|
||||
|
||||
pika_plug_in_proc_frame_init (&plug_in->main_proc_frame,
|
||||
context, progress, procedure);
|
||||
|
||||
return plug_in;
|
||||
}
|
||||
|
||||
gboolean
|
||||
pika_plug_in_open (PikaPlugIn *plug_in,
|
||||
PikaPlugInCallMode call_mode,
|
||||
gboolean synchronous)
|
||||
{
|
||||
gchar *progname;
|
||||
gint my_read[2];
|
||||
gint my_write[2];
|
||||
gchar **envp;
|
||||
const gchar *args[10];
|
||||
gchar **argv;
|
||||
gint argc;
|
||||
gchar protocol_version[8];
|
||||
gchar *interp, *interp_arg;
|
||||
gchar *his_read_fd, *his_write_fd;
|
||||
const gchar *mode;
|
||||
gchar *stm;
|
||||
GError *error = NULL;
|
||||
gboolean debug;
|
||||
guint debug_flag;
|
||||
guint spawn_flags;
|
||||
|
||||
g_return_val_if_fail (PIKA_IS_PLUG_IN (plug_in), FALSE);
|
||||
g_return_val_if_fail (plug_in->call_mode == PIKA_PLUG_IN_CALL_NONE, FALSE);
|
||||
|
||||
/* Open two pipes. (Bidirectional communication).
|
||||
*/
|
||||
if ((pipe (my_read) == -1) || (pipe (my_write) == -1))
|
||||
{
|
||||
pika_message (plug_in->manager->pika, NULL, PIKA_MESSAGE_ERROR,
|
||||
"Unable to run plug-in \"%s\"\n(%s)\n\npipe() failed: %s",
|
||||
pika_object_get_name (plug_in),
|
||||
pika_file_get_utf8_name (plug_in->file),
|
||||
g_strerror (errno));
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
#if defined(G_WITH_CYGWIN)
|
||||
/* Set to binary mode */
|
||||
setmode (my_read[0], _O_BINARY);
|
||||
setmode (my_write[0], _O_BINARY);
|
||||
setmode (my_read[1], _O_BINARY);
|
||||
setmode (my_write[1], _O_BINARY);
|
||||
#endif
|
||||
|
||||
/* Prevent the plug-in from inheriting our end of the pipes */
|
||||
pika_spawn_set_cloexec (my_read[0]);
|
||||
pika_spawn_set_cloexec (my_write[1]);
|
||||
|
||||
#ifdef G_OS_WIN32
|
||||
plug_in->my_read = g_io_channel_win32_new_fd (my_read[0]);
|
||||
plug_in->my_write = g_io_channel_win32_new_fd (my_write[1]);
|
||||
plug_in->his_read = g_io_channel_win32_new_fd (my_write[0]);
|
||||
plug_in->his_write = g_io_channel_win32_new_fd (my_read[1]);
|
||||
#else
|
||||
plug_in->my_read = g_io_channel_unix_new (my_read[0]);
|
||||
plug_in->my_write = g_io_channel_unix_new (my_write[1]);
|
||||
plug_in->his_read = g_io_channel_unix_new (my_write[0]);
|
||||
plug_in->his_write = g_io_channel_unix_new (my_read[1]);
|
||||
#endif
|
||||
|
||||
g_io_channel_set_encoding (plug_in->my_read, NULL, NULL);
|
||||
g_io_channel_set_encoding (plug_in->my_write, NULL, NULL);
|
||||
g_io_channel_set_encoding (plug_in->his_read, NULL, NULL);
|
||||
g_io_channel_set_encoding (plug_in->his_write, NULL, NULL);
|
||||
|
||||
g_io_channel_set_buffered (plug_in->my_read, FALSE);
|
||||
g_io_channel_set_buffered (plug_in->my_write, FALSE);
|
||||
g_io_channel_set_buffered (plug_in->his_read, FALSE);
|
||||
g_io_channel_set_buffered (plug_in->his_write, FALSE);
|
||||
|
||||
g_io_channel_set_close_on_unref (plug_in->my_read, TRUE);
|
||||
g_io_channel_set_close_on_unref (plug_in->my_write, TRUE);
|
||||
g_io_channel_set_close_on_unref (plug_in->his_read, TRUE);
|
||||
g_io_channel_set_close_on_unref (plug_in->his_write, TRUE);
|
||||
|
||||
/* Remember the file descriptors for the pipes.
|
||||
*/
|
||||
his_read_fd = g_strdup_printf ("%d",
|
||||
g_io_channel_unix_get_fd (plug_in->his_read));
|
||||
his_write_fd = g_strdup_printf ("%d",
|
||||
g_io_channel_unix_get_fd (plug_in->his_write));
|
||||
|
||||
switch (call_mode)
|
||||
{
|
||||
case PIKA_PLUG_IN_CALL_QUERY:
|
||||
mode = "-query";
|
||||
debug_flag = PIKA_DEBUG_WRAP_QUERY;
|
||||
break;
|
||||
|
||||
case PIKA_PLUG_IN_CALL_INIT:
|
||||
mode = "-init";
|
||||
debug_flag = PIKA_DEBUG_WRAP_INIT;
|
||||
break;
|
||||
|
||||
case PIKA_PLUG_IN_CALL_RUN:
|
||||
mode = "-run";
|
||||
debug_flag = PIKA_DEBUG_WRAP_RUN;
|
||||
break;
|
||||
|
||||
default:
|
||||
pika_assert_not_reached ();
|
||||
}
|
||||
|
||||
stm = g_strdup_printf ("%d", plug_in->manager->pika->stack_trace_mode);
|
||||
|
||||
progname = g_file_get_path (plug_in->file);
|
||||
|
||||
interp = pika_interpreter_db_resolve (plug_in->manager->interpreter_db,
|
||||
progname, &interp_arg);
|
||||
|
||||
argc = 0;
|
||||
|
||||
if (interp)
|
||||
args[argc++] = interp;
|
||||
|
||||
if (interp_arg)
|
||||
args[argc++] = interp_arg;
|
||||
|
||||
g_snprintf (protocol_version, sizeof (protocol_version),
|
||||
"%d", PIKA_PROTOCOL_VERSION);
|
||||
|
||||
args[argc++] = progname;
|
||||
args[argc++] = "-pika";
|
||||
args[argc++] = protocol_version;
|
||||
args[argc++] = his_read_fd;
|
||||
args[argc++] = his_write_fd;
|
||||
args[argc++] = mode;
|
||||
args[argc++] = stm;
|
||||
args[argc++] = NULL;
|
||||
|
||||
argv = (gchar **) args;
|
||||
envp = pika_environ_table_get_envp (plug_in->manager->environ_table);
|
||||
spawn_flags = (G_SPAWN_LEAVE_DESCRIPTORS_OPEN |
|
||||
G_SPAWN_DO_NOT_REAP_CHILD |
|
||||
G_SPAWN_CHILD_INHERITS_STDIN);
|
||||
|
||||
debug = FALSE;
|
||||
|
||||
if (plug_in->manager->debug)
|
||||
{
|
||||
gchar **debug_argv = pika_plug_in_debug_argv (plug_in->manager->debug,
|
||||
progname,
|
||||
debug_flag, args);
|
||||
|
||||
if (debug_argv)
|
||||
{
|
||||
debug = TRUE;
|
||||
argv = debug_argv;
|
||||
spawn_flags |= G_SPAWN_SEARCH_PATH;
|
||||
}
|
||||
}
|
||||
|
||||
/* Fork another process. We'll remember the process id so that we
|
||||
* can later use it to kill the filter if necessary.
|
||||
*/
|
||||
#if defined G_OS_WIN32 && defined WIN32_32BIT_DLL_FOLDER
|
||||
pika_plug_in_set_dll_directory (argv[0]);
|
||||
#endif
|
||||
if (! pika_spawn_async (argv, envp, spawn_flags, &plug_in->pid, &error))
|
||||
{
|
||||
pika_message (plug_in->manager->pika, NULL, PIKA_MESSAGE_ERROR,
|
||||
"Unable to run plug-in \"%s\"\n(%s)\n\n%s",
|
||||
pika_object_get_name (plug_in),
|
||||
pika_file_get_utf8_name (plug_in->file),
|
||||
error->message);
|
||||
g_clear_error (&error);
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
g_clear_pointer (&plug_in->his_read, g_io_channel_unref);
|
||||
g_clear_pointer (&plug_in->his_write, g_io_channel_unref);
|
||||
|
||||
if (! synchronous)
|
||||
{
|
||||
GSource *source;
|
||||
|
||||
source = g_io_create_watch (plug_in->my_read,
|
||||
G_IO_IN | G_IO_PRI | G_IO_ERR | G_IO_HUP);
|
||||
|
||||
g_source_set_callback (source,
|
||||
(GSourceFunc) pika_plug_in_recv_message, plug_in,
|
||||
NULL);
|
||||
|
||||
g_source_set_can_recurse (source, TRUE);
|
||||
|
||||
plug_in->input_id = g_source_attach (source, NULL);
|
||||
g_source_unref (source);
|
||||
}
|
||||
|
||||
plug_in->open = TRUE;
|
||||
plug_in->call_mode = call_mode;
|
||||
|
||||
pika_plug_in_manager_add_open_plug_in (plug_in->manager, plug_in);
|
||||
|
||||
cleanup:
|
||||
|
||||
#if defined G_OS_WIN32 && defined WIN32_32BIT_DLL_FOLDER
|
||||
pika_plug_in_set_dll_directory (NULL);
|
||||
#endif
|
||||
|
||||
if (debug)
|
||||
g_free (argv);
|
||||
|
||||
g_free (his_read_fd);
|
||||
g_free (his_write_fd);
|
||||
g_free (stm);
|
||||
g_free (interp);
|
||||
g_free (interp_arg);
|
||||
g_free (progname);
|
||||
|
||||
return plug_in->open;
|
||||
}
|
||||
|
||||
void
|
||||
pika_plug_in_close (PikaPlugIn *plug_in,
|
||||
gboolean kill_it)
|
||||
{
|
||||
g_return_if_fail (PIKA_IS_PLUG_IN (plug_in));
|
||||
g_return_if_fail (plug_in->open);
|
||||
|
||||
plug_in->open = FALSE;
|
||||
|
||||
if (plug_in->pid)
|
||||
{
|
||||
#ifndef G_OS_WIN32
|
||||
gint status;
|
||||
#endif
|
||||
|
||||
/* Ask the filter to exit gracefully,
|
||||
but not if it is closed because of a broken pipe. */
|
||||
if (kill_it && ! plug_in->hup)
|
||||
{
|
||||
gp_quit_write (plug_in->my_write, plug_in);
|
||||
|
||||
/* give the plug-in some time (10 ms) */
|
||||
g_usleep (10000);
|
||||
}
|
||||
|
||||
/* If necessary, kill the filter. */
|
||||
|
||||
#ifndef G_OS_WIN32
|
||||
|
||||
if (kill_it)
|
||||
{
|
||||
if (plug_in->manager->pika->be_verbose)
|
||||
g_print ("Terminating plug-in: '%s'\n",
|
||||
pika_file_get_utf8_name (plug_in->file));
|
||||
|
||||
/* If the plug-in opened a process group, kill the group instead
|
||||
* of only the plug-in, so we kill the plug-in's children too
|
||||
*/
|
||||
if (getpgid (0) != getpgid (plug_in->pid))
|
||||
status = kill (- plug_in->pid, SIGKILL);
|
||||
else
|
||||
status = kill (plug_in->pid, SIGKILL);
|
||||
|
||||
/* Wait for the process to exit. This will happen
|
||||
* immediately as it was just killed.
|
||||
*/
|
||||
waitpid (plug_in->pid, &status, 0);
|
||||
}
|
||||
else
|
||||
{
|
||||
/*
|
||||
* If we don't kill it, it means the plug-in ended normally
|
||||
* hence its process should just return without problem. And
|
||||
* this is the case nearly all the time. Yet I had this one
|
||||
* case where the process would never return (even though the
|
||||
* plug-in returned with a result and no errors) and a
|
||||
* waitpid() would block the main process forever.
|
||||
* Thus use instead a child watch source. My idea was that in
|
||||
* the rare case when the child process doesn't return, it is
|
||||
* better to leave a zombie than freeze the core. As it turns
|
||||
* out, doing this even made the broken process exit (does
|
||||
* g_child_watch_add_full() do something better than
|
||||
* waitpid()?).
|
||||
*/
|
||||
g_object_ref (plug_in);
|
||||
g_child_watch_add_full (G_PRIORITY_LOW, plug_in->pid,
|
||||
(GChildWatchFunc) pika_plug_in_close_waitpid,
|
||||
plug_in, (GDestroyNotify) g_object_unref);
|
||||
}
|
||||
|
||||
#else /* G_OS_WIN32 */
|
||||
|
||||
if (kill_it)
|
||||
{
|
||||
/* Trying to avoid TerminateProcess (does mostly work).
|
||||
* Otherwise some of our needed DLLs may get into an
|
||||
* unstable state (see Win32 API docs).
|
||||
*/
|
||||
DWORD dwExitCode = STILL_ACTIVE;
|
||||
DWORD dwTries = 10;
|
||||
|
||||
while (dwExitCode == STILL_ACTIVE &&
|
||||
GetExitCodeProcess ((HANDLE) plug_in->pid, &dwExitCode) &&
|
||||
(dwTries > 0))
|
||||
{
|
||||
Sleep (10);
|
||||
dwTries--;
|
||||
}
|
||||
|
||||
if (dwExitCode == STILL_ACTIVE)
|
||||
{
|
||||
if (plug_in->manager->pika->be_verbose)
|
||||
g_print ("Terminating plug-in: '%s'\n",
|
||||
pika_file_get_utf8_name (plug_in->file));
|
||||
|
||||
TerminateProcess ((HANDLE) plug_in->pid, 0);
|
||||
}
|
||||
}
|
||||
|
||||
g_spawn_close_pid (plug_in->pid);
|
||||
#endif /* G_OS_WIN32 */
|
||||
|
||||
plug_in->pid = 0;
|
||||
}
|
||||
|
||||
/* Remove the input handler. */
|
||||
if (plug_in->input_id)
|
||||
{
|
||||
g_source_remove (plug_in->input_id);
|
||||
plug_in->input_id = 0;
|
||||
}
|
||||
|
||||
/* Close the pipes. */
|
||||
g_clear_pointer (&plug_in->my_read, g_io_channel_unref);
|
||||
g_clear_pointer (&plug_in->my_write, g_io_channel_unref);
|
||||
g_clear_pointer (&plug_in->his_read, g_io_channel_unref);
|
||||
g_clear_pointer (&plug_in->his_write, g_io_channel_unref);
|
||||
|
||||
pika_wire_clear_error ();
|
||||
|
||||
while (plug_in->temp_proc_frames)
|
||||
{
|
||||
PikaPlugInProcFrame *proc_frame = plug_in->temp_proc_frames->data;
|
||||
|
||||
#ifdef PIKA_UNSTABLE
|
||||
g_printerr ("plug-in '%s' aborted before sending its "
|
||||
"temporary procedure return values\n",
|
||||
pika_object_get_name (plug_in));
|
||||
#endif
|
||||
|
||||
if (proc_frame->main_loop &&
|
||||
g_main_loop_is_running (proc_frame->main_loop))
|
||||
{
|
||||
g_main_loop_quit (proc_frame->main_loop);
|
||||
}
|
||||
|
||||
/* pop the frame here, because normally this only happens in
|
||||
* pika_plug_in_handle_temp_proc_return(), which can't
|
||||
* be called after plug_in_close()
|
||||
*/
|
||||
pika_plug_in_proc_frame_pop (plug_in);
|
||||
}
|
||||
|
||||
if (plug_in->main_proc_frame.main_loop &&
|
||||
g_main_loop_is_running (plug_in->main_proc_frame.main_loop))
|
||||
{
|
||||
#ifdef PIKA_UNSTABLE
|
||||
g_printerr ("plug-in '%s' aborted before sending its "
|
||||
"procedure return values\n",
|
||||
pika_object_get_name (plug_in));
|
||||
#endif
|
||||
|
||||
g_main_loop_quit (plug_in->main_proc_frame.main_loop);
|
||||
}
|
||||
|
||||
if (plug_in->ext_main_loop &&
|
||||
g_main_loop_is_running (plug_in->ext_main_loop))
|
||||
{
|
||||
#ifdef PIKA_UNSTABLE
|
||||
g_printerr ("extension '%s' aborted before sending its "
|
||||
"extension_ack message\n",
|
||||
pika_object_get_name (plug_in));
|
||||
#endif
|
||||
|
||||
g_main_loop_quit (plug_in->ext_main_loop);
|
||||
}
|
||||
|
||||
/* Unregister any temporary procedures. */
|
||||
while (plug_in->temp_procedures)
|
||||
pika_plug_in_remove_temp_proc (plug_in, plug_in->temp_procedures->data);
|
||||
|
||||
pika_plug_in_manager_remove_open_plug_in (plug_in->manager, plug_in);
|
||||
}
|
||||
|
||||
PikaPlugInProcFrame *
|
||||
pika_plug_in_get_proc_frame (PikaPlugIn *plug_in)
|
||||
{
|
||||
g_return_val_if_fail (PIKA_IS_PLUG_IN (plug_in), NULL);
|
||||
|
||||
if (plug_in->temp_proc_frames)
|
||||
return plug_in->temp_proc_frames->data;
|
||||
else
|
||||
return &plug_in->main_proc_frame;
|
||||
}
|
||||
|
||||
PikaPlugInProcFrame *
|
||||
pika_plug_in_proc_frame_push (PikaPlugIn *plug_in,
|
||||
PikaContext *context,
|
||||
PikaProgress *progress,
|
||||
PikaTemporaryProcedure *procedure)
|
||||
{
|
||||
PikaPlugInProcFrame *proc_frame;
|
||||
|
||||
g_return_val_if_fail (PIKA_IS_PLUG_IN (plug_in), NULL);
|
||||
g_return_val_if_fail (PIKA_IS_PDB_CONTEXT (context), NULL);
|
||||
g_return_val_if_fail (progress == NULL || PIKA_IS_PROGRESS (progress), NULL);
|
||||
g_return_val_if_fail (PIKA_IS_TEMPORARY_PROCEDURE (procedure), NULL);
|
||||
|
||||
proc_frame = pika_plug_in_proc_frame_new (context, progress,
|
||||
PIKA_PLUG_IN_PROCEDURE (procedure));
|
||||
|
||||
plug_in->temp_proc_frames = g_list_prepend (plug_in->temp_proc_frames,
|
||||
proc_frame);
|
||||
|
||||
return proc_frame;
|
||||
}
|
||||
|
||||
void
|
||||
pika_plug_in_proc_frame_pop (PikaPlugIn *plug_in)
|
||||
{
|
||||
PikaPlugInProcFrame *proc_frame;
|
||||
|
||||
g_return_if_fail (PIKA_IS_PLUG_IN (plug_in));
|
||||
g_return_if_fail (plug_in->temp_proc_frames != NULL);
|
||||
|
||||
proc_frame = (PikaPlugInProcFrame *) plug_in->temp_proc_frames->data;
|
||||
|
||||
pika_plug_in_proc_frame_unref (proc_frame, plug_in);
|
||||
|
||||
plug_in->temp_proc_frames = g_list_remove (plug_in->temp_proc_frames,
|
||||
proc_frame);
|
||||
}
|
||||
|
||||
void
|
||||
pika_plug_in_main_loop (PikaPlugIn *plug_in)
|
||||
{
|
||||
PikaPlugInProcFrame *proc_frame;
|
||||
|
||||
g_return_if_fail (PIKA_IS_PLUG_IN (plug_in));
|
||||
g_return_if_fail (plug_in->temp_proc_frames != NULL);
|
||||
|
||||
proc_frame = (PikaPlugInProcFrame *) plug_in->temp_proc_frames->data;
|
||||
|
||||
g_return_if_fail (proc_frame->main_loop == NULL);
|
||||
|
||||
proc_frame->main_loop = g_main_loop_new (NULL, FALSE);
|
||||
|
||||
g_main_loop_run (proc_frame->main_loop);
|
||||
|
||||
g_clear_pointer (&proc_frame->main_loop, g_main_loop_unref);
|
||||
}
|
||||
|
||||
void
|
||||
pika_plug_in_main_loop_quit (PikaPlugIn *plug_in)
|
||||
{
|
||||
PikaPlugInProcFrame *proc_frame;
|
||||
|
||||
g_return_if_fail (PIKA_IS_PLUG_IN (plug_in));
|
||||
g_return_if_fail (plug_in->temp_proc_frames != NULL);
|
||||
|
||||
proc_frame = (PikaPlugInProcFrame *) plug_in->temp_proc_frames->data;
|
||||
|
||||
g_return_if_fail (proc_frame->main_loop != NULL);
|
||||
|
||||
g_main_loop_quit (proc_frame->main_loop);
|
||||
}
|
||||
|
||||
const gchar *
|
||||
pika_plug_in_get_undo_desc (PikaPlugIn *plug_in)
|
||||
{
|
||||
PikaPlugInProcFrame *proc_frame;
|
||||
const gchar *undo_desc = NULL;
|
||||
|
||||
g_return_val_if_fail (PIKA_IS_PLUG_IN (plug_in), NULL);
|
||||
|
||||
proc_frame = pika_plug_in_get_proc_frame (plug_in);
|
||||
|
||||
if (proc_frame && proc_frame->procedure)
|
||||
undo_desc = pika_procedure_get_label (proc_frame->procedure);
|
||||
|
||||
return undo_desc ? undo_desc : pika_object_get_name (plug_in);
|
||||
}
|
||||
|
||||
void
|
||||
pika_plug_in_add_temp_proc (PikaPlugIn *plug_in,
|
||||
PikaTemporaryProcedure *proc)
|
||||
{
|
||||
PikaPlugInProcedure *overridden;
|
||||
const gchar *help_domain;
|
||||
|
||||
g_return_if_fail (PIKA_IS_PLUG_IN (plug_in));
|
||||
g_return_if_fail (PIKA_IS_TEMPORARY_PROCEDURE (proc));
|
||||
|
||||
overridden = pika_plug_in_procedure_find (plug_in->temp_procedures,
|
||||
pika_object_get_name (proc));
|
||||
|
||||
if (overridden)
|
||||
pika_plug_in_remove_temp_proc (plug_in,
|
||||
PIKA_TEMPORARY_PROCEDURE (overridden));
|
||||
|
||||
help_domain = pika_plug_in_manager_get_help_domain (plug_in->manager,
|
||||
plug_in->file,
|
||||
NULL);
|
||||
|
||||
pika_plug_in_procedure_set_help_domain (PIKA_PLUG_IN_PROCEDURE (proc),
|
||||
help_domain);
|
||||
|
||||
plug_in->temp_procedures = g_slist_prepend (plug_in->temp_procedures,
|
||||
g_object_ref (proc));
|
||||
pika_plug_in_manager_add_temp_proc (plug_in->manager, proc);
|
||||
}
|
||||
|
||||
void
|
||||
pika_plug_in_remove_temp_proc (PikaPlugIn *plug_in,
|
||||
PikaTemporaryProcedure *proc)
|
||||
{
|
||||
g_return_if_fail (PIKA_IS_PLUG_IN (plug_in));
|
||||
g_return_if_fail (PIKA_IS_TEMPORARY_PROCEDURE (proc));
|
||||
|
||||
plug_in->temp_procedures = g_slist_remove (plug_in->temp_procedures, proc);
|
||||
|
||||
pika_plug_in_manager_remove_temp_proc (plug_in->manager, proc);
|
||||
g_object_unref (proc);
|
||||
}
|
||||
|
||||
void
|
||||
pika_plug_in_set_error_handler (PikaPlugIn *plug_in,
|
||||
PikaPDBErrorHandler handler)
|
||||
{
|
||||
PikaPlugInProcFrame *proc_frame;
|
||||
|
||||
g_return_if_fail (PIKA_IS_PLUG_IN (plug_in));
|
||||
|
||||
proc_frame = pika_plug_in_get_proc_frame (plug_in);
|
||||
|
||||
if (proc_frame)
|
||||
proc_frame->error_handler = handler;
|
||||
}
|
||||
|
||||
PikaPDBErrorHandler
|
||||
pika_plug_in_get_error_handler (PikaPlugIn *plug_in)
|
||||
{
|
||||
PikaPlugInProcFrame *proc_frame;
|
||||
|
||||
g_return_val_if_fail (PIKA_IS_PLUG_IN (plug_in),
|
||||
PIKA_PDB_ERROR_HANDLER_INTERNAL);
|
||||
|
||||
proc_frame = pika_plug_in_get_proc_frame (plug_in);
|
||||
|
||||
if (proc_frame)
|
||||
return proc_frame->error_handler;
|
||||
|
||||
return PIKA_PDB_ERROR_HANDLER_INTERNAL;
|
||||
}
|
123
app/plug-in/pikaplugin.h
Normal file
123
app/plug-in/pikaplugin.h
Normal file
@ -0,0 +1,123 @@
|
||||
/* PIKA - Photo and Image Kooker Application
|
||||
* a rebranding of The GNU Image Manipulation Program (created with heckimp)
|
||||
* A derived work which may be trivial. However, any changes may be (C)2023 by Aldercone Studio
|
||||
*
|
||||
* Original copyright, applying to most contents (license remains unchanged):
|
||||
* Copyright (C) 1995 Spencer Kimball and Peter Mattis
|
||||
*
|
||||
* pikaplugin.h
|
||||
*
|
||||
* 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 3 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, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#ifndef __PIKA_PLUG_IN_H__
|
||||
#define __PIKA_PLUG_IN_H__
|
||||
|
||||
|
||||
#include "core/pikaobject.h"
|
||||
#include "pikapluginprocframe.h"
|
||||
|
||||
|
||||
#define WRITE_BUFFER_SIZE 512
|
||||
|
||||
|
||||
#define PIKA_TYPE_PLUG_IN (pika_plug_in_get_type ())
|
||||
#define PIKA_PLUG_IN(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), PIKA_TYPE_PLUG_IN, PikaPlugIn))
|
||||
#define PIKA_PLUG_IN_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), PIKA_TYPE_PLUG_IN, PikaPlugInClass))
|
||||
#define PIKA_IS_PLUG_IN(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), PIKA_TYPE_PLUG_IN))
|
||||
#define PIKA_IS_PLUG_IN_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), PIKA_TYPE_PLUG_IN))
|
||||
|
||||
|
||||
typedef struct _PikaPlugInClass PikaPlugInClass;
|
||||
|
||||
struct _PikaPlugIn
|
||||
{
|
||||
PikaObject parent_instance;
|
||||
|
||||
PikaPlugInManager *manager;
|
||||
GFile *file; /* Plug-in's full path name */
|
||||
|
||||
PikaPlugInCallMode call_mode; /* QUERY, INIT or RUN */
|
||||
guint open : 1; /* Is the plug-in open? */
|
||||
guint hup : 1; /* Did we receive a G_IO_HUP */
|
||||
GPid pid; /* Plug-in's process id */
|
||||
|
||||
GIOChannel *my_read; /* App's read and write channels */
|
||||
GIOChannel *my_write;
|
||||
GIOChannel *his_read; /* Plug-in's read and write channels */
|
||||
GIOChannel *his_write;
|
||||
|
||||
guint input_id; /* Id of input proc */
|
||||
|
||||
gchar write_buffer[WRITE_BUFFER_SIZE]; /* Buffer for writing */
|
||||
gint write_buffer_index; /* Buffer index */
|
||||
|
||||
GSList *temp_procedures; /* Temporary procedures */
|
||||
|
||||
GMainLoop *ext_main_loop; /* for waiting for extension_ack */
|
||||
|
||||
PikaPlugInProcFrame main_proc_frame;
|
||||
|
||||
GList *temp_proc_frames;
|
||||
|
||||
PikaPlugInDef *plug_in_def; /* Valid during query() and init() */
|
||||
};
|
||||
|
||||
struct _PikaPlugInClass
|
||||
{
|
||||
PikaObjectClass parent_class;
|
||||
};
|
||||
|
||||
|
||||
GType pika_plug_in_get_type (void) G_GNUC_CONST;
|
||||
|
||||
PikaPlugIn * pika_plug_in_new (PikaPlugInManager *manager,
|
||||
PikaContext *context,
|
||||
PikaProgress *progress,
|
||||
PikaPlugInProcedure *procedure,
|
||||
GFile *file);
|
||||
|
||||
gboolean pika_plug_in_open (PikaPlugIn *plug_in,
|
||||
PikaPlugInCallMode call_mode,
|
||||
gboolean synchronous);
|
||||
void pika_plug_in_close (PikaPlugIn *plug_in,
|
||||
gboolean kill_it);
|
||||
|
||||
PikaPlugInProcFrame *
|
||||
pika_plug_in_get_proc_frame (PikaPlugIn *plug_in);
|
||||
|
||||
PikaPlugInProcFrame *
|
||||
pika_plug_in_proc_frame_push (PikaPlugIn *plug_in,
|
||||
PikaContext *context,
|
||||
PikaProgress *progress,
|
||||
PikaTemporaryProcedure *procedure);
|
||||
void pika_plug_in_proc_frame_pop (PikaPlugIn *plug_in);
|
||||
|
||||
void pika_plug_in_main_loop (PikaPlugIn *plug_in);
|
||||
void pika_plug_in_main_loop_quit (PikaPlugIn *plug_in);
|
||||
|
||||
const gchar * pika_plug_in_get_undo_desc (PikaPlugIn *plug_in);
|
||||
|
||||
void pika_plug_in_add_temp_proc (PikaPlugIn *plug_in,
|
||||
PikaTemporaryProcedure *procedure);
|
||||
void pika_plug_in_remove_temp_proc (PikaPlugIn *plug_in,
|
||||
PikaTemporaryProcedure *procedure);
|
||||
|
||||
void pika_plug_in_set_error_handler (PikaPlugIn *plug_in,
|
||||
PikaPDBErrorHandler handler);
|
||||
PikaPDBErrorHandler
|
||||
pika_plug_in_get_error_handler (PikaPlugIn *plug_in);
|
||||
|
||||
|
||||
#endif /* __PIKA_PLUG_IN_H__ */
|
146
app/plug-in/pikaplugindebug.c
Normal file
146
app/plug-in/pikaplugindebug.c
Normal file
@ -0,0 +1,146 @@
|
||||
/* PIKA - Photo and Image Kooker Application
|
||||
* a rebranding of The GNU Image Manipulation Program (created with heckimp)
|
||||
* A derived work which may be trivial. However, any changes may be (C)2023 by Aldercone Studio
|
||||
*
|
||||
* Original copyright, applying to most contents (license remains unchanged):
|
||||
* Copyright (C) 1995 Spencer Kimball and Peter Mattis
|
||||
*
|
||||
* pikaplugindebug.c
|
||||
*
|
||||
* 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 3 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, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include "config.h"
|
||||
|
||||
#include <string.h>
|
||||
|
||||
#include <glib-object.h>
|
||||
|
||||
#include "plug-in-types.h"
|
||||
|
||||
#include "pikaplugindebug.h"
|
||||
|
||||
|
||||
struct _PikaPlugInDebug
|
||||
{
|
||||
gchar *name;
|
||||
guint flags;
|
||||
gchar **args;
|
||||
};
|
||||
|
||||
|
||||
static const GDebugKey pika_debug_wrap_keys[] =
|
||||
{
|
||||
{ "query", PIKA_DEBUG_WRAP_QUERY },
|
||||
{ "init", PIKA_DEBUG_WRAP_INIT },
|
||||
{ "run", PIKA_DEBUG_WRAP_RUN },
|
||||
{ "on", PIKA_DEBUG_WRAP_DEFAULT }
|
||||
};
|
||||
|
||||
|
||||
PikaPlugInDebug *
|
||||
pika_plug_in_debug_new (void)
|
||||
{
|
||||
PikaPlugInDebug *debug;
|
||||
const gchar *wrap, *wrapper;
|
||||
gchar *debug_string;
|
||||
gchar **args;
|
||||
GError *error = NULL;
|
||||
|
||||
wrap = g_getenv ("PIKA_PLUGIN_DEBUG_WRAP");
|
||||
wrapper = g_getenv ("PIKA_PLUGIN_DEBUG_WRAPPER");
|
||||
|
||||
if (!(wrap && wrapper))
|
||||
return NULL;
|
||||
|
||||
if (!g_shell_parse_argv (wrapper, NULL, &args, &error))
|
||||
{
|
||||
g_warning ("Unable to parse debug wrapper: \"%s\"\n%s",
|
||||
wrapper, error->message);
|
||||
g_error_free (error);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
debug = g_slice_new (PikaPlugInDebug);
|
||||
|
||||
debug->args = args;
|
||||
|
||||
debug_string = strchr (wrap, ',');
|
||||
|
||||
if (debug_string)
|
||||
{
|
||||
debug->name = g_strndup (wrap, debug_string - wrap);
|
||||
debug->flags = g_parse_debug_string (debug_string + 1,
|
||||
pika_debug_wrap_keys,
|
||||
G_N_ELEMENTS (pika_debug_wrap_keys));
|
||||
}
|
||||
else
|
||||
{
|
||||
debug->name = g_strdup (wrap);
|
||||
debug->flags = PIKA_DEBUG_WRAP_DEFAULT;
|
||||
}
|
||||
|
||||
return debug;
|
||||
}
|
||||
|
||||
void
|
||||
pika_plug_in_debug_free (PikaPlugInDebug *debug)
|
||||
{
|
||||
g_return_if_fail (debug != NULL);
|
||||
|
||||
if (debug->name)
|
||||
g_free (debug->name);
|
||||
|
||||
if (debug->args)
|
||||
g_strfreev (debug->args);
|
||||
|
||||
g_slice_free (PikaPlugInDebug, debug);
|
||||
}
|
||||
|
||||
gchar **
|
||||
pika_plug_in_debug_argv (PikaPlugInDebug *debug,
|
||||
const gchar *name,
|
||||
PikaDebugWrapFlag flag,
|
||||
const gchar **args)
|
||||
{
|
||||
GPtrArray *argv;
|
||||
gchar **arg;
|
||||
gchar *basename;
|
||||
|
||||
g_return_val_if_fail (debug != NULL, NULL);
|
||||
g_return_val_if_fail (name != NULL, NULL);
|
||||
g_return_val_if_fail (args != NULL, NULL);
|
||||
|
||||
basename = g_path_get_basename (name);
|
||||
|
||||
if (!(debug->flags & flag) || (strcmp (debug->name, basename) != 0))
|
||||
{
|
||||
g_free (basename);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
g_free (basename);
|
||||
|
||||
argv = g_ptr_array_sized_new (8);
|
||||
|
||||
for (arg = debug->args; *arg != NULL; arg++)
|
||||
g_ptr_array_add (argv, *arg);
|
||||
|
||||
for (arg = (gchar **) args; *arg != NULL; arg++)
|
||||
g_ptr_array_add (argv, *arg);
|
||||
|
||||
g_ptr_array_add (argv, NULL);
|
||||
|
||||
return (gchar **) g_ptr_array_free (argv, FALSE);
|
||||
}
|
47
app/plug-in/pikaplugindebug.h
Normal file
47
app/plug-in/pikaplugindebug.h
Normal file
@ -0,0 +1,47 @@
|
||||
/* PIKA - Photo and Image Kooker Application
|
||||
* a rebranding of The GNU Image Manipulation Program (created with heckimp)
|
||||
* A derived work which may be trivial. However, any changes may be (C)2023 by Aldercone Studio
|
||||
*
|
||||
* Original copyright, applying to most contents (license remains unchanged):
|
||||
* Copyright (C) 1995 Spencer Kimball and Peter Mattis
|
||||
*
|
||||
* pikaplugindebug.h
|
||||
*
|
||||
* 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 3 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, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#ifndef __PIKA_PLUG_IN_DEBUG_H__
|
||||
#define __PIKA_PLUG_IN_DEBUG_H__
|
||||
|
||||
|
||||
typedef enum
|
||||
{
|
||||
PIKA_DEBUG_WRAP_QUERY = 1 << 0,
|
||||
PIKA_DEBUG_WRAP_INIT = 1 << 1,
|
||||
PIKA_DEBUG_WRAP_RUN = 1 << 2,
|
||||
|
||||
PIKA_DEBUG_WRAP_DEFAULT = PIKA_DEBUG_WRAP_RUN
|
||||
} PikaDebugWrapFlag;
|
||||
|
||||
|
||||
PikaPlugInDebug * pika_plug_in_debug_new (void);
|
||||
void pika_plug_in_debug_free (PikaPlugInDebug *debug);
|
||||
|
||||
gchar ** pika_plug_in_debug_argv (PikaPlugInDebug *debug,
|
||||
const gchar *name,
|
||||
PikaDebugWrapFlag flag,
|
||||
const gchar **args);
|
||||
|
||||
|
||||
#endif /* __PIKA_PLUG_IN_DEBUG_H__ */
|
207
app/plug-in/pikaplugindef.c
Normal file
207
app/plug-in/pikaplugindef.c
Normal file
@ -0,0 +1,207 @@
|
||||
/* PIKA - Photo and Image Kooker Application
|
||||
* a rebranding of The GNU Image Manipulation Program (created with heckimp)
|
||||
* A derived work which may be trivial. However, any changes may be (C)2023 by Aldercone Studio
|
||||
*
|
||||
* Original copyright, applying to most contents (license remains unchanged):
|
||||
* Copyright (C) 1995 Spencer Kimball and Peter Mattis
|
||||
*
|
||||
* pikaplugindef.c
|
||||
*
|
||||
* 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 3 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, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include "config.h"
|
||||
|
||||
#include <gdk-pixbuf/gdk-pixbuf.h>
|
||||
#include <gegl.h>
|
||||
|
||||
#include "plug-in-types.h"
|
||||
|
||||
#include "core/pika-memsize.h"
|
||||
|
||||
#include "pikaplugindef.h"
|
||||
#include "pikapluginprocedure.h"
|
||||
|
||||
|
||||
static void pika_plug_in_def_finalize (GObject *object);
|
||||
|
||||
static gint64 pika_plug_in_def_get_memsize (PikaObject *object,
|
||||
gint64 *gui_size);
|
||||
|
||||
|
||||
G_DEFINE_TYPE (PikaPlugInDef, pika_plug_in_def, PIKA_TYPE_OBJECT)
|
||||
|
||||
#define parent_class pika_plug_in_def_parent_class
|
||||
|
||||
|
||||
static void
|
||||
pika_plug_in_def_class_init (PikaPlugInDefClass *klass)
|
||||
{
|
||||
GObjectClass *object_class = G_OBJECT_CLASS (klass);
|
||||
PikaObjectClass *pika_object_class = PIKA_OBJECT_CLASS (klass);
|
||||
|
||||
object_class->finalize = pika_plug_in_def_finalize;
|
||||
|
||||
pika_object_class->get_memsize = pika_plug_in_def_get_memsize;
|
||||
}
|
||||
|
||||
static void
|
||||
pika_plug_in_def_init (PikaPlugInDef *def)
|
||||
{
|
||||
}
|
||||
|
||||
static void
|
||||
pika_plug_in_def_finalize (GObject *object)
|
||||
{
|
||||
PikaPlugInDef *plug_in_def = PIKA_PLUG_IN_DEF (object);
|
||||
|
||||
g_object_unref (plug_in_def->file);
|
||||
g_free (plug_in_def->help_domain_name);
|
||||
g_free (plug_in_def->help_domain_uri);
|
||||
|
||||
g_slist_free_full (plug_in_def->procedures, (GDestroyNotify) g_object_unref);
|
||||
|
||||
G_OBJECT_CLASS (parent_class)->finalize (object);
|
||||
}
|
||||
|
||||
static gint64
|
||||
pika_plug_in_def_get_memsize (PikaObject *object,
|
||||
gint64 *gui_size)
|
||||
{
|
||||
PikaPlugInDef *plug_in_def = PIKA_PLUG_IN_DEF (object);
|
||||
gint64 memsize = 0;
|
||||
|
||||
memsize += pika_g_object_get_memsize (G_OBJECT (plug_in_def->file));
|
||||
memsize += pika_string_get_memsize (plug_in_def->help_domain_name);
|
||||
memsize += pika_string_get_memsize (plug_in_def->help_domain_uri);
|
||||
|
||||
memsize += pika_g_slist_get_memsize (plug_in_def->procedures, 0);
|
||||
|
||||
return memsize + PIKA_OBJECT_CLASS (parent_class)->get_memsize (object,
|
||||
gui_size);
|
||||
}
|
||||
|
||||
|
||||
/* public functions */
|
||||
|
||||
PikaPlugInDef *
|
||||
pika_plug_in_def_new (GFile *file)
|
||||
{
|
||||
PikaPlugInDef *plug_in_def;
|
||||
|
||||
g_return_val_if_fail (G_IS_FILE (file), NULL);
|
||||
|
||||
plug_in_def = g_object_new (PIKA_TYPE_PLUG_IN_DEF, NULL);
|
||||
|
||||
plug_in_def->file = g_object_ref (file);
|
||||
|
||||
return plug_in_def;
|
||||
}
|
||||
|
||||
void
|
||||
pika_plug_in_def_add_procedure (PikaPlugInDef *plug_in_def,
|
||||
PikaPlugInProcedure *proc)
|
||||
{
|
||||
PikaPlugInProcedure *overridden;
|
||||
|
||||
g_return_if_fail (PIKA_IS_PLUG_IN_DEF (plug_in_def));
|
||||
g_return_if_fail (PIKA_IS_PLUG_IN_PROCEDURE (proc));
|
||||
|
||||
overridden = pika_plug_in_procedure_find (plug_in_def->procedures,
|
||||
pika_object_get_name (proc));
|
||||
|
||||
if (overridden)
|
||||
pika_plug_in_def_remove_procedure (plug_in_def, overridden);
|
||||
|
||||
proc->mtime = plug_in_def->mtime;
|
||||
|
||||
pika_plug_in_procedure_set_help_domain (proc,
|
||||
plug_in_def->help_domain_name);
|
||||
|
||||
plug_in_def->procedures = g_slist_append (plug_in_def->procedures,
|
||||
g_object_ref (proc));
|
||||
}
|
||||
|
||||
void
|
||||
pika_plug_in_def_remove_procedure (PikaPlugInDef *plug_in_def,
|
||||
PikaPlugInProcedure *proc)
|
||||
{
|
||||
g_return_if_fail (PIKA_IS_PLUG_IN_DEF (plug_in_def));
|
||||
g_return_if_fail (PIKA_IS_PLUG_IN_PROCEDURE (proc));
|
||||
|
||||
plug_in_def->procedures = g_slist_remove (plug_in_def->procedures, proc);
|
||||
g_object_unref (proc);
|
||||
}
|
||||
|
||||
void
|
||||
pika_plug_in_def_set_help_domain (PikaPlugInDef *plug_in_def,
|
||||
const gchar *domain_name,
|
||||
const gchar *domain_uri)
|
||||
{
|
||||
GSList *list;
|
||||
|
||||
g_return_if_fail (PIKA_IS_PLUG_IN_DEF (plug_in_def));
|
||||
|
||||
if (plug_in_def->help_domain_name)
|
||||
g_free (plug_in_def->help_domain_name);
|
||||
plug_in_def->help_domain_name = g_strdup (domain_name);
|
||||
|
||||
if (plug_in_def->help_domain_uri)
|
||||
g_free (plug_in_def->help_domain_uri);
|
||||
plug_in_def->help_domain_uri = g_strdup (domain_uri);
|
||||
|
||||
for (list = plug_in_def->procedures; list; list = g_slist_next (list))
|
||||
{
|
||||
PikaPlugInProcedure *procedure = list->data;
|
||||
|
||||
pika_plug_in_procedure_set_help_domain (procedure,
|
||||
plug_in_def->help_domain_name);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
pika_plug_in_def_set_mtime (PikaPlugInDef *plug_in_def,
|
||||
gint64 mtime)
|
||||
{
|
||||
GSList *list;
|
||||
|
||||
g_return_if_fail (PIKA_IS_PLUG_IN_DEF (plug_in_def));
|
||||
|
||||
plug_in_def->mtime = mtime;
|
||||
|
||||
for (list = plug_in_def->procedures; list; list = g_slist_next (list))
|
||||
{
|
||||
PikaPlugInProcedure *proc = list->data;
|
||||
|
||||
proc->mtime = plug_in_def->mtime;
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
pika_plug_in_def_set_needs_query (PikaPlugInDef *plug_in_def,
|
||||
gboolean needs_query)
|
||||
{
|
||||
g_return_if_fail (PIKA_IS_PLUG_IN_DEF (plug_in_def));
|
||||
|
||||
plug_in_def->needs_query = needs_query ? TRUE : FALSE;
|
||||
}
|
||||
|
||||
void
|
||||
pika_plug_in_def_set_has_init (PikaPlugInDef *plug_in_def,
|
||||
gboolean has_init)
|
||||
{
|
||||
g_return_if_fail (PIKA_IS_PLUG_IN_DEF (plug_in_def));
|
||||
|
||||
plug_in_def->has_init = has_init ? TRUE : FALSE;
|
||||
}
|
80
app/plug-in/pikaplugindef.h
Normal file
80
app/plug-in/pikaplugindef.h
Normal file
@ -0,0 +1,80 @@
|
||||
/* PIKA - Photo and Image Kooker Application
|
||||
* a rebranding of The GNU Image Manipulation Program (created with heckimp)
|
||||
* A derived work which may be trivial. However, any changes may be (C)2023 by Aldercone Studio
|
||||
*
|
||||
* Original copyright, applying to most contents (license remains unchanged):
|
||||
* Copyright (C) 1995 Spencer Kimball and Peter Mattis
|
||||
*
|
||||
* pikaplugindef.h
|
||||
*
|
||||
* 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 3 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, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#ifndef __PIKA_PLUG_IN_DEF_H__
|
||||
#define __PIKA_PLUG_IN_DEF_H__
|
||||
|
||||
|
||||
#include "core/pikaobject.h"
|
||||
|
||||
|
||||
#define PIKA_TYPE_PLUG_IN_DEF (pika_plug_in_def_get_type ())
|
||||
#define PIKA_PLUG_IN_DEF(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), PIKA_TYPE_PLUG_IN_DEF, PikaPlugInDef))
|
||||
#define PIKA_PLUG_IN_DEF_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), PIKA_TYPE_PLUG_IN_DEF, PikaPlugInDefClass))
|
||||
#define PIKA_IS_PLUG_IN_DEF(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), PIKA_TYPE_PLUG_IN_DEF))
|
||||
#define PIKA_IS_PLUG_IN_DEF_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), PIKA_TYPE_PLUG_IN_DEF))
|
||||
|
||||
|
||||
typedef struct _PikaPlugInDefClass PikaPlugInDefClass;
|
||||
|
||||
struct _PikaPlugInDef
|
||||
{
|
||||
PikaObject parent_instance;
|
||||
|
||||
GFile *file;
|
||||
GSList *procedures;
|
||||
gchar *help_domain_name;
|
||||
gchar *help_domain_uri;
|
||||
gint64 mtime;
|
||||
gboolean needs_query; /* Does the plug-in need to be queried ? */
|
||||
gboolean has_init; /* Does the plug-in need to be initialized ? */
|
||||
};
|
||||
|
||||
struct _PikaPlugInDefClass
|
||||
{
|
||||
PikaObjectClass parent_class;
|
||||
};
|
||||
|
||||
|
||||
GType pika_plug_in_def_get_type (void) G_GNUC_CONST;
|
||||
|
||||
PikaPlugInDef * pika_plug_in_def_new (GFile *file);
|
||||
|
||||
void pika_plug_in_def_add_procedure (PikaPlugInDef *plug_in_def,
|
||||
PikaPlugInProcedure *proc);
|
||||
void pika_plug_in_def_remove_procedure (PikaPlugInDef *plug_in_def,
|
||||
PikaPlugInProcedure *proc);
|
||||
|
||||
void pika_plug_in_def_set_help_domain (PikaPlugInDef *plug_in_def,
|
||||
const gchar *domain_name,
|
||||
const gchar *domain_uri);
|
||||
|
||||
void pika_plug_in_def_set_mtime (PikaPlugInDef *plug_in_def,
|
||||
gint64 mtime);
|
||||
void pika_plug_in_def_set_needs_query (PikaPlugInDef *plug_in_def,
|
||||
gboolean needs_query);
|
||||
void pika_plug_in_def_set_has_init (PikaPlugInDef *plug_in_def,
|
||||
gboolean has_init);
|
||||
|
||||
|
||||
#endif /* __PIKA_PLUG_IN_DEF_H__ */
|
40
app/plug-in/pikapluginerror.c
Normal file
40
app/plug-in/pikapluginerror.c
Normal file
@ -0,0 +1,40 @@
|
||||
/* PIKA - Photo and Image Kooker Application
|
||||
* a rebranding of The GNU Image Manipulation Program (created with heckimp)
|
||||
* A derived work which may be trivial. However, any changes may be (C)2023 by Aldercone Studio
|
||||
*
|
||||
* Original copyright, applying to most contents (license remains unchanged):
|
||||
* Copyright (C) 1995 Spencer Kimball and Peter Mattis
|
||||
*
|
||||
* 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 3 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, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include "config.h"
|
||||
|
||||
#include <glib-object.h>
|
||||
|
||||
#include "pikapluginerror.h"
|
||||
|
||||
|
||||
/**
|
||||
* pika_plug_in_error_quark:
|
||||
*
|
||||
* This function is never called directly. Use PIKA_PLUG_IN_ERROR() instead.
|
||||
*
|
||||
* Returns: the #GQuark that defines the PikaPlugIn error domain.
|
||||
**/
|
||||
GQuark
|
||||
pika_plug_in_error_quark (void)
|
||||
{
|
||||
return g_quark_from_static_string ("pika-plug-in-error-quark");
|
||||
}
|
39
app/plug-in/pikapluginerror.h
Normal file
39
app/plug-in/pikapluginerror.h
Normal file
@ -0,0 +1,39 @@
|
||||
/* PIKA - Photo and Image Kooker Application
|
||||
* a rebranding of The GNU Image Manipulation Program (created with heckimp)
|
||||
* A derived work which may be trivial. However, any changes may be (C)2023 by Aldercone Studio
|
||||
*
|
||||
* Original copyright, applying to most contents (license remains unchanged):
|
||||
* Copyright (C) 1995 Spencer Kimball and Peter Mattis
|
||||
*
|
||||
* 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 3 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, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#ifndef __PIKA_PLUG_IN_ERROR_H__
|
||||
#define __PIKA_PLUG_IN_ERROR_H__
|
||||
|
||||
|
||||
typedef enum
|
||||
{
|
||||
PIKA_PLUG_IN_FAILED, /* generic error condition */
|
||||
PIKA_PLUG_IN_EXECUTION_FAILED,
|
||||
PIKA_PLUG_IN_NOT_FOUND
|
||||
} PikaPlugInErrorCode;
|
||||
|
||||
|
||||
#define PIKA_PLUG_IN_ERROR (pika_plug_in_error_quark ())
|
||||
|
||||
GQuark pika_plug_in_error_quark (void) G_GNUC_CONST;
|
||||
|
||||
|
||||
#endif /* __PIKA_PLUG_IN_ERROR_H__ */
|
385
app/plug-in/pikapluginmanager-call.c
Normal file
385
app/plug-in/pikapluginmanager-call.c
Normal file
@ -0,0 +1,385 @@
|
||||
/* PIKA - Photo and Image Kooker Application
|
||||
* a rebranding of The GNU Image Manipulation Program (created with heckimp)
|
||||
* A derived work which may be trivial. However, any changes may be (C)2023 by Aldercone Studio
|
||||
*
|
||||
* Original copyright, applying to most contents (license remains unchanged):
|
||||
* Copyright (C) 1995 Spencer Kimball and Peter Mattis
|
||||
*
|
||||
* pikapluginmanager-call.c
|
||||
*
|
||||
* 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 3 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, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include "config.h"
|
||||
|
||||
#include <gdk-pixbuf/gdk-pixbuf.h>
|
||||
#include <gegl.h>
|
||||
|
||||
#ifdef G_OS_WIN32
|
||||
#include <windows.h>
|
||||
#endif
|
||||
|
||||
#include "libpikabase/pikabase.h"
|
||||
#include "libpikabase/pikaprotocol.h"
|
||||
#include "libpikabase/pikawire.h"
|
||||
|
||||
#include "libpika/pikagpparams.h"
|
||||
|
||||
#include "plug-in-types.h"
|
||||
|
||||
#include "config/pikaguiconfig.h"
|
||||
|
||||
#include "core/pika.h"
|
||||
#include "core/pikadisplay.h"
|
||||
#include "core/pikaprogress.h"
|
||||
|
||||
#include "pdb/pikapdbcontext.h"
|
||||
|
||||
#include "pikaplugin.h"
|
||||
#include "pikaplugin-message.h"
|
||||
#include "pikaplugindef.h"
|
||||
#include "pikapluginerror.h"
|
||||
#include "pikapluginmanager.h"
|
||||
#define __YES_I_NEED_PIKA_PLUG_IN_MANAGER_CALL__
|
||||
#include "pikapluginmanager-call.h"
|
||||
#include "pikapluginshm.h"
|
||||
#include "pikatemporaryprocedure.h"
|
||||
|
||||
#include "pika-intl.h"
|
||||
|
||||
|
||||
static void
|
||||
pika_allow_set_foreground_window (PikaPlugIn *plug_in)
|
||||
{
|
||||
#ifdef G_OS_WIN32
|
||||
AllowSetForegroundWindow (GetProcessId (plug_in->pid));
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
/* public functions */
|
||||
|
||||
void
|
||||
pika_plug_in_manager_call_query (PikaPlugInManager *manager,
|
||||
PikaContext *context,
|
||||
PikaPlugInDef *plug_in_def)
|
||||
{
|
||||
PikaPlugIn *plug_in;
|
||||
|
||||
g_return_if_fail (PIKA_IS_PLUG_IN_MANAGER (manager));
|
||||
g_return_if_fail (PIKA_IS_PDB_CONTEXT (context));
|
||||
g_return_if_fail (PIKA_IS_PLUG_IN_DEF (plug_in_def));
|
||||
|
||||
plug_in = pika_plug_in_new (manager, context, NULL,
|
||||
NULL, plug_in_def->file);
|
||||
|
||||
if (plug_in)
|
||||
{
|
||||
plug_in->plug_in_def = plug_in_def;
|
||||
|
||||
if (pika_plug_in_open (plug_in, PIKA_PLUG_IN_CALL_QUERY, TRUE))
|
||||
{
|
||||
while (plug_in->open)
|
||||
{
|
||||
PikaWireMessage msg;
|
||||
|
||||
if (! pika_wire_read_msg (plug_in->my_read, &msg, plug_in))
|
||||
{
|
||||
pika_plug_in_close (plug_in, TRUE);
|
||||
}
|
||||
else
|
||||
{
|
||||
pika_plug_in_handle_message (plug_in, &msg);
|
||||
pika_wire_destroy (&msg);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
g_object_unref (plug_in);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
pika_plug_in_manager_call_init (PikaPlugInManager *manager,
|
||||
PikaContext *context,
|
||||
PikaPlugInDef *plug_in_def)
|
||||
{
|
||||
PikaPlugIn *plug_in;
|
||||
|
||||
g_return_if_fail (PIKA_IS_PLUG_IN_MANAGER (manager));
|
||||
g_return_if_fail (PIKA_IS_PDB_CONTEXT (context));
|
||||
g_return_if_fail (PIKA_IS_PLUG_IN_DEF (plug_in_def));
|
||||
|
||||
plug_in = pika_plug_in_new (manager, context, NULL,
|
||||
NULL, plug_in_def->file);
|
||||
|
||||
if (plug_in)
|
||||
{
|
||||
plug_in->plug_in_def = plug_in_def;
|
||||
|
||||
if (pika_plug_in_open (plug_in, PIKA_PLUG_IN_CALL_INIT, TRUE))
|
||||
{
|
||||
while (plug_in->open)
|
||||
{
|
||||
PikaWireMessage msg;
|
||||
|
||||
if (! pika_wire_read_msg (plug_in->my_read, &msg, plug_in))
|
||||
{
|
||||
pika_plug_in_close (plug_in, TRUE);
|
||||
}
|
||||
else
|
||||
{
|
||||
pika_plug_in_handle_message (plug_in, &msg);
|
||||
pika_wire_destroy (&msg);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
g_object_unref (plug_in);
|
||||
}
|
||||
}
|
||||
|
||||
PikaValueArray *
|
||||
pika_plug_in_manager_call_run (PikaPlugInManager *manager,
|
||||
PikaContext *context,
|
||||
PikaProgress *progress,
|
||||
PikaPlugInProcedure *procedure,
|
||||
PikaValueArray *args,
|
||||
gboolean synchronous,
|
||||
PikaDisplay *display)
|
||||
{
|
||||
PikaValueArray *return_vals = NULL;
|
||||
PikaPlugIn *plug_in;
|
||||
|
||||
g_return_val_if_fail (PIKA_IS_PLUG_IN_MANAGER (manager), NULL);
|
||||
g_return_val_if_fail (PIKA_IS_PDB_CONTEXT (context), NULL);
|
||||
g_return_val_if_fail (progress == NULL || PIKA_IS_PROGRESS (progress), NULL);
|
||||
g_return_val_if_fail (PIKA_IS_PLUG_IN_PROCEDURE (procedure), NULL);
|
||||
g_return_val_if_fail (args != NULL, NULL);
|
||||
g_return_val_if_fail (display == NULL || PIKA_IS_DISPLAY (display), NULL);
|
||||
|
||||
plug_in = pika_plug_in_new (manager, context, progress, procedure, NULL);
|
||||
|
||||
if (plug_in)
|
||||
{
|
||||
PikaCoreConfig *core_config = manager->pika->config;
|
||||
PikaGeglConfig *gegl_config = PIKA_GEGL_CONFIG (core_config);
|
||||
PikaDisplayConfig *display_config = PIKA_DISPLAY_CONFIG (core_config);
|
||||
PikaGuiConfig *gui_config = PIKA_GUI_CONFIG (core_config);
|
||||
GPConfig config;
|
||||
GPProcRun proc_run;
|
||||
gint display_id;
|
||||
GObject *monitor;
|
||||
GFile *icon_theme_dir;
|
||||
|
||||
if (! pika_plug_in_open (plug_in, PIKA_PLUG_IN_CALL_RUN, FALSE))
|
||||
{
|
||||
const gchar *name = pika_object_get_name (plug_in);
|
||||
GError *error = g_error_new (PIKA_PLUG_IN_ERROR,
|
||||
PIKA_PLUG_IN_EXECUTION_FAILED,
|
||||
_("Failed to run plug-in \"%s\""),
|
||||
name);
|
||||
|
||||
g_object_unref (plug_in);
|
||||
|
||||
return_vals = pika_procedure_get_return_values (PIKA_PROCEDURE (procedure),
|
||||
FALSE, error);
|
||||
g_error_free (error);
|
||||
|
||||
return return_vals;
|
||||
}
|
||||
|
||||
if (! display)
|
||||
display = pika_context_get_display (context);
|
||||
|
||||
display_id = display ? pika_display_get_id (display) : -1;
|
||||
|
||||
icon_theme_dir = pika_get_icon_theme_dir (manager->pika);
|
||||
|
||||
config.tile_width = PIKA_PLUG_IN_TILE_WIDTH;
|
||||
config.tile_height = PIKA_PLUG_IN_TILE_HEIGHT;
|
||||
config.shm_id = (manager->shm ?
|
||||
pika_plug_in_shm_get_id (manager->shm) :
|
||||
-1);
|
||||
config.check_size = display_config->transparency_size;
|
||||
config.check_type = display_config->transparency_type;
|
||||
config.check_custom_color1 = display_config->transparency_custom_color1;
|
||||
config.check_custom_color2 = display_config->transparency_custom_color2;
|
||||
config.show_help_button = (gui_config->use_help &&
|
||||
gui_config->show_help_button);
|
||||
config.use_cpu_accel = manager->pika->use_cpu_accel;
|
||||
config.use_opencl = gegl_config->use_opencl;
|
||||
config.export_color_profile = core_config->export_color_profile;
|
||||
config.export_comment = core_config->export_comment;
|
||||
config.export_exif = core_config->export_metadata_exif;
|
||||
config.export_xmp = core_config->export_metadata_xmp;
|
||||
config.export_iptc = core_config->export_metadata_iptc;
|
||||
config.default_display_id = display_id;
|
||||
config.app_name = (gchar *) g_get_application_name ();
|
||||
config.wm_class = (gchar *) pika_get_program_class (manager->pika);
|
||||
config.display_name = pika_get_display_name (manager->pika,
|
||||
display_id,
|
||||
&monitor,
|
||||
&config.monitor_number);
|
||||
config.timestamp = pika_get_user_time (manager->pika);
|
||||
config.icon_theme_dir = (icon_theme_dir ?
|
||||
g_file_get_path (icon_theme_dir) :
|
||||
NULL);
|
||||
config.tile_cache_size = gegl_config->tile_cache_size;
|
||||
config.swap_path = gegl_config->swap_path;
|
||||
config.swap_compression = gegl_config->swap_compression;
|
||||
config.num_processors = gegl_config->num_processors;
|
||||
|
||||
proc_run.name = (gchar *) pika_object_get_name (procedure);
|
||||
proc_run.n_params = pika_value_array_length (args);
|
||||
proc_run.params = _pika_value_array_to_gp_params (args, FALSE);
|
||||
|
||||
if (! gp_config_write (plug_in->my_write, &config, plug_in) ||
|
||||
! gp_proc_run_write (plug_in->my_write, &proc_run, plug_in) ||
|
||||
! pika_wire_flush (plug_in->my_write, plug_in))
|
||||
{
|
||||
const gchar *name = pika_object_get_name (plug_in);
|
||||
GError *error = g_error_new (PIKA_PLUG_IN_ERROR,
|
||||
PIKA_PLUG_IN_EXECUTION_FAILED,
|
||||
_("Failed to run plug-in \"%s\""),
|
||||
name);
|
||||
|
||||
g_free (config.display_name);
|
||||
g_free (config.icon_theme_dir);
|
||||
|
||||
_pika_gp_params_free (proc_run.params, proc_run.n_params, FALSE);
|
||||
|
||||
g_object_unref (plug_in);
|
||||
|
||||
return_vals = pika_procedure_get_return_values (PIKA_PROCEDURE (procedure),
|
||||
FALSE, error);
|
||||
g_error_free (error);
|
||||
|
||||
return return_vals;
|
||||
}
|
||||
|
||||
g_free (config.display_name);
|
||||
g_free (config.icon_theme_dir);
|
||||
|
||||
_pika_gp_params_free (proc_run.params, proc_run.n_params, FALSE);
|
||||
|
||||
/* If this is an extension,
|
||||
* wait for an installation-confirmation message
|
||||
*/
|
||||
if (PIKA_PROCEDURE (procedure)->proc_type == PIKA_PDB_PROC_TYPE_EXTENSION)
|
||||
{
|
||||
plug_in->ext_main_loop = g_main_loop_new (NULL, FALSE);
|
||||
|
||||
g_main_loop_run (plug_in->ext_main_loop);
|
||||
|
||||
/* main_loop is quit in pika_plug_in_handle_extension_ack() */
|
||||
|
||||
g_clear_pointer (&plug_in->ext_main_loop, g_main_loop_unref);
|
||||
}
|
||||
|
||||
/* If this plug-in is requested to run synchronously,
|
||||
* wait for its return values
|
||||
*/
|
||||
if (synchronous)
|
||||
{
|
||||
PikaPlugInProcFrame *proc_frame = &plug_in->main_proc_frame;
|
||||
|
||||
proc_frame->main_loop = g_main_loop_new (NULL, FALSE);
|
||||
|
||||
g_main_loop_run (proc_frame->main_loop);
|
||||
|
||||
/* main_loop is quit in pika_plug_in_handle_proc_return() */
|
||||
|
||||
g_clear_pointer (&proc_frame->main_loop, g_main_loop_unref);
|
||||
|
||||
return_vals = pika_plug_in_proc_frame_get_return_values (proc_frame);
|
||||
}
|
||||
|
||||
g_object_unref (plug_in);
|
||||
}
|
||||
|
||||
return return_vals;
|
||||
}
|
||||
|
||||
PikaValueArray *
|
||||
pika_plug_in_manager_call_run_temp (PikaPlugInManager *manager,
|
||||
PikaContext *context,
|
||||
PikaProgress *progress,
|
||||
PikaTemporaryProcedure *procedure,
|
||||
PikaValueArray *args)
|
||||
{
|
||||
PikaValueArray *return_vals = NULL;
|
||||
PikaPlugIn *plug_in;
|
||||
|
||||
g_return_val_if_fail (PIKA_IS_PLUG_IN_MANAGER (manager), NULL);
|
||||
g_return_val_if_fail (PIKA_IS_PDB_CONTEXT (context), NULL);
|
||||
g_return_val_if_fail (progress == NULL || PIKA_IS_PROGRESS (progress), NULL);
|
||||
g_return_val_if_fail (PIKA_IS_TEMPORARY_PROCEDURE (procedure), NULL);
|
||||
g_return_val_if_fail (args != NULL, NULL);
|
||||
|
||||
plug_in = procedure->plug_in;
|
||||
|
||||
if (plug_in)
|
||||
{
|
||||
PikaPlugInProcFrame *proc_frame;
|
||||
GPProcRun proc_run;
|
||||
|
||||
proc_frame = pika_plug_in_proc_frame_push (plug_in, context, progress,
|
||||
procedure);
|
||||
|
||||
proc_run.name = (gchar *) pika_object_get_name (procedure);
|
||||
proc_run.n_params = pika_value_array_length (args);
|
||||
proc_run.params = _pika_value_array_to_gp_params (args, FALSE);
|
||||
|
||||
if (! gp_temp_proc_run_write (plug_in->my_write, &proc_run, plug_in) ||
|
||||
! pika_wire_flush (plug_in->my_write, plug_in))
|
||||
{
|
||||
const gchar *name = pika_object_get_name (plug_in);
|
||||
GError *error = g_error_new (PIKA_PLUG_IN_ERROR,
|
||||
PIKA_PLUG_IN_EXECUTION_FAILED,
|
||||
_("Failed to run plug-in \"%s\""),
|
||||
name);
|
||||
|
||||
|
||||
_pika_gp_params_free (proc_run.params, proc_run.n_params, FALSE);
|
||||
pika_plug_in_proc_frame_pop (plug_in);
|
||||
|
||||
return_vals = pika_procedure_get_return_values (PIKA_PROCEDURE (procedure),
|
||||
FALSE, error);
|
||||
g_error_free (error);
|
||||
|
||||
return return_vals;
|
||||
}
|
||||
|
||||
pika_allow_set_foreground_window (plug_in);
|
||||
|
||||
_pika_gp_params_free (proc_run.params, proc_run.n_params, FALSE);
|
||||
|
||||
g_object_ref (plug_in);
|
||||
pika_plug_in_proc_frame_ref (proc_frame);
|
||||
|
||||
pika_plug_in_main_loop (plug_in);
|
||||
|
||||
/* main_loop is quit and proc_frame is popped in
|
||||
* pika_plug_in_handle_temp_proc_return()
|
||||
*/
|
||||
|
||||
return_vals = pika_plug_in_proc_frame_get_return_values (proc_frame);
|
||||
|
||||
pika_plug_in_proc_frame_unref (proc_frame, plug_in);
|
||||
g_object_unref (plug_in);
|
||||
}
|
||||
|
||||
return return_vals;
|
||||
}
|
63
app/plug-in/pikapluginmanager-call.h
Normal file
63
app/plug-in/pikapluginmanager-call.h
Normal file
@ -0,0 +1,63 @@
|
||||
/* PIKA - Photo and Image Kooker Application
|
||||
* a rebranding of The GNU Image Manipulation Program (created with heckimp)
|
||||
* A derived work which may be trivial. However, any changes may be (C)2023 by Aldercone Studio
|
||||
*
|
||||
* Original copyright, applying to most contents (license remains unchanged):
|
||||
* Copyright (C) 1995 Spencer Kimball and Peter Mattis
|
||||
*
|
||||
* pikapluginmanager-call.h
|
||||
*
|
||||
* 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 3 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, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#ifndef __PIKA_PLUG_IN_MANAGER_CALL_H__
|
||||
#define __PIKA_PLUG_IN_MANAGER_CALL_H__
|
||||
|
||||
#ifndef __YES_I_NEED_PIKA_PLUG_IN_MANAGER_CALL__
|
||||
#error Do not use pika_plug_in_manager_call_run*(), use pika_procedure_execute*() instead.
|
||||
#endif
|
||||
|
||||
|
||||
/* Call the plug-in's query() function
|
||||
*/
|
||||
void pika_plug_in_manager_call_query (PikaPlugInManager *manager,
|
||||
PikaContext *context,
|
||||
PikaPlugInDef *plug_in_def);
|
||||
|
||||
/* Call the plug-in's init() function
|
||||
*/
|
||||
void pika_plug_in_manager_call_init (PikaPlugInManager *manager,
|
||||
PikaContext *context,
|
||||
PikaPlugInDef *plug_in_def);
|
||||
|
||||
/* Run a plug-in as if it were a procedure database procedure
|
||||
*/
|
||||
PikaValueArray * pika_plug_in_manager_call_run (PikaPlugInManager *manager,
|
||||
PikaContext *context,
|
||||
PikaProgress *progress,
|
||||
PikaPlugInProcedure *procedure,
|
||||
PikaValueArray *args,
|
||||
gboolean synchronous,
|
||||
PikaDisplay *display);
|
||||
|
||||
/* Run a temp plug-in proc as if it were a procedure database procedure
|
||||
*/
|
||||
PikaValueArray * pika_plug_in_manager_call_run_temp (PikaPlugInManager *manager,
|
||||
PikaContext *context,
|
||||
PikaProgress *progress,
|
||||
PikaTemporaryProcedure *procedure,
|
||||
PikaValueArray *args);
|
||||
|
||||
|
||||
#endif /* __PIKA_PLUG_IN_MANAGER_CALL_H__ */
|
137
app/plug-in/pikapluginmanager-data.c
Normal file
137
app/plug-in/pikapluginmanager-data.c
Normal file
@ -0,0 +1,137 @@
|
||||
/* PIKA - Photo and Image Kooker Application
|
||||
* a rebranding of The GNU Image Manipulation Program (created with heckimp)
|
||||
* A derived work which may be trivial. However, any changes may be (C)2023 by Aldercone Studio
|
||||
*
|
||||
* Original copyright, applying to most contents (license remains unchanged):
|
||||
* Copyright (C) 1995 Spencer Kimball and Peter Mattis
|
||||
*
|
||||
* pikapluginmanager-data.c
|
||||
*
|
||||
* 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 3 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, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include "config.h"
|
||||
|
||||
#include <string.h>
|
||||
|
||||
#include <gio/gio.h>
|
||||
|
||||
#include "plug-in-types.h"
|
||||
|
||||
#include "pikapluginmanager.h"
|
||||
#include "pikapluginmanager-data.h"
|
||||
|
||||
|
||||
typedef struct _PikaPlugInData PikaPlugInData;
|
||||
|
||||
struct _PikaPlugInData
|
||||
{
|
||||
gchar *identifier;
|
||||
gint32 bytes;
|
||||
guint8 *data;
|
||||
};
|
||||
|
||||
|
||||
/* public functions */
|
||||
|
||||
void
|
||||
pika_plug_in_manager_data_free (PikaPlugInManager *manager)
|
||||
{
|
||||
g_return_if_fail (PIKA_IS_PLUG_IN_MANAGER (manager));
|
||||
|
||||
if (manager->data_list)
|
||||
{
|
||||
GList *list;
|
||||
|
||||
for (list = manager->data_list;
|
||||
list;
|
||||
list = g_list_next (list))
|
||||
{
|
||||
PikaPlugInData *data = list->data;
|
||||
|
||||
g_free (data->identifier);
|
||||
g_free (data->data);
|
||||
g_slice_free (PikaPlugInData, data);
|
||||
}
|
||||
|
||||
g_list_free (manager->data_list);
|
||||
manager->data_list = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
pika_plug_in_manager_set_data (PikaPlugInManager *manager,
|
||||
const gchar *identifier,
|
||||
gint32 bytes,
|
||||
const guint8 *data)
|
||||
{
|
||||
PikaPlugInData *plug_in_data;
|
||||
GList *list;
|
||||
|
||||
g_return_if_fail (PIKA_IS_PLUG_IN_MANAGER (manager));
|
||||
g_return_if_fail (identifier != NULL);
|
||||
g_return_if_fail (bytes > 0);
|
||||
g_return_if_fail (data != NULL);
|
||||
|
||||
for (list = manager->data_list; list; list = g_list_next (list))
|
||||
{
|
||||
plug_in_data = list->data;
|
||||
|
||||
if (! strcmp (plug_in_data->identifier, identifier))
|
||||
break;
|
||||
}
|
||||
|
||||
/* If there isn't already data with the specified identifier, create one */
|
||||
if (list == NULL)
|
||||
{
|
||||
plug_in_data = g_slice_new0 (PikaPlugInData);
|
||||
plug_in_data->identifier = g_strdup (identifier);
|
||||
|
||||
manager->data_list = g_list_prepend (manager->data_list, plug_in_data);
|
||||
}
|
||||
else
|
||||
{
|
||||
g_free (plug_in_data->data);
|
||||
}
|
||||
|
||||
plug_in_data->bytes = bytes;
|
||||
plug_in_data->data = g_memdup2 (data, bytes);
|
||||
}
|
||||
|
||||
const guint8 *
|
||||
pika_plug_in_manager_get_data (PikaPlugInManager *manager,
|
||||
const gchar *identifier,
|
||||
gint32 *bytes)
|
||||
{
|
||||
GList *list;
|
||||
|
||||
g_return_val_if_fail (PIKA_IS_PLUG_IN_MANAGER (manager), NULL);
|
||||
g_return_val_if_fail (identifier != NULL, NULL);
|
||||
g_return_val_if_fail (bytes != NULL, NULL);
|
||||
|
||||
*bytes = 0;
|
||||
|
||||
for (list = manager->data_list; list; list = g_list_next (list))
|
||||
{
|
||||
PikaPlugInData *plug_in_data = list->data;
|
||||
|
||||
if (! strcmp (plug_in_data->identifier, identifier))
|
||||
{
|
||||
*bytes = plug_in_data->bytes;
|
||||
return plug_in_data->data;
|
||||
}
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
39
app/plug-in/pikapluginmanager-data.h
Normal file
39
app/plug-in/pikapluginmanager-data.h
Normal file
@ -0,0 +1,39 @@
|
||||
/* PIKA - Photo and Image Kooker Application
|
||||
* a rebranding of The GNU Image Manipulation Program (created with heckimp)
|
||||
* A derived work which may be trivial. However, any changes may be (C)2023 by Aldercone Studio
|
||||
*
|
||||
* Original copyright, applying to most contents (license remains unchanged):
|
||||
* Copyright (C) 1995 Spencer Kimball and Peter Mattis
|
||||
*
|
||||
* pikapluginmanager-data.h
|
||||
*
|
||||
* 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 3 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, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#ifndef __PIKA_PLUG_IN_MANAGER_DATA_H__
|
||||
#define __PIKA_PLUG_IN_MANAGER_DATA_H__
|
||||
|
||||
|
||||
void pika_plug_in_manager_data_free (PikaPlugInManager *manager);
|
||||
|
||||
void pika_plug_in_manager_set_data (PikaPlugInManager *manager,
|
||||
const gchar *identifier,
|
||||
gint32 bytes,
|
||||
const guint8 *data);
|
||||
const guint8 * pika_plug_in_manager_get_data (PikaPlugInManager *manager,
|
||||
const gchar *identifier,
|
||||
gint32 *bytes);
|
||||
|
||||
|
||||
#endif /* __PIKA_PLUG_IN_MANAGER_DATA_H__ */
|
908
app/plug-in/pikapluginmanager-file.c
Normal file
908
app/plug-in/pikapluginmanager-file.c
Normal file
@ -0,0 +1,908 @@
|
||||
/* PIKA - Photo and Image Kooker Application
|
||||
* a rebranding of The GNU Image Manipulation Program (created with heckimp)
|
||||
* A derived work which may be trivial. However, any changes may be (C)2023 by Aldercone Studio
|
||||
*
|
||||
* Original copyright, applying to most contents (license remains unchanged):
|
||||
* Copyright (C) 1995 Spencer Kimball and Peter Mattis
|
||||
*
|
||||
* pikapluginmanager-file.c
|
||||
*
|
||||
* 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 3 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, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include "config.h"
|
||||
|
||||
#include <errno.h>
|
||||
#include <string.h>
|
||||
|
||||
#include <gdk-pixbuf/gdk-pixbuf.h>
|
||||
#include <gegl.h>
|
||||
|
||||
#include "libpikabase/pikabase.h"
|
||||
|
||||
#include "plug-in-types.h"
|
||||
|
||||
#include "core/pika.h"
|
||||
#include "core/pika-utils.h"
|
||||
|
||||
#include "pikaplugin.h"
|
||||
#include "pikaplugindef.h"
|
||||
#include "pikapluginmanager.h"
|
||||
#include "pikapluginmanager-file.h"
|
||||
#include "pikapluginprocedure.h"
|
||||
|
||||
#include "pika-log.h"
|
||||
|
||||
#include "pika-intl.h"
|
||||
|
||||
#ifdef G_OS_WIN32
|
||||
#include <stdlib.h>
|
||||
#endif
|
||||
|
||||
|
||||
typedef enum
|
||||
{
|
||||
/* positive values indicate the length of a matching magic */
|
||||
|
||||
FILE_MATCH_NONE = 0,
|
||||
FILE_MATCH_SIZE = -1
|
||||
} FileMatchType;
|
||||
|
||||
|
||||
/* local function prototypes */
|
||||
|
||||
static gboolean file_proc_in_group (PikaPlugInProcedure *file_proc,
|
||||
PikaFileProcedureGroup group);
|
||||
|
||||
static PikaPlugInProcedure * file_proc_find (GSList *procs,
|
||||
GFile *file,
|
||||
GError **error);
|
||||
static PikaPlugInProcedure * file_proc_find_by_prefix (GSList *procs,
|
||||
GFile *file,
|
||||
gboolean skip_magic);
|
||||
static PikaPlugInProcedure * file_proc_find_by_extension (GSList *procs,
|
||||
GFile *file,
|
||||
gboolean skip_magic);
|
||||
static PikaPlugInProcedure * file_proc_find_by_mime_type (GSList *procs,
|
||||
const gchar *mime_type);
|
||||
static PikaPlugInProcedure * file_proc_find_by_name (GSList *procs,
|
||||
GFile *file,
|
||||
gboolean skip_magic);
|
||||
|
||||
static void file_convert_string (const gchar *instr,
|
||||
gchar *outmem,
|
||||
gint maxmem,
|
||||
gint *nmem);
|
||||
static FileMatchType file_check_single_magic (const gchar *offset,
|
||||
const gchar *type,
|
||||
const gchar *value,
|
||||
const guchar *file_head,
|
||||
gint headsize,
|
||||
GFile *file,
|
||||
GInputStream *input);
|
||||
static FileMatchType file_check_magic_list (GSList *magics_list,
|
||||
const guchar *head,
|
||||
gint headsize,
|
||||
GFile *file,
|
||||
GInputStream *input);
|
||||
|
||||
|
||||
/* public functions */
|
||||
|
||||
void
|
||||
pika_plug_in_manager_add_load_procedure (PikaPlugInManager *manager,
|
||||
PikaPlugInProcedure *proc)
|
||||
{
|
||||
g_return_if_fail (PIKA_IS_PLUG_IN_MANAGER (manager));
|
||||
g_return_if_fail (PIKA_IS_PLUG_IN_PROCEDURE (proc));
|
||||
|
||||
if (! g_slist_find (manager->load_procs, proc))
|
||||
manager->load_procs = g_slist_prepend (manager->load_procs, proc);
|
||||
}
|
||||
|
||||
void
|
||||
pika_plug_in_manager_add_save_procedure (PikaPlugInManager *manager,
|
||||
PikaPlugInProcedure *proc)
|
||||
{
|
||||
g_return_if_fail (PIKA_IS_PLUG_IN_MANAGER (manager));
|
||||
g_return_if_fail (PIKA_IS_PLUG_IN_PROCEDURE (proc));
|
||||
|
||||
if (file_proc_in_group (proc, PIKA_FILE_PROCEDURE_GROUP_SAVE))
|
||||
{
|
||||
if (! g_slist_find (manager->save_procs, proc))
|
||||
manager->save_procs = g_slist_prepend (manager->save_procs, proc);
|
||||
}
|
||||
|
||||
if (file_proc_in_group (proc, PIKA_FILE_PROCEDURE_GROUP_EXPORT))
|
||||
{
|
||||
if (! g_slist_find (manager->export_procs, proc))
|
||||
manager->export_procs = g_slist_prepend (manager->export_procs, proc);
|
||||
}
|
||||
}
|
||||
|
||||
GSList *
|
||||
pika_plug_in_manager_get_file_procedures (PikaPlugInManager *manager,
|
||||
PikaFileProcedureGroup group)
|
||||
{
|
||||
g_return_val_if_fail (PIKA_IS_PLUG_IN_MANAGER (manager), NULL);
|
||||
|
||||
switch (group)
|
||||
{
|
||||
case PIKA_FILE_PROCEDURE_GROUP_NONE:
|
||||
return NULL;
|
||||
|
||||
case PIKA_FILE_PROCEDURE_GROUP_OPEN:
|
||||
return manager->display_load_procs;
|
||||
|
||||
case PIKA_FILE_PROCEDURE_GROUP_SAVE:
|
||||
return manager->display_save_procs;
|
||||
|
||||
case PIKA_FILE_PROCEDURE_GROUP_EXPORT:
|
||||
return manager->display_export_procs;
|
||||
|
||||
default:
|
||||
g_return_val_if_reached (NULL);
|
||||
}
|
||||
}
|
||||
|
||||
PikaPlugInProcedure *
|
||||
pika_plug_in_manager_file_procedure_find (PikaPlugInManager *manager,
|
||||
PikaFileProcedureGroup group,
|
||||
GFile *file,
|
||||
GError **error)
|
||||
{
|
||||
g_return_val_if_fail (PIKA_IS_PLUG_IN_MANAGER (manager), NULL);
|
||||
g_return_val_if_fail (G_IS_FILE (file), NULL);
|
||||
g_return_val_if_fail (error == NULL || *error == NULL, NULL);
|
||||
|
||||
switch (group)
|
||||
{
|
||||
case PIKA_FILE_PROCEDURE_GROUP_OPEN:
|
||||
return file_proc_find (manager->load_procs, file, error);
|
||||
|
||||
case PIKA_FILE_PROCEDURE_GROUP_SAVE:
|
||||
return file_proc_find (manager->save_procs, file, error);
|
||||
|
||||
case PIKA_FILE_PROCEDURE_GROUP_EXPORT:
|
||||
return file_proc_find (manager->export_procs, file, error);
|
||||
|
||||
default:
|
||||
g_return_val_if_reached (NULL);
|
||||
}
|
||||
}
|
||||
|
||||
PikaPlugInProcedure *
|
||||
pika_plug_in_manager_file_procedure_find_by_prefix (PikaPlugInManager *manager,
|
||||
PikaFileProcedureGroup group,
|
||||
GFile *file)
|
||||
{
|
||||
g_return_val_if_fail (PIKA_IS_PLUG_IN_MANAGER (manager), NULL);
|
||||
g_return_val_if_fail (G_IS_FILE (file), NULL);
|
||||
|
||||
switch (group)
|
||||
{
|
||||
case PIKA_FILE_PROCEDURE_GROUP_OPEN:
|
||||
return file_proc_find_by_prefix (manager->load_procs, file, FALSE);
|
||||
|
||||
case PIKA_FILE_PROCEDURE_GROUP_SAVE:
|
||||
return file_proc_find_by_prefix (manager->save_procs, file, FALSE);
|
||||
|
||||
case PIKA_FILE_PROCEDURE_GROUP_EXPORT:
|
||||
return file_proc_find_by_prefix (manager->export_procs, file, FALSE);
|
||||
|
||||
default:
|
||||
g_return_val_if_reached (NULL);
|
||||
}
|
||||
}
|
||||
|
||||
PikaPlugInProcedure *
|
||||
pika_plug_in_manager_file_procedure_find_by_extension (PikaPlugInManager *manager,
|
||||
PikaFileProcedureGroup group,
|
||||
GFile *file)
|
||||
{
|
||||
g_return_val_if_fail (PIKA_IS_PLUG_IN_MANAGER (manager), NULL);
|
||||
g_return_val_if_fail (G_IS_FILE (file), NULL);
|
||||
|
||||
switch (group)
|
||||
{
|
||||
case PIKA_FILE_PROCEDURE_GROUP_OPEN:
|
||||
return file_proc_find_by_extension (manager->load_procs, file, FALSE);
|
||||
|
||||
case PIKA_FILE_PROCEDURE_GROUP_SAVE:
|
||||
return file_proc_find_by_extension (manager->save_procs, file, FALSE);
|
||||
|
||||
case PIKA_FILE_PROCEDURE_GROUP_EXPORT:
|
||||
return file_proc_find_by_extension (manager->export_procs, file, FALSE);
|
||||
|
||||
default:
|
||||
g_return_val_if_reached (NULL);
|
||||
}
|
||||
}
|
||||
|
||||
PikaPlugInProcedure *
|
||||
pika_plug_in_manager_file_procedure_find_by_mime_type (PikaPlugInManager *manager,
|
||||
PikaFileProcedureGroup group,
|
||||
const gchar *mime_type)
|
||||
{
|
||||
g_return_val_if_fail (PIKA_IS_PLUG_IN_MANAGER (manager), NULL);
|
||||
g_return_val_if_fail (mime_type != NULL, NULL);
|
||||
|
||||
switch (group)
|
||||
{
|
||||
case PIKA_FILE_PROCEDURE_GROUP_OPEN:
|
||||
return file_proc_find_by_mime_type (manager->load_procs, mime_type);
|
||||
|
||||
case PIKA_FILE_PROCEDURE_GROUP_SAVE:
|
||||
return file_proc_find_by_mime_type (manager->save_procs, mime_type);
|
||||
|
||||
case PIKA_FILE_PROCEDURE_GROUP_EXPORT:
|
||||
return file_proc_find_by_mime_type (manager->export_procs, mime_type);
|
||||
|
||||
default:
|
||||
g_return_val_if_reached (NULL);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/* private functions */
|
||||
|
||||
static gboolean
|
||||
file_proc_in_group (PikaPlugInProcedure *file_proc,
|
||||
PikaFileProcedureGroup group)
|
||||
{
|
||||
const gchar *name = pika_object_get_name (file_proc);
|
||||
gboolean is_xcf_save = FALSE;
|
||||
gboolean is_filter = FALSE;
|
||||
|
||||
is_xcf_save = (strcmp (name, "pika-xcf-save") == 0);
|
||||
|
||||
is_filter = (strcmp (name, "file-gz-save") == 0 ||
|
||||
strcmp (name, "file-bz2-save") == 0 ||
|
||||
strcmp (name, "file-xz-save") == 0);
|
||||
|
||||
switch (group)
|
||||
{
|
||||
case PIKA_FILE_PROCEDURE_GROUP_NONE:
|
||||
return FALSE;
|
||||
|
||||
case PIKA_FILE_PROCEDURE_GROUP_SAVE:
|
||||
/* Only .xcf shall pass */
|
||||
return is_xcf_save || is_filter;
|
||||
|
||||
case PIKA_FILE_PROCEDURE_GROUP_EXPORT:
|
||||
/* Anything but .xcf shall pass */
|
||||
return ! is_xcf_save;
|
||||
|
||||
case PIKA_FILE_PROCEDURE_GROUP_OPEN:
|
||||
/* No filter applied for Open */
|
||||
return TRUE;
|
||||
|
||||
default:
|
||||
case PIKA_FILE_PROCEDURE_GROUP_ANY:
|
||||
return TRUE;
|
||||
}
|
||||
}
|
||||
|
||||
static PikaPlugInProcedure *
|
||||
file_proc_find (GSList *procs,
|
||||
GFile *file,
|
||||
GError **error)
|
||||
{
|
||||
PikaPlugInProcedure *file_proc;
|
||||
PikaPlugInProcedure *size_matched_proc = NULL;
|
||||
gint size_match_count = 0;
|
||||
|
||||
g_return_val_if_fail (procs != NULL, NULL);
|
||||
g_return_val_if_fail (G_IS_FILE (file), NULL);
|
||||
g_return_val_if_fail (error == NULL || *error == NULL, NULL);
|
||||
|
||||
/* First, check magicless prefixes/suffixes */
|
||||
file_proc = file_proc_find_by_name (procs, file, TRUE);
|
||||
|
||||
if (file_proc)
|
||||
return file_proc;
|
||||
|
||||
/* Then look for magics, but not on remote files */
|
||||
if (g_file_is_native (file))
|
||||
{
|
||||
GSList *list;
|
||||
GInputStream *input = NULL;
|
||||
gboolean opened = FALSE;
|
||||
gsize head_size = 0;
|
||||
guchar head[256];
|
||||
FileMatchType best_match_val = FILE_MATCH_NONE;
|
||||
PikaPlugInProcedure *best_file_proc = NULL;
|
||||
|
||||
for (list = procs; list; list = g_slist_next (list))
|
||||
{
|
||||
file_proc = list->data;
|
||||
|
||||
if (file_proc->magics_list)
|
||||
{
|
||||
if (G_UNLIKELY (! opened))
|
||||
{
|
||||
input = G_INPUT_STREAM (g_file_read (file, NULL, error));
|
||||
|
||||
if (input)
|
||||
{
|
||||
g_input_stream_read_all (input,
|
||||
head, sizeof (head),
|
||||
&head_size, NULL, error);
|
||||
|
||||
if (head_size < 4)
|
||||
{
|
||||
g_object_unref (input);
|
||||
input = NULL;
|
||||
}
|
||||
else
|
||||
{
|
||||
GDataInputStream *data_input;
|
||||
|
||||
data_input = g_data_input_stream_new (input);
|
||||
g_object_unref (input);
|
||||
input = G_INPUT_STREAM (data_input);
|
||||
}
|
||||
}
|
||||
|
||||
opened = TRUE;
|
||||
}
|
||||
|
||||
if (head_size >= 4)
|
||||
{
|
||||
FileMatchType match_val;
|
||||
|
||||
match_val = file_check_magic_list (file_proc->magics_list,
|
||||
head, head_size,
|
||||
file, input);
|
||||
|
||||
if (match_val == FILE_MATCH_SIZE)
|
||||
{
|
||||
/* Use it only if no other magic matches */
|
||||
size_match_count++;
|
||||
size_matched_proc = file_proc;
|
||||
}
|
||||
else if (match_val != FILE_MATCH_NONE)
|
||||
{
|
||||
PIKA_LOG (MAGIC_MATCH,
|
||||
"magic match %d on %s\n",
|
||||
match_val,
|
||||
pika_object_get_name (file_proc));
|
||||
|
||||
if (match_val > best_match_val)
|
||||
{
|
||||
best_match_val = match_val;
|
||||
best_file_proc = file_proc;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (input)
|
||||
g_object_unref (input);
|
||||
|
||||
if (best_file_proc)
|
||||
{
|
||||
PIKA_LOG (MAGIC_MATCH,
|
||||
"best magic match on %s\n",
|
||||
pika_object_get_name (best_file_proc));
|
||||
|
||||
return best_file_proc;
|
||||
}
|
||||
}
|
||||
|
||||
if (size_match_count == 1)
|
||||
return size_matched_proc;
|
||||
|
||||
/* As a last resort, try matching by name, not skipping magic procs */
|
||||
file_proc = file_proc_find_by_name (procs, file, FALSE);
|
||||
|
||||
if (file_proc)
|
||||
{
|
||||
/* we found a procedure, clear error that might have been set */
|
||||
g_clear_error (error);
|
||||
}
|
||||
else
|
||||
{
|
||||
/* set an error message unless one was already set */
|
||||
if (error && *error == NULL)
|
||||
g_set_error_literal (error, G_FILE_ERROR, G_FILE_ERROR_FAILED,
|
||||
_("Unknown file type"));
|
||||
}
|
||||
|
||||
return file_proc;
|
||||
}
|
||||
|
||||
static PikaPlugInProcedure *
|
||||
file_proc_find_by_mime_type (GSList *procs,
|
||||
const gchar *mime_type)
|
||||
{
|
||||
GSList *list;
|
||||
|
||||
g_return_val_if_fail (mime_type != NULL, NULL);
|
||||
|
||||
for (list = procs; list; list = g_slist_next (list))
|
||||
{
|
||||
PikaPlugInProcedure *proc = list->data;
|
||||
GSList *mime;
|
||||
|
||||
for (mime = proc->mime_types_list; mime; mime = g_slist_next (mime))
|
||||
{
|
||||
if (! strcmp (mime_type, mime->data))
|
||||
return proc;
|
||||
}
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static PikaPlugInProcedure *
|
||||
file_proc_find_by_prefix (GSList *procs,
|
||||
GFile *file,
|
||||
gboolean skip_magic)
|
||||
{
|
||||
gchar *uri = g_file_get_uri (file);
|
||||
GSList *p;
|
||||
|
||||
for (p = procs; p; p = g_slist_next (p))
|
||||
{
|
||||
PikaPlugInProcedure *proc = p->data;
|
||||
GSList *prefixes;
|
||||
|
||||
if (skip_magic && proc->magics_list)
|
||||
continue;
|
||||
|
||||
for (prefixes = proc->prefixes_list;
|
||||
prefixes;
|
||||
prefixes = g_slist_next (prefixes))
|
||||
{
|
||||
if (g_str_has_prefix (uri, prefixes->data))
|
||||
{
|
||||
g_free (uri);
|
||||
return proc;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
g_free (uri);
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static PikaPlugInProcedure *
|
||||
file_proc_find_by_extension (GSList *procs,
|
||||
GFile *file,
|
||||
gboolean skip_magic)
|
||||
{
|
||||
gchar *ext = pika_file_get_extension (file);
|
||||
|
||||
if (ext)
|
||||
{
|
||||
GSList *p;
|
||||
|
||||
for (p = procs; p; p = g_slist_next (p))
|
||||
{
|
||||
PikaPlugInProcedure *proc = p->data;
|
||||
|
||||
if (skip_magic && proc->magics_list)
|
||||
continue;
|
||||
|
||||
if (g_slist_find_custom (proc->extensions_list,
|
||||
ext + 1,
|
||||
(GCompareFunc) g_ascii_strcasecmp))
|
||||
{
|
||||
g_free (ext);
|
||||
|
||||
return proc;
|
||||
}
|
||||
}
|
||||
|
||||
g_free (ext);
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static PikaPlugInProcedure *
|
||||
file_proc_find_by_name (GSList *procs,
|
||||
GFile *file,
|
||||
gboolean skip_magic)
|
||||
{
|
||||
PikaPlugInProcedure *proc;
|
||||
|
||||
proc = file_proc_find_by_prefix (procs, file, skip_magic);
|
||||
|
||||
if (! proc)
|
||||
proc = file_proc_find_by_extension (procs, file, skip_magic);
|
||||
|
||||
return proc;
|
||||
}
|
||||
|
||||
static void
|
||||
file_convert_string (const gchar *instr,
|
||||
gchar *outmem,
|
||||
gint maxmem,
|
||||
gint *nmem)
|
||||
{
|
||||
/* Convert a string in C-notation to array of char */
|
||||
const guchar *uin = (const guchar *) instr;
|
||||
guchar *uout = (guchar *) outmem;
|
||||
guchar tmp[5], *tmpptr;
|
||||
guint k;
|
||||
|
||||
while ((*uin != '\0') && ((((gchar *) uout) - outmem) < maxmem))
|
||||
{
|
||||
if (*uin != '\\') /* Not an escaped character ? */
|
||||
{
|
||||
*(uout++) = *(uin++);
|
||||
continue;
|
||||
}
|
||||
|
||||
if (*(++uin) == '\0')
|
||||
{
|
||||
*(uout++) = '\\';
|
||||
break;
|
||||
}
|
||||
|
||||
switch (*uin)
|
||||
{
|
||||
case '0': case '1': case '2': case '3': /* octal */
|
||||
for (tmpptr = tmp; (tmpptr - tmp) <= 3;)
|
||||
{
|
||||
*(tmpptr++) = *(uin++);
|
||||
if ( (*uin == '\0') || (!g_ascii_isdigit (*uin))
|
||||
|| (*uin == '8') || (*uin == '9'))
|
||||
break;
|
||||
}
|
||||
|
||||
*tmpptr = '\0';
|
||||
sscanf ((gchar *) tmp, "%o", &k);
|
||||
*(uout++) = k;
|
||||
break;
|
||||
|
||||
case 'a': *(uout++) = '\a'; uin++; break;
|
||||
case 'b': *(uout++) = '\b'; uin++; break;
|
||||
case 't': *(uout++) = '\t'; uin++; break;
|
||||
case 'n': *(uout++) = '\n'; uin++; break;
|
||||
case 'v': *(uout++) = '\v'; uin++; break;
|
||||
case 'f': *(uout++) = '\f'; uin++; break;
|
||||
case 'r': *(uout++) = '\r'; uin++; break;
|
||||
|
||||
default : *(uout++) = *(uin++); break;
|
||||
}
|
||||
}
|
||||
|
||||
*nmem = ((gchar *) uout) - outmem;
|
||||
}
|
||||
|
||||
static FileMatchType
|
||||
file_check_single_magic (const gchar *offset,
|
||||
const gchar *type,
|
||||
const gchar *value,
|
||||
const guchar *file_head,
|
||||
gint headsize,
|
||||
GFile *file,
|
||||
GInputStream *input)
|
||||
|
||||
{
|
||||
FileMatchType found = FILE_MATCH_NONE;
|
||||
glong offs;
|
||||
gulong num_testval;
|
||||
gulong num_operator_val;
|
||||
gint numbytes, k;
|
||||
const gchar *num_operator_ptr;
|
||||
gchar num_operator;
|
||||
|
||||
/* Check offset */
|
||||
if (sscanf (offset, "%ld", &offs) != 1)
|
||||
return FILE_MATCH_NONE;
|
||||
|
||||
/* Check type of test */
|
||||
num_operator_ptr = NULL;
|
||||
num_operator = '\0';
|
||||
|
||||
if (g_str_has_prefix (type, "byte"))
|
||||
{
|
||||
numbytes = 1;
|
||||
num_operator_ptr = type + strlen ("byte");
|
||||
}
|
||||
else if (g_str_has_prefix (type, "short"))
|
||||
{
|
||||
numbytes = 2;
|
||||
num_operator_ptr = type + strlen ("short");
|
||||
}
|
||||
else if (g_str_has_prefix (type, "long"))
|
||||
{
|
||||
numbytes = 4;
|
||||
num_operator_ptr = type + strlen ("long");
|
||||
}
|
||||
else if (g_str_has_prefix (type, "size"))
|
||||
{
|
||||
numbytes = 5;
|
||||
}
|
||||
else if (strcmp (type, "string") == 0)
|
||||
{
|
||||
numbytes = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
return FILE_MATCH_NONE;
|
||||
}
|
||||
|
||||
/* Check numerical operator value if present */
|
||||
if (num_operator_ptr && (*num_operator_ptr == '&'))
|
||||
{
|
||||
if (g_ascii_isdigit (num_operator_ptr[1]))
|
||||
{
|
||||
if (num_operator_ptr[1] != '0') /* decimal */
|
||||
sscanf (num_operator_ptr+1, "%lu", &num_operator_val);
|
||||
else if (num_operator_ptr[2] == 'x') /* hexadecimal */
|
||||
sscanf (num_operator_ptr+3, "%lx", &num_operator_val);
|
||||
else /* octal */
|
||||
sscanf (num_operator_ptr+2, "%lo", &num_operator_val);
|
||||
|
||||
num_operator = *num_operator_ptr;
|
||||
}
|
||||
}
|
||||
|
||||
if (numbytes > 0)
|
||||
{
|
||||
/* Numerical test */
|
||||
|
||||
gchar num_test = '=';
|
||||
gulong fileval = 0;
|
||||
|
||||
/* Check test value */
|
||||
if ((value[0] == '>') || (value[0] == '<'))
|
||||
{
|
||||
num_test = value[0];
|
||||
value++;
|
||||
}
|
||||
|
||||
errno = 0;
|
||||
num_testval = strtol (value, NULL, 0);
|
||||
|
||||
if (errno != 0)
|
||||
return FILE_MATCH_NONE;
|
||||
|
||||
if (numbytes == 5)
|
||||
{
|
||||
/* Check for file size */
|
||||
|
||||
GFileInfo *info = g_file_query_info (file,
|
||||
G_FILE_ATTRIBUTE_STANDARD_SIZE,
|
||||
G_FILE_QUERY_INFO_NONE,
|
||||
NULL, NULL);
|
||||
if (! info)
|
||||
return FILE_MATCH_NONE;
|
||||
|
||||
fileval = g_file_info_get_size (info);
|
||||
g_object_unref (info);
|
||||
}
|
||||
else if (offs >= 0 &&
|
||||
(offs + numbytes <= headsize))
|
||||
{
|
||||
/* We have it in memory */
|
||||
|
||||
for (k = 0; k < numbytes; k++)
|
||||
fileval = (fileval << 8) | (glong) file_head[offs + k];
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Read it from file */
|
||||
|
||||
if (! g_seekable_seek (G_SEEKABLE (input), offs,
|
||||
(offs >= 0) ? G_SEEK_SET : G_SEEK_END,
|
||||
NULL, NULL))
|
||||
return FILE_MATCH_NONE;
|
||||
|
||||
for (k = 0; k < numbytes; k++)
|
||||
{
|
||||
guchar byte;
|
||||
GError *error = NULL;
|
||||
|
||||
byte = g_data_input_stream_read_byte (G_DATA_INPUT_STREAM (input),
|
||||
NULL, &error);
|
||||
if (error)
|
||||
{
|
||||
g_clear_error (&error);
|
||||
return FILE_MATCH_NONE;
|
||||
}
|
||||
|
||||
fileval = (fileval << 8) | byte;
|
||||
}
|
||||
}
|
||||
|
||||
if (num_operator == '&')
|
||||
fileval &= num_operator_val;
|
||||
|
||||
if (num_test == '<')
|
||||
{
|
||||
if (fileval < num_testval)
|
||||
found = numbytes;
|
||||
}
|
||||
else if (num_test == '>')
|
||||
{
|
||||
if (fileval > num_testval)
|
||||
found = numbytes;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (fileval == num_testval)
|
||||
found = numbytes;
|
||||
}
|
||||
|
||||
if (found && (numbytes == 5))
|
||||
found = FILE_MATCH_SIZE;
|
||||
}
|
||||
else if (numbytes == 0)
|
||||
{
|
||||
/* String test */
|
||||
|
||||
gchar mem_testval[256];
|
||||
|
||||
file_convert_string (value,
|
||||
mem_testval, sizeof (mem_testval),
|
||||
&numbytes);
|
||||
|
||||
if (numbytes <= 0)
|
||||
return FILE_MATCH_NONE;
|
||||
|
||||
if (offs >= 0 &&
|
||||
(offs + numbytes <= headsize))
|
||||
{
|
||||
/* We have it in memory */
|
||||
|
||||
if (memcmp (mem_testval, file_head + offs, numbytes) == 0)
|
||||
found = numbytes;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Read it from file */
|
||||
|
||||
if (! g_seekable_seek (G_SEEKABLE (input), offs,
|
||||
(offs >= 0) ? G_SEEK_SET : G_SEEK_END,
|
||||
NULL, NULL))
|
||||
return FILE_MATCH_NONE;
|
||||
|
||||
for (k = 0; k < numbytes; k++)
|
||||
{
|
||||
guchar byte;
|
||||
GError *error = NULL;
|
||||
|
||||
byte = g_data_input_stream_read_byte (G_DATA_INPUT_STREAM (input),
|
||||
NULL, &error);
|
||||
if (error)
|
||||
{
|
||||
g_clear_error (&error);
|
||||
|
||||
return FILE_MATCH_NONE;
|
||||
}
|
||||
|
||||
if (byte != mem_testval[k])
|
||||
return FILE_MATCH_NONE;
|
||||
}
|
||||
|
||||
found = numbytes;
|
||||
}
|
||||
}
|
||||
|
||||
return found;
|
||||
}
|
||||
|
||||
static FileMatchType
|
||||
file_check_magic_list (GSList *magics_list,
|
||||
const guchar *head,
|
||||
gint headsize,
|
||||
GFile *file,
|
||||
GInputStream *input)
|
||||
|
||||
{
|
||||
gboolean and = FALSE;
|
||||
gboolean found = FALSE;
|
||||
FileMatchType best_match_val = FILE_MATCH_NONE;
|
||||
FileMatchType match_val = FILE_MATCH_NONE;
|
||||
|
||||
for (; magics_list; magics_list = magics_list->next)
|
||||
{
|
||||
const gchar *offset;
|
||||
const gchar *type;
|
||||
const gchar *value;
|
||||
FileMatchType single_match_val = FILE_MATCH_NONE;
|
||||
|
||||
if ((offset = magics_list->data) == NULL) return FILE_MATCH_NONE;
|
||||
if ((magics_list = magics_list->next) == NULL) return FILE_MATCH_NONE;
|
||||
if ((type = magics_list->data) == NULL) return FILE_MATCH_NONE;
|
||||
if ((magics_list = magics_list->next) == NULL) return FILE_MATCH_NONE;
|
||||
if ((value = magics_list->data) == NULL) return FILE_MATCH_NONE;
|
||||
|
||||
single_match_val = file_check_single_magic (offset, type, value,
|
||||
head, headsize,
|
||||
file, input);
|
||||
|
||||
if (and)
|
||||
found = found && (single_match_val != FILE_MATCH_NONE);
|
||||
else
|
||||
found = (single_match_val != FILE_MATCH_NONE);
|
||||
|
||||
if (found)
|
||||
{
|
||||
if (match_val == FILE_MATCH_NONE)
|
||||
{
|
||||
/* if we have no match yet, this is it in any case */
|
||||
|
||||
match_val = single_match_val;
|
||||
}
|
||||
else if (single_match_val != FILE_MATCH_NONE)
|
||||
{
|
||||
/* else if we have a match on this one, combine it with the
|
||||
* existing return value
|
||||
*/
|
||||
|
||||
if (single_match_val == FILE_MATCH_SIZE)
|
||||
{
|
||||
/* if we already have a magic match, simply increase
|
||||
* that by one to indicate "better match", not perfect
|
||||
* but better than losing the additional size match
|
||||
* entirely
|
||||
*/
|
||||
if (match_val != FILE_MATCH_SIZE)
|
||||
match_val += 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* if we already have a magic match, simply add to its
|
||||
* length; otherwise if we already have a size match,
|
||||
* combine it with this match, see comment above
|
||||
*/
|
||||
if (match_val != FILE_MATCH_SIZE)
|
||||
match_val += single_match_val;
|
||||
else
|
||||
match_val = single_match_val + 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
match_val = FILE_MATCH_NONE;
|
||||
}
|
||||
|
||||
and = (strchr (offset, '&') != NULL);
|
||||
|
||||
if (! and)
|
||||
{
|
||||
/* when done with this 'and' list, update best_match_val */
|
||||
|
||||
if (best_match_val == FILE_MATCH_NONE)
|
||||
{
|
||||
/* if we have no best match yet, this is it */
|
||||
|
||||
best_match_val = match_val;
|
||||
}
|
||||
else if (match_val != FILE_MATCH_NONE)
|
||||
{
|
||||
/* otherwise if this was a match, update the best match, note
|
||||
* that by using MAX we will not overwrite a magic match
|
||||
* with a size match
|
||||
*/
|
||||
|
||||
best_match_val = MAX (best_match_val, match_val);
|
||||
}
|
||||
|
||||
match_val = FILE_MATCH_NONE;
|
||||
}
|
||||
}
|
||||
|
||||
return best_match_val;
|
||||
}
|
55
app/plug-in/pikapluginmanager-file.h
Normal file
55
app/plug-in/pikapluginmanager-file.h
Normal file
@ -0,0 +1,55 @@
|
||||
/* PIKA - Photo and Image Kooker Application
|
||||
* a rebranding of The GNU Image Manipulation Program (created with heckimp)
|
||||
* A derived work which may be trivial. However, any changes may be (C)2023 by Aldercone Studio
|
||||
*
|
||||
* Original copyright, applying to most contents (license remains unchanged):
|
||||
* Copyright (C) 1995 Spencer Kimball and Peter Mattis
|
||||
*
|
||||
* pikapluginmanager-file.h
|
||||
*
|
||||
* 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 3 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, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#ifndef __PIKA_PLUG_IN_MANAGER_FILE_H__
|
||||
#define __PIKA_PLUG_IN_MANAGER_FILE_H__
|
||||
|
||||
|
||||
void pika_plug_in_manager_add_load_procedure (PikaPlugInManager *manager,
|
||||
PikaPlugInProcedure *proc);
|
||||
void pika_plug_in_manager_add_save_procedure (PikaPlugInManager *manager,
|
||||
PikaPlugInProcedure *proc);
|
||||
|
||||
GSList * pika_plug_in_manager_get_file_procedures (PikaPlugInManager *manager,
|
||||
PikaFileProcedureGroup group);
|
||||
|
||||
PikaPlugInProcedure *
|
||||
pika_plug_in_manager_file_procedure_find (PikaPlugInManager *manager,
|
||||
PikaFileProcedureGroup group,
|
||||
GFile *file,
|
||||
GError **error);
|
||||
PikaPlugInProcedure *
|
||||
pika_plug_in_manager_file_procedure_find_by_prefix (PikaPlugInManager *manager,
|
||||
PikaFileProcedureGroup group,
|
||||
GFile *file);
|
||||
PikaPlugInProcedure *
|
||||
pika_plug_in_manager_file_procedure_find_by_extension (PikaPlugInManager *manager,
|
||||
PikaFileProcedureGroup group,
|
||||
GFile *file);
|
||||
PikaPlugInProcedure *
|
||||
pika_plug_in_manager_file_procedure_find_by_mime_type (PikaPlugInManager *manager,
|
||||
PikaFileProcedureGroup group,
|
||||
const gchar *mime_type);
|
||||
|
||||
|
||||
#endif /* __PIKA_PLUG_IN_MANAGER_FILE_H__ */
|
164
app/plug-in/pikapluginmanager-help-domain.c
Normal file
164
app/plug-in/pikapluginmanager-help-domain.c
Normal file
@ -0,0 +1,164 @@
|
||||
/* PIKA - Photo and Image Kooker Application
|
||||
* a rebranding of The GNU Image Manipulation Program (created with heckimp)
|
||||
* A derived work which may be trivial. However, any changes may be (C)2023 by Aldercone Studio
|
||||
*
|
||||
* Original copyright, applying to most contents (license remains unchanged):
|
||||
* Copyright (C) 1995 Spencer Kimball and Peter Mattis
|
||||
*
|
||||
* pikapluginmanager-help-domain.c
|
||||
*
|
||||
* 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 3 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, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include "config.h"
|
||||
|
||||
#include <string.h>
|
||||
|
||||
#include <gio/gio.h>
|
||||
|
||||
#include "plug-in-types.h"
|
||||
|
||||
#include "pikapluginmanager.h"
|
||||
#include "pikapluginmanager-help-domain.h"
|
||||
|
||||
|
||||
typedef struct _PikaPlugInHelpDomain PikaPlugInHelpDomain;
|
||||
|
||||
struct _PikaPlugInHelpDomain
|
||||
{
|
||||
GFile *file;
|
||||
gchar *domain_name;
|
||||
gchar *domain_uri;
|
||||
};
|
||||
|
||||
|
||||
void
|
||||
pika_plug_in_manager_help_domain_exit (PikaPlugInManager *manager)
|
||||
{
|
||||
GSList *list;
|
||||
|
||||
g_return_if_fail (PIKA_IS_PLUG_IN_MANAGER (manager));
|
||||
|
||||
for (list = manager->help_domains; list; list = list->next)
|
||||
{
|
||||
PikaPlugInHelpDomain *domain = list->data;
|
||||
|
||||
g_object_unref (domain->file);
|
||||
g_free (domain->domain_name);
|
||||
g_free (domain->domain_uri);
|
||||
g_slice_free (PikaPlugInHelpDomain, domain);
|
||||
}
|
||||
|
||||
g_slist_free (manager->help_domains);
|
||||
manager->help_domains = NULL;
|
||||
}
|
||||
|
||||
void
|
||||
pika_plug_in_manager_add_help_domain (PikaPlugInManager *manager,
|
||||
GFile *file,
|
||||
const gchar *domain_name,
|
||||
const gchar *domain_uri)
|
||||
{
|
||||
PikaPlugInHelpDomain *domain;
|
||||
|
||||
g_return_if_fail (PIKA_IS_PLUG_IN_MANAGER (manager));
|
||||
g_return_if_fail (G_IS_FILE (file));
|
||||
g_return_if_fail (domain_name != NULL);
|
||||
|
||||
domain = g_slice_new (PikaPlugInHelpDomain);
|
||||
|
||||
domain->file = g_object_ref (file);
|
||||
domain->domain_name = g_strdup (domain_name);
|
||||
domain->domain_uri = g_strdup (domain_uri);
|
||||
|
||||
manager->help_domains = g_slist_prepend (manager->help_domains, domain);
|
||||
|
||||
#ifdef VERBOSE
|
||||
g_print ("added help domain \"%s\" for base uri \"%s\"\n",
|
||||
domain->domain_name ? domain->domain_name : "(null)",
|
||||
domain->domain_uri ? domain->domain_uri : "(null)");
|
||||
#endif
|
||||
}
|
||||
|
||||
const gchar *
|
||||
pika_plug_in_manager_get_help_domain (PikaPlugInManager *manager,
|
||||
GFile *file,
|
||||
const gchar **domain_uri)
|
||||
{
|
||||
GSList *list;
|
||||
|
||||
g_return_val_if_fail (PIKA_IS_PLUG_IN_MANAGER (manager), NULL);
|
||||
g_return_val_if_fail (file == NULL || G_IS_FILE (file), NULL);
|
||||
|
||||
if (domain_uri)
|
||||
*domain_uri = NULL;
|
||||
|
||||
/* A NULL prog_name is PIKA itself, return the default domain */
|
||||
if (! file)
|
||||
return NULL;
|
||||
|
||||
for (list = manager->help_domains; list; list = list->next)
|
||||
{
|
||||
PikaPlugInHelpDomain *domain = list->data;
|
||||
|
||||
if (domain && domain->file &&
|
||||
g_file_equal (domain->file, file))
|
||||
{
|
||||
if (domain_uri && domain->domain_uri)
|
||||
*domain_uri = domain->domain_uri;
|
||||
|
||||
return domain->domain_name;
|
||||
}
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
gint
|
||||
pika_plug_in_manager_get_help_domains (PikaPlugInManager *manager,
|
||||
gchar ***help_domains,
|
||||
gchar ***help_uris)
|
||||
{
|
||||
gint n_domains;
|
||||
|
||||
g_return_val_if_fail (PIKA_IS_PLUG_IN_MANAGER (manager), 0);
|
||||
g_return_val_if_fail (help_domains != NULL, 0);
|
||||
g_return_val_if_fail (help_uris != NULL, 0);
|
||||
|
||||
n_domains = g_slist_length (manager->help_domains);
|
||||
|
||||
if (n_domains > 0)
|
||||
{
|
||||
GSList *list;
|
||||
gint i;
|
||||
|
||||
*help_domains = g_new0 (gchar *, n_domains + 1);
|
||||
*help_uris = g_new0 (gchar *, n_domains + 1);
|
||||
|
||||
for (list = manager->help_domains, i = 0; list; list = list->next, i++)
|
||||
{
|
||||
PikaPlugInHelpDomain *domain = list->data;
|
||||
|
||||
(*help_domains)[i] = g_strdup (domain->domain_name);
|
||||
(*help_uris)[i] = g_strdup (domain->domain_uri);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
*help_domains = NULL;
|
||||
*help_uris = NULL;
|
||||
}
|
||||
|
||||
return n_domains;
|
||||
}
|
47
app/plug-in/pikapluginmanager-help-domain.h
Normal file
47
app/plug-in/pikapluginmanager-help-domain.h
Normal file
@ -0,0 +1,47 @@
|
||||
/* PIKA - Photo and Image Kooker Application
|
||||
* a rebranding of The GNU Image Manipulation Program (created with heckimp)
|
||||
* A derived work which may be trivial. However, any changes may be (C)2023 by Aldercone Studio
|
||||
*
|
||||
* Original copyright, applying to most contents (license remains unchanged):
|
||||
* Copyright (C) 1995 Spencer Kimball and Peter Mattis
|
||||
*
|
||||
* pikapluginmanager-help-domain.h
|
||||
*
|
||||
* 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 3 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, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#ifndef __PIKA_PLUG_IN_MANAGER_HELP_DOMAIN_H__
|
||||
#define __PIKA_PLUG_IN_MANAGER_HELP_DOMAIN_H__
|
||||
|
||||
|
||||
void pika_plug_in_manager_help_domain_exit (PikaPlugInManager *manager);
|
||||
|
||||
/* Add a help domain */
|
||||
void pika_plug_in_manager_add_help_domain (PikaPlugInManager *manager,
|
||||
GFile *file,
|
||||
const gchar *domain_name,
|
||||
const gchar *domain_uri);
|
||||
|
||||
/* Retrieve a plug-ins help domain */
|
||||
const gchar * pika_plug_in_manager_get_help_domain (PikaPlugInManager *manager,
|
||||
GFile *file,
|
||||
const gchar **help_uri);
|
||||
|
||||
/* Retrieve all help domains */
|
||||
gint pika_plug_in_manager_get_help_domains (PikaPlugInManager *manager,
|
||||
gchar ***help_domains,
|
||||
gchar ***help_uris);
|
||||
|
||||
|
||||
#endif /* __PIKA_PLUG_IN_MANAGER_HELP_DOMAIN_H__ */
|
96
app/plug-in/pikapluginmanager-menu-branch.c
Normal file
96
app/plug-in/pikapluginmanager-menu-branch.c
Normal file
@ -0,0 +1,96 @@
|
||||
/* PIKA - Photo and Image Kooker Application
|
||||
* a rebranding of The GNU Image Manipulation Program (created with heckimp)
|
||||
* A derived work which may be trivial. However, any changes may be (C)2023 by Aldercone Studio
|
||||
*
|
||||
* Original copyright, applying to most contents (license remains unchanged):
|
||||
* Copyright (C) 1995 Spencer Kimball and Peter Mattis
|
||||
*
|
||||
* pikapluginmanager-menu-branch.c
|
||||
*
|
||||
* 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 3 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, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include "config.h"
|
||||
|
||||
#include <gio/gio.h>
|
||||
|
||||
#include "plug-in-types.h"
|
||||
|
||||
#include "pikapluginmanager.h"
|
||||
#include "pikapluginmanager-menu-branch.h"
|
||||
#include "plug-in-menu-path.h"
|
||||
|
||||
|
||||
/* public functions */
|
||||
|
||||
void
|
||||
pika_plug_in_manager_menu_branch_exit (PikaPlugInManager *manager)
|
||||
{
|
||||
GSList *list;
|
||||
|
||||
g_return_if_fail (PIKA_IS_PLUG_IN_MANAGER (manager));
|
||||
|
||||
for (list = manager->menu_branches; list; list = list->next)
|
||||
{
|
||||
PikaPlugInMenuBranch *branch = list->data;
|
||||
|
||||
g_object_unref (branch->file);
|
||||
g_free (branch->menu_path);
|
||||
g_free (branch->menu_label);
|
||||
g_slice_free (PikaPlugInMenuBranch, branch);
|
||||
}
|
||||
|
||||
g_slist_free (manager->menu_branches);
|
||||
manager->menu_branches = NULL;
|
||||
}
|
||||
|
||||
void
|
||||
pika_plug_in_manager_add_menu_branch (PikaPlugInManager *manager,
|
||||
GFile *file,
|
||||
const gchar *menu_path,
|
||||
const gchar *menu_label)
|
||||
{
|
||||
PikaPlugInMenuBranch *branch;
|
||||
|
||||
g_return_if_fail (PIKA_IS_PLUG_IN_MANAGER (manager));
|
||||
g_return_if_fail (G_IS_FILE (file));
|
||||
g_return_if_fail (menu_path != NULL);
|
||||
g_return_if_fail (menu_label != NULL);
|
||||
|
||||
branch = g_slice_new (PikaPlugInMenuBranch);
|
||||
|
||||
branch->file = g_object_ref (file);
|
||||
branch->menu_path = plug_in_menu_path_map (menu_path, menu_label);
|
||||
branch->menu_label = g_strdup (menu_label);
|
||||
|
||||
manager->menu_branches = g_slist_append (manager->menu_branches, branch);
|
||||
|
||||
g_signal_emit_by_name (manager, "menu-branch-added",
|
||||
branch->file,
|
||||
branch->menu_path,
|
||||
branch->menu_label);
|
||||
|
||||
#ifdef VERBOSE
|
||||
g_print ("added menu branch \"%s\" at path \"%s\"\n",
|
||||
branch->menu_label, branch->menu_path);
|
||||
#endif
|
||||
}
|
||||
|
||||
GSList *
|
||||
pika_plug_in_manager_get_menu_branches (PikaPlugInManager *manager)
|
||||
{
|
||||
g_return_val_if_fail (PIKA_IS_PLUG_IN_MANAGER (manager), NULL);
|
||||
|
||||
return manager->menu_branches;
|
||||
}
|
46
app/plug-in/pikapluginmanager-menu-branch.h
Normal file
46
app/plug-in/pikapluginmanager-menu-branch.h
Normal file
@ -0,0 +1,46 @@
|
||||
/* PIKA - Photo and Image Kooker Application
|
||||
* a rebranding of The GNU Image Manipulation Program (created with heckimp)
|
||||
* A derived work which may be trivial. However, any changes may be (C)2023 by Aldercone Studio
|
||||
*
|
||||
* Original copyright, applying to most contents (license remains unchanged):
|
||||
* Copyright (C) 1995 Spencer Kimball and Peter Mattis
|
||||
*
|
||||
* pikapluginmanager-menu-branch.h
|
||||
*
|
||||
* 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 3 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, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#ifndef __PIKA_PLUG_IN_MANAGER_MENU_BRANCH_H__
|
||||
#define __PIKA_PLUG_IN_MANAGER_MENU_BRANCH_H__
|
||||
|
||||
|
||||
struct _PikaPlugInMenuBranch
|
||||
{
|
||||
GFile *file;
|
||||
gchar *menu_path;
|
||||
gchar *menu_label;
|
||||
};
|
||||
|
||||
|
||||
void pika_plug_in_manager_menu_branch_exit (PikaPlugInManager *manager);
|
||||
|
||||
/* Add a menu branch */
|
||||
void pika_plug_in_manager_add_menu_branch (PikaPlugInManager *manager,
|
||||
GFile *file,
|
||||
const gchar *menu_path,
|
||||
const gchar *menu_label);
|
||||
GSList * pika_plug_in_manager_get_menu_branches (PikaPlugInManager *manager);
|
||||
|
||||
|
||||
#endif /* __PIKA_PLUG_IN_MANAGER_MENU_BRANCH_H__ */
|
132
app/plug-in/pikapluginmanager-query.c
Normal file
132
app/plug-in/pikapluginmanager-query.c
Normal file
@ -0,0 +1,132 @@
|
||||
/* PIKA - Photo and Image Kooker Application
|
||||
* a rebranding of The GNU Image Manipulation Program (created with heckimp)
|
||||
* A derived work which may be trivial. However, any changes may be (C)2023 by Aldercone Studio
|
||||
*
|
||||
* Original copyright, applying to most contents (license remains unchanged):
|
||||
* Copyright (C) 1995-2003 Spencer Kimball and Peter Mattis
|
||||
*
|
||||
* plug-ins-query.c
|
||||
*
|
||||
* 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 3 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, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include "config.h"
|
||||
|
||||
#include <string.h>
|
||||
|
||||
#include <gdk-pixbuf/gdk-pixbuf.h>
|
||||
#include <gegl.h>
|
||||
|
||||
#include "libpikabase/pikabase.h"
|
||||
|
||||
#include "plug-in-types.h"
|
||||
|
||||
#include "pikapluginmanager.h"
|
||||
#include "pikapluginmanager-query.h"
|
||||
#include "pikapluginprocedure.h"
|
||||
|
||||
|
||||
static gboolean
|
||||
match_string (GRegex *regex,
|
||||
gchar *string)
|
||||
{
|
||||
return g_regex_match (regex, string, 0, NULL);
|
||||
}
|
||||
|
||||
gint
|
||||
pika_plug_in_manager_query (PikaPlugInManager *manager,
|
||||
const gchar *search_str,
|
||||
gchar ***procedure_strs,
|
||||
gchar ***accel_strs,
|
||||
gchar ***prog_strs,
|
||||
gint32 **time_ints)
|
||||
{
|
||||
gint num_plugins = 0;
|
||||
GRegex *sregex = NULL;
|
||||
GSList *matched = NULL;
|
||||
GSList *list;
|
||||
gint i;
|
||||
|
||||
g_return_val_if_fail (PIKA_IS_PLUG_IN_MANAGER (manager), 0);
|
||||
g_return_val_if_fail (procedure_strs != NULL, 0);
|
||||
g_return_val_if_fail (accel_strs != NULL, 0);
|
||||
g_return_val_if_fail (prog_strs != NULL, 0);
|
||||
g_return_val_if_fail (time_ints != NULL, 0);
|
||||
|
||||
*procedure_strs = NULL;
|
||||
*accel_strs = NULL;
|
||||
*prog_strs = NULL;
|
||||
*time_ints = NULL;
|
||||
|
||||
if (search_str && ! strlen (search_str))
|
||||
search_str = NULL;
|
||||
|
||||
if (search_str)
|
||||
{
|
||||
sregex = g_regex_new (search_str, G_REGEX_CASELESS | G_REGEX_OPTIMIZE, 0,
|
||||
NULL);
|
||||
if (! sregex)
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* count number of plugin entries, then allocate arrays of correct size
|
||||
* where we can store the strings.
|
||||
*/
|
||||
|
||||
for (list = manager->plug_in_procedures; list; list = g_slist_next (list))
|
||||
{
|
||||
PikaPlugInProcedure *proc = list->data;
|
||||
|
||||
if (proc->file && proc->menu_paths)
|
||||
{
|
||||
gchar *name = proc->menu_label;
|
||||
|
||||
name = pika_strip_uline (name);
|
||||
|
||||
if (! search_str || match_string (sregex, name))
|
||||
{
|
||||
num_plugins++;
|
||||
matched = g_slist_prepend (matched, proc);
|
||||
}
|
||||
|
||||
g_free (name);
|
||||
}
|
||||
}
|
||||
|
||||
*procedure_strs = g_new0 (gchar *, num_plugins + 1);
|
||||
*accel_strs = g_new0 (gchar *, num_plugins + 1);
|
||||
*prog_strs = g_new0 (gchar *, num_plugins + 1);
|
||||
*time_ints = g_new (gint, num_plugins);
|
||||
|
||||
matched = g_slist_reverse (matched);
|
||||
|
||||
for (list = matched, i = 0;
|
||||
list;
|
||||
list = g_slist_next (list), i++)
|
||||
{
|
||||
PikaPlugInProcedure *proc = list->data;
|
||||
|
||||
(*procedure_strs)[i] = g_strdup (pika_object_get_name (proc));
|
||||
(*accel_strs)[i] = g_strdup ("");
|
||||
(*prog_strs)[i] = g_file_get_path (proc->file);
|
||||
(*time_ints)[i] = proc->mtime;
|
||||
}
|
||||
|
||||
g_slist_free (matched);
|
||||
|
||||
if (sregex)
|
||||
g_regex_unref (sregex);
|
||||
|
||||
return num_plugins;
|
||||
}
|
36
app/plug-in/pikapluginmanager-query.h
Normal file
36
app/plug-in/pikapluginmanager-query.h
Normal file
@ -0,0 +1,36 @@
|
||||
/* PIKA - Photo and Image Kooker Application
|
||||
* a rebranding of The GNU Image Manipulation Program (created with heckimp)
|
||||
* A derived work which may be trivial. However, any changes may be (C)2023 by Aldercone Studio
|
||||
*
|
||||
* Original copyright, applying to most contents (license remains unchanged):
|
||||
* Copyright (C) 1995 Spencer Kimball and Peter Mattis
|
||||
*
|
||||
* pikapluginmanager-query.h
|
||||
*
|
||||
* 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 3 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, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#ifndef __PIKA_PLUG_IN_MANAGER_QUERY_H__
|
||||
#define __PIKA_PLUG_IN_MANAGER_QUERY_H__
|
||||
|
||||
|
||||
gint pika_plug_in_manager_query (PikaPlugInManager *manager,
|
||||
const gchar *search_str,
|
||||
gchar ***procedure_strs,
|
||||
gchar ***accel_strs,
|
||||
gchar ***prog_strs,
|
||||
gint32 **time_ints);
|
||||
|
||||
|
||||
#endif /* __PIKA_PLUG_IN_MANAGER_QUERY_H__ */
|
1036
app/plug-in/pikapluginmanager-restore.c
Normal file
1036
app/plug-in/pikapluginmanager-restore.c
Normal file
File diff suppressed because it is too large
Load Diff
33
app/plug-in/pikapluginmanager-restore.h
Normal file
33
app/plug-in/pikapluginmanager-restore.h
Normal file
@ -0,0 +1,33 @@
|
||||
/* PIKA - Photo and Image Kooker Application
|
||||
* a rebranding of The GNU Image Manipulation Program (created with heckimp)
|
||||
* A derived work which may be trivial. However, any changes may be (C)2023 by Aldercone Studio
|
||||
*
|
||||
* Original copyright, applying to most contents (license remains unchanged):
|
||||
* Copyright (C) 1995-1997 Spencer Kimball and Peter Mattis
|
||||
*
|
||||
* pikapluginmanager-restore.h
|
||||
*
|
||||
* 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 3 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, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#ifndef __PIKA_PLUG_IN_MANAGER_RESTORE_H__
|
||||
#define __PIKA_PLUG_IN_MANAGER_RESTORE_H__
|
||||
|
||||
|
||||
void pika_plug_in_manager_restore (PikaPlugInManager *manager,
|
||||
PikaContext *context,
|
||||
PikaInitStatusFunc status_callback);
|
||||
|
||||
|
||||
#endif /* __PIKA_PLUG_IN_MANAGER_RESTORE_H__ */
|
447
app/plug-in/pikapluginmanager.c
Normal file
447
app/plug-in/pikapluginmanager.c
Normal file
@ -0,0 +1,447 @@
|
||||
/* PIKA - Photo and Image Kooker Application
|
||||
* a rebranding of The GNU Image Manipulation Program (created with heckimp)
|
||||
* A derived work which may be trivial. However, any changes may be (C)2023 by Aldercone Studio
|
||||
*
|
||||
* Original copyright, applying to most contents (license remains unchanged):
|
||||
* Copyright (C) 1995-2002 Spencer Kimball, Peter Mattis, and others
|
||||
*
|
||||
* pikapluginmanager.c
|
||||
*
|
||||
* 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 3 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, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include "config.h"
|
||||
|
||||
#include <string.h>
|
||||
|
||||
#include <gdk-pixbuf/gdk-pixbuf.h>
|
||||
#include <gegl.h>
|
||||
|
||||
#include "libpikabase/pikabase.h"
|
||||
#include "libpikaconfig/pikaconfig.h"
|
||||
|
||||
#include "plug-in-types.h"
|
||||
|
||||
#include "config/pikacoreconfig.h"
|
||||
|
||||
#include "core/pika.h"
|
||||
#include "core/pika-filter-history.h"
|
||||
#include "core/pika-memsize.h"
|
||||
#include "core/pikamarshal.h"
|
||||
|
||||
#include "pdb/pikapdb.h"
|
||||
|
||||
#include "pikaenvirontable.h"
|
||||
#include "pikainterpreterdb.h"
|
||||
#include "pikaplugin.h"
|
||||
#include "pikaplugindebug.h"
|
||||
#include "pikaplugindef.h"
|
||||
#include "pikapluginmanager.h"
|
||||
#include "pikapluginmanager-data.h"
|
||||
#include "pikapluginmanager-help-domain.h"
|
||||
#include "pikapluginmanager-menu-branch.h"
|
||||
#include "pikapluginshm.h"
|
||||
#include "pikatemporaryprocedure.h"
|
||||
|
||||
#include "pika-intl.h"
|
||||
|
||||
|
||||
enum
|
||||
{
|
||||
PLUG_IN_OPENED,
|
||||
PLUG_IN_CLOSED,
|
||||
MENU_BRANCH_ADDED,
|
||||
LAST_SIGNAL
|
||||
};
|
||||
|
||||
|
||||
static void pika_plug_in_manager_finalize (GObject *object);
|
||||
|
||||
static gint64 pika_plug_in_manager_get_memsize (PikaObject *object,
|
||||
gint64 *gui_size);
|
||||
|
||||
|
||||
G_DEFINE_TYPE (PikaPlugInManager, pika_plug_in_manager, PIKA_TYPE_OBJECT)
|
||||
|
||||
#define parent_class pika_plug_in_manager_parent_class
|
||||
|
||||
static guint manager_signals[LAST_SIGNAL] = { 0, };
|
||||
|
||||
|
||||
static void
|
||||
pika_plug_in_manager_class_init (PikaPlugInManagerClass *klass)
|
||||
{
|
||||
GObjectClass *object_class = G_OBJECT_CLASS (klass);
|
||||
PikaObjectClass *pika_object_class = PIKA_OBJECT_CLASS (klass);
|
||||
|
||||
manager_signals[PLUG_IN_OPENED] =
|
||||
g_signal_new ("plug-in-opened",
|
||||
G_TYPE_FROM_CLASS (klass),
|
||||
G_SIGNAL_RUN_LAST,
|
||||
G_STRUCT_OFFSET (PikaPlugInManagerClass,
|
||||
plug_in_opened),
|
||||
NULL, NULL, NULL,
|
||||
G_TYPE_NONE, 1,
|
||||
PIKA_TYPE_PLUG_IN);
|
||||
|
||||
manager_signals[PLUG_IN_CLOSED] =
|
||||
g_signal_new ("plug-in-closed",
|
||||
G_TYPE_FROM_CLASS (klass),
|
||||
G_SIGNAL_RUN_LAST,
|
||||
G_STRUCT_OFFSET (PikaPlugInManagerClass,
|
||||
plug_in_closed),
|
||||
NULL, NULL, NULL,
|
||||
G_TYPE_NONE, 1,
|
||||
PIKA_TYPE_PLUG_IN);
|
||||
|
||||
manager_signals[MENU_BRANCH_ADDED] =
|
||||
g_signal_new ("menu-branch-added",
|
||||
G_TYPE_FROM_CLASS (klass),
|
||||
G_SIGNAL_RUN_LAST,
|
||||
G_STRUCT_OFFSET (PikaPlugInManagerClass,
|
||||
menu_branch_added),
|
||||
NULL, NULL,
|
||||
pika_marshal_VOID__OBJECT_STRING_STRING,
|
||||
G_TYPE_NONE, 3,
|
||||
G_TYPE_FILE,
|
||||
G_TYPE_STRING,
|
||||
G_TYPE_STRING);
|
||||
|
||||
object_class->finalize = pika_plug_in_manager_finalize;
|
||||
|
||||
pika_object_class->get_memsize = pika_plug_in_manager_get_memsize;
|
||||
}
|
||||
|
||||
static void
|
||||
pika_plug_in_manager_init (PikaPlugInManager *manager)
|
||||
{
|
||||
}
|
||||
|
||||
static void
|
||||
pika_plug_in_manager_finalize (GObject *object)
|
||||
{
|
||||
PikaPlugInManager *manager = PIKA_PLUG_IN_MANAGER (object);
|
||||
|
||||
g_clear_pointer (&manager->load_procs, g_slist_free);
|
||||
g_clear_pointer (&manager->save_procs, g_slist_free);
|
||||
g_clear_pointer (&manager->export_procs, g_slist_free);
|
||||
g_clear_pointer (&manager->raw_load_procs, g_slist_free);
|
||||
g_clear_pointer (&manager->batch_procs, g_slist_free);
|
||||
|
||||
g_clear_pointer (&manager->display_load_procs, g_slist_free);
|
||||
g_clear_pointer (&manager->display_save_procs, g_slist_free);
|
||||
g_clear_pointer (&manager->display_export_procs, g_slist_free);
|
||||
g_clear_pointer (&manager->display_raw_load_procs, g_slist_free);
|
||||
|
||||
if (manager->plug_in_procedures)
|
||||
{
|
||||
g_slist_free_full (manager->plug_in_procedures,
|
||||
(GDestroyNotify) g_object_unref);
|
||||
manager->plug_in_procedures = NULL;
|
||||
}
|
||||
|
||||
if (manager->plug_in_defs)
|
||||
{
|
||||
g_slist_free_full (manager->plug_in_defs,
|
||||
(GDestroyNotify) g_object_unref);
|
||||
manager->plug_in_defs = NULL;
|
||||
}
|
||||
|
||||
g_clear_object (&manager->environ_table);
|
||||
g_clear_object (&manager->interpreter_db);
|
||||
|
||||
g_clear_pointer (&manager->debug, pika_plug_in_debug_free);
|
||||
|
||||
pika_plug_in_manager_menu_branch_exit (manager);
|
||||
pika_plug_in_manager_help_domain_exit (manager);
|
||||
pika_plug_in_manager_data_free (manager);
|
||||
|
||||
G_OBJECT_CLASS (parent_class)->finalize (object);
|
||||
}
|
||||
|
||||
static gint64
|
||||
pika_plug_in_manager_get_memsize (PikaObject *object,
|
||||
gint64 *gui_size)
|
||||
{
|
||||
PikaPlugInManager *manager = PIKA_PLUG_IN_MANAGER (object);
|
||||
gint64 memsize = 0;
|
||||
|
||||
memsize += pika_g_slist_get_memsize_foreach (manager->plug_in_defs,
|
||||
(PikaMemsizeFunc)
|
||||
pika_object_get_memsize,
|
||||
gui_size);
|
||||
|
||||
memsize += pika_g_slist_get_memsize (manager->plug_in_procedures, 0);
|
||||
memsize += pika_g_slist_get_memsize (manager->load_procs, 0);
|
||||
memsize += pika_g_slist_get_memsize (manager->save_procs, 0);
|
||||
memsize += pika_g_slist_get_memsize (manager->export_procs, 0);
|
||||
memsize += pika_g_slist_get_memsize (manager->raw_load_procs, 0);
|
||||
memsize += pika_g_slist_get_memsize (manager->batch_procs, 0);
|
||||
memsize += pika_g_slist_get_memsize (manager->display_load_procs, 0);
|
||||
memsize += pika_g_slist_get_memsize (manager->display_save_procs, 0);
|
||||
memsize += pika_g_slist_get_memsize (manager->display_export_procs, 0);
|
||||
memsize += pika_g_slist_get_memsize (manager->display_raw_load_procs, 0);
|
||||
|
||||
memsize += pika_g_slist_get_memsize (manager->menu_branches, 0 /* FIXME */);
|
||||
memsize += pika_g_slist_get_memsize (manager->help_domains, 0 /* FIXME */);
|
||||
|
||||
memsize += pika_g_slist_get_memsize_foreach (manager->open_plug_ins,
|
||||
(PikaMemsizeFunc)
|
||||
pika_object_get_memsize,
|
||||
gui_size);
|
||||
memsize += pika_g_slist_get_memsize (manager->plug_in_stack, 0);
|
||||
|
||||
memsize += 0; /* FIXME manager->shm */
|
||||
memsize += /* FIXME */ pika_g_object_get_memsize (G_OBJECT (manager->interpreter_db));
|
||||
memsize += /* FIXME */ pika_g_object_get_memsize (G_OBJECT (manager->environ_table));
|
||||
memsize += 0; /* FIXME manager->plug_in_debug */
|
||||
memsize += pika_g_list_get_memsize (manager->data_list, 0 /* FIXME */);
|
||||
|
||||
return memsize + PIKA_OBJECT_CLASS (parent_class)->get_memsize (object,
|
||||
gui_size);
|
||||
}
|
||||
|
||||
PikaPlugInManager *
|
||||
pika_plug_in_manager_new (Pika *pika)
|
||||
{
|
||||
PikaPlugInManager *manager;
|
||||
|
||||
manager = g_object_new (PIKA_TYPE_PLUG_IN_MANAGER, NULL);
|
||||
|
||||
manager->pika = pika;
|
||||
manager->interpreter_db = pika_interpreter_db_new (pika->be_verbose);
|
||||
manager->environ_table = pika_environ_table_new (pika->be_verbose);
|
||||
|
||||
return manager;
|
||||
}
|
||||
|
||||
void
|
||||
pika_plug_in_manager_initialize (PikaPlugInManager *manager,
|
||||
PikaInitStatusFunc status_callback)
|
||||
{
|
||||
PikaCoreConfig *config;
|
||||
GList *path;
|
||||
|
||||
g_return_if_fail (PIKA_IS_PLUG_IN_MANAGER (manager));
|
||||
g_return_if_fail (status_callback != NULL);
|
||||
|
||||
config = manager->pika->config;
|
||||
|
||||
status_callback (NULL, _("Plug-in Interpreters"), 0.8);
|
||||
|
||||
path = pika_config_path_expand_to_files (config->interpreter_path, NULL);
|
||||
pika_interpreter_db_load (manager->interpreter_db, path);
|
||||
g_list_free_full (path, (GDestroyNotify) g_object_unref);
|
||||
|
||||
status_callback (NULL, _("Plug-in Environment"), 0.9);
|
||||
|
||||
path = pika_config_path_expand_to_files (config->environ_path, NULL);
|
||||
pika_environ_table_load (manager->environ_table, path);
|
||||
g_list_free_full (path, (GDestroyNotify) g_object_unref);
|
||||
|
||||
/* allocate a piece of shared memory for use in transporting tiles
|
||||
* to plug-ins. if we can't allocate a piece of shared memory then
|
||||
* we'll fall back on sending the data over the pipe.
|
||||
*/
|
||||
if (manager->pika->use_shm)
|
||||
manager->shm = pika_plug_in_shm_new ();
|
||||
|
||||
manager->debug = pika_plug_in_debug_new ();
|
||||
}
|
||||
|
||||
void
|
||||
pika_plug_in_manager_exit (PikaPlugInManager *manager)
|
||||
{
|
||||
g_return_if_fail (PIKA_IS_PLUG_IN_MANAGER (manager));
|
||||
|
||||
while (manager->open_plug_ins)
|
||||
pika_plug_in_close (manager->open_plug_ins->data, TRUE);
|
||||
|
||||
/* need to detach from shared memory, we can't rely on exit()
|
||||
* cleaning up behind us (see bug #609026)
|
||||
*/
|
||||
if (manager->shm)
|
||||
{
|
||||
pika_plug_in_shm_free (manager->shm);
|
||||
manager->shm = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
pika_plug_in_manager_add_procedure (PikaPlugInManager *manager,
|
||||
PikaPlugInProcedure *procedure)
|
||||
{
|
||||
GSList *list;
|
||||
|
||||
g_return_if_fail (PIKA_IS_PLUG_IN_MANAGER (manager));
|
||||
g_return_if_fail (PIKA_IS_PLUG_IN_PROCEDURE (procedure));
|
||||
|
||||
for (list = manager->plug_in_procedures; list; list = list->next)
|
||||
{
|
||||
PikaPlugInProcedure *tmp_proc = list->data;
|
||||
|
||||
if (strcmp (pika_object_get_name (procedure),
|
||||
pika_object_get_name (tmp_proc)) == 0)
|
||||
{
|
||||
GSList *list2;
|
||||
|
||||
list->data = g_object_ref (procedure);
|
||||
|
||||
g_printerr ("Removing duplicate PDB procedure '%s' "
|
||||
"registered by '%s'\n",
|
||||
pika_object_get_name (tmp_proc),
|
||||
pika_file_get_utf8_name (tmp_proc->file));
|
||||
|
||||
/* search the plugin list to see if any plugins had references to
|
||||
* the tmp_proc.
|
||||
*/
|
||||
for (list2 = manager->plug_in_defs; list2; list2 = list2->next)
|
||||
{
|
||||
PikaPlugInDef *plug_in_def = list2->data;
|
||||
|
||||
if (g_slist_find (plug_in_def->procedures, tmp_proc))
|
||||
pika_plug_in_def_remove_procedure (plug_in_def, tmp_proc);
|
||||
}
|
||||
|
||||
/* also remove it from the lists of load, save and export procs */
|
||||
manager->load_procs = g_slist_remove (manager->load_procs, tmp_proc);
|
||||
manager->save_procs = g_slist_remove (manager->save_procs, tmp_proc);
|
||||
manager->export_procs = g_slist_remove (manager->export_procs, tmp_proc);
|
||||
manager->raw_load_procs = g_slist_remove (manager->raw_load_procs, tmp_proc);
|
||||
manager->batch_procs = g_slist_remove (manager->batch_procs, tmp_proc);
|
||||
manager->display_load_procs = g_slist_remove (manager->display_load_procs, tmp_proc);
|
||||
manager->display_save_procs = g_slist_remove (manager->display_save_procs, tmp_proc);
|
||||
manager->display_export_procs = g_slist_remove (manager->display_export_procs, tmp_proc);
|
||||
manager->display_raw_load_procs = g_slist_remove (manager->display_raw_load_procs, tmp_proc);
|
||||
|
||||
/* and from the history */
|
||||
pika_filter_history_remove (manager->pika, PIKA_PROCEDURE (tmp_proc));
|
||||
|
||||
g_object_unref (tmp_proc);
|
||||
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
manager->plug_in_procedures = g_slist_prepend (manager->plug_in_procedures,
|
||||
g_object_ref (procedure));
|
||||
}
|
||||
|
||||
void
|
||||
pika_plug_in_manager_add_batch_procedure (PikaPlugInManager *manager,
|
||||
PikaPlugInProcedure *proc)
|
||||
{
|
||||
g_return_if_fail (PIKA_IS_PLUG_IN_MANAGER (manager));
|
||||
g_return_if_fail (PIKA_IS_PLUG_IN_PROCEDURE (proc));
|
||||
|
||||
if (! g_slist_find (manager->batch_procs, proc))
|
||||
manager->batch_procs = g_slist_prepend (manager->batch_procs, proc);
|
||||
}
|
||||
|
||||
GSList *
|
||||
pika_plug_in_manager_get_batch_procedures (PikaPlugInManager *manager)
|
||||
{
|
||||
g_return_val_if_fail (PIKA_IS_PLUG_IN_MANAGER (manager), NULL);
|
||||
|
||||
return manager->batch_procs;
|
||||
}
|
||||
|
||||
void
|
||||
pika_plug_in_manager_add_temp_proc (PikaPlugInManager *manager,
|
||||
PikaTemporaryProcedure *procedure)
|
||||
{
|
||||
g_return_if_fail (PIKA_IS_PLUG_IN_MANAGER (manager));
|
||||
g_return_if_fail (PIKA_IS_TEMPORARY_PROCEDURE (procedure));
|
||||
|
||||
pika_pdb_register_procedure (manager->pika->pdb, PIKA_PROCEDURE (procedure));
|
||||
|
||||
manager->plug_in_procedures = g_slist_prepend (manager->plug_in_procedures,
|
||||
g_object_ref (procedure));
|
||||
}
|
||||
|
||||
void
|
||||
pika_plug_in_manager_remove_temp_proc (PikaPlugInManager *manager,
|
||||
PikaTemporaryProcedure *procedure)
|
||||
{
|
||||
g_return_if_fail (PIKA_IS_PLUG_IN_MANAGER (manager));
|
||||
g_return_if_fail (PIKA_IS_TEMPORARY_PROCEDURE (procedure));
|
||||
|
||||
manager->plug_in_procedures = g_slist_remove (manager->plug_in_procedures,
|
||||
procedure);
|
||||
|
||||
pika_filter_history_remove (manager->pika,
|
||||
PIKA_PROCEDURE (procedure));
|
||||
|
||||
pika_pdb_unregister_procedure (manager->pika->pdb,
|
||||
PIKA_PROCEDURE (procedure));
|
||||
|
||||
g_object_unref (procedure);
|
||||
}
|
||||
|
||||
void
|
||||
pika_plug_in_manager_add_open_plug_in (PikaPlugInManager *manager,
|
||||
PikaPlugIn *plug_in)
|
||||
{
|
||||
g_return_if_fail (PIKA_IS_PLUG_IN_MANAGER (manager));
|
||||
g_return_if_fail (PIKA_IS_PLUG_IN (plug_in));
|
||||
|
||||
manager->open_plug_ins = g_slist_prepend (manager->open_plug_ins,
|
||||
g_object_ref (plug_in));
|
||||
|
||||
g_signal_emit (manager, manager_signals[PLUG_IN_OPENED], 0,
|
||||
plug_in);
|
||||
}
|
||||
|
||||
void
|
||||
pika_plug_in_manager_remove_open_plug_in (PikaPlugInManager *manager,
|
||||
PikaPlugIn *plug_in)
|
||||
{
|
||||
g_return_if_fail (PIKA_IS_PLUG_IN_MANAGER (manager));
|
||||
g_return_if_fail (PIKA_IS_PLUG_IN (plug_in));
|
||||
|
||||
manager->open_plug_ins = g_slist_remove (manager->open_plug_ins, plug_in);
|
||||
|
||||
g_signal_emit (manager, manager_signals[PLUG_IN_CLOSED], 0,
|
||||
plug_in);
|
||||
|
||||
g_object_unref (plug_in);
|
||||
}
|
||||
|
||||
void
|
||||
pika_plug_in_manager_plug_in_push (PikaPlugInManager *manager,
|
||||
PikaPlugIn *plug_in)
|
||||
{
|
||||
g_return_if_fail (PIKA_IS_PLUG_IN_MANAGER (manager));
|
||||
g_return_if_fail (PIKA_IS_PLUG_IN (plug_in));
|
||||
|
||||
manager->current_plug_in = plug_in;
|
||||
|
||||
manager->plug_in_stack = g_slist_prepend (manager->plug_in_stack,
|
||||
manager->current_plug_in);
|
||||
}
|
||||
|
||||
void
|
||||
pika_plug_in_manager_plug_in_pop (PikaPlugInManager *manager)
|
||||
{
|
||||
g_return_if_fail (PIKA_IS_PLUG_IN_MANAGER (manager));
|
||||
|
||||
if (manager->current_plug_in)
|
||||
manager->plug_in_stack = g_slist_remove (manager->plug_in_stack,
|
||||
manager->plug_in_stack->data);
|
||||
|
||||
if (manager->plug_in_stack)
|
||||
manager->current_plug_in = manager->plug_in_stack->data;
|
||||
else
|
||||
manager->current_plug_in = NULL;
|
||||
}
|
126
app/plug-in/pikapluginmanager.h
Normal file
126
app/plug-in/pikapluginmanager.h
Normal file
@ -0,0 +1,126 @@
|
||||
/* PIKA - Photo and Image Kooker Application
|
||||
* a rebranding of The GNU Image Manipulation Program (created with heckimp)
|
||||
* A derived work which may be trivial. However, any changes may be (C)2023 by Aldercone Studio
|
||||
*
|
||||
* Original copyright, applying to most contents (license remains unchanged):
|
||||
* Copyright (C) 1995-1997 Spencer Kimball and Peter Mattis
|
||||
*
|
||||
* pikapluginmanager.h
|
||||
*
|
||||
* 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 3 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, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#ifndef __PIKA_PLUG_IN_MANAGER_H__
|
||||
#define __PIKA_PLUG_IN_MANAGER_H__
|
||||
|
||||
|
||||
#include "core/pikaobject.h"
|
||||
|
||||
|
||||
#define PIKA_TYPE_PLUG_IN_MANAGER (pika_plug_in_manager_get_type ())
|
||||
#define PIKA_PLUG_IN_MANAGER(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), PIKA_TYPE_PLUG_IN_MANAGER, PikaPlugInManager))
|
||||
#define PIKA_PLUG_IN_MANAGER_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), PIKA_TYPE_PLUG_IN_MANAGER, PikaPlugInManagerClass))
|
||||
#define PIKA_IS_PLUG_IN_MANAGER(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), PIKA_TYPE_PLUG_IN_MANAGER))
|
||||
#define PIKA_IS_PLUG_IN_MANAGER_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), PIKA_TYPE_PLUG_IN_MANAGER))
|
||||
|
||||
|
||||
typedef struct _PikaPlugInManagerClass PikaPlugInManagerClass;
|
||||
|
||||
struct _PikaPlugInManager
|
||||
{
|
||||
PikaObject parent_instance;
|
||||
|
||||
Pika *pika;
|
||||
|
||||
GSList *plug_in_defs;
|
||||
gboolean write_pluginrc;
|
||||
|
||||
GSList *plug_in_procedures;
|
||||
|
||||
GSList *load_procs;
|
||||
GSList *save_procs;
|
||||
GSList *export_procs;
|
||||
GSList *raw_load_procs;
|
||||
GSList *batch_procs;
|
||||
|
||||
GSList *display_load_procs;
|
||||
GSList *display_save_procs;
|
||||
GSList *display_export_procs;
|
||||
GSList *display_raw_load_procs;
|
||||
|
||||
GSList *menu_branches;
|
||||
GSList *help_domains;
|
||||
|
||||
PikaPlugIn *current_plug_in;
|
||||
GSList *open_plug_ins;
|
||||
GSList *plug_in_stack;
|
||||
|
||||
PikaPlugInShm *shm;
|
||||
PikaInterpreterDB *interpreter_db;
|
||||
PikaEnvironTable *environ_table;
|
||||
PikaPlugInDebug *debug;
|
||||
GList *data_list;
|
||||
};
|
||||
|
||||
struct _PikaPlugInManagerClass
|
||||
{
|
||||
PikaObjectClass parent_class;
|
||||
|
||||
void (* plug_in_opened) (PikaPlugInManager *manager,
|
||||
PikaPlugIn *plug_in);
|
||||
void (* plug_in_closed) (PikaPlugInManager *manager,
|
||||
PikaPlugIn *plug_in);
|
||||
|
||||
void (* menu_branch_added) (PikaPlugInManager *manager,
|
||||
GFile *file,
|
||||
const gchar *menu_path,
|
||||
const gchar *menu_label);
|
||||
};
|
||||
|
||||
|
||||
GType pika_plug_in_manager_get_type (void) G_GNUC_CONST;
|
||||
|
||||
PikaPlugInManager * pika_plug_in_manager_new (Pika *pika);
|
||||
|
||||
void pika_plug_in_manager_initialize (PikaPlugInManager *manager,
|
||||
PikaInitStatusFunc status_callback);
|
||||
void pika_plug_in_manager_exit (PikaPlugInManager *manager);
|
||||
|
||||
/* Register a plug-in. This function is public for file load-save
|
||||
* handlers, which are organized around the plug-in data structure.
|
||||
* This could all be done a little better, but oh well. -josh
|
||||
*/
|
||||
void pika_plug_in_manager_add_procedure (PikaPlugInManager *manager,
|
||||
PikaPlugInProcedure *procedure);
|
||||
|
||||
void pika_plug_in_manager_add_batch_procedure (PikaPlugInManager *manager,
|
||||
PikaPlugInProcedure *proc);
|
||||
GSList * pika_plug_in_manager_get_batch_procedures (PikaPlugInManager *manager);
|
||||
|
||||
void pika_plug_in_manager_add_temp_proc (PikaPlugInManager *manager,
|
||||
PikaTemporaryProcedure *procedure);
|
||||
void pika_plug_in_manager_remove_temp_proc (PikaPlugInManager *manager,
|
||||
PikaTemporaryProcedure *procedure);
|
||||
|
||||
void pika_plug_in_manager_add_open_plug_in (PikaPlugInManager *manager,
|
||||
PikaPlugIn *plug_in);
|
||||
void pika_plug_in_manager_remove_open_plug_in (PikaPlugInManager *manager,
|
||||
PikaPlugIn *plug_in);
|
||||
|
||||
void pika_plug_in_manager_plug_in_push (PikaPlugInManager *manager,
|
||||
PikaPlugIn *plug_in);
|
||||
void pika_plug_in_manager_plug_in_pop (PikaPlugInManager *manager);
|
||||
|
||||
|
||||
#endif /* __PIKA_PLUG_IN_MANAGER_H__ */
|
1320
app/plug-in/pikapluginprocedure.c
Normal file
1320
app/plug-in/pikapluginprocedure.c
Normal file
File diff suppressed because it is too large
Load Diff
155
app/plug-in/pikapluginprocedure.h
Normal file
155
app/plug-in/pikapluginprocedure.h
Normal file
@ -0,0 +1,155 @@
|
||||
/* PIKA - Photo and Image Kooker Application
|
||||
* a rebranding of The GNU Image Manipulation Program (created with heckimp)
|
||||
* A derived work which may be trivial. However, any changes may be (C)2023 by Aldercone Studio
|
||||
*
|
||||
* Original copyright, applying to most contents (license remains unchanged):
|
||||
* Copyright (C) 1995 Spencer Kimball and Peter Mattis
|
||||
*
|
||||
* pikapluginprocedure.h
|
||||
*
|
||||
* 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 3 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, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#ifndef __PIKA_PLUG_IN_PROCEDURE_H__
|
||||
#define __PIKA_PLUG_IN_PROCEDURE_H__
|
||||
|
||||
|
||||
#include "pdb/pikaprocedure.h"
|
||||
|
||||
|
||||
#define PIKA_TYPE_PLUG_IN_PROCEDURE (pika_plug_in_procedure_get_type ())
|
||||
#define PIKA_PLUG_IN_PROCEDURE(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), PIKA_TYPE_PLUG_IN_PROCEDURE, PikaPlugInProcedure))
|
||||
#define PIKA_PLUG_IN_PROCEDURE_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), PIKA_TYPE_PLUG_IN_PROCEDURE, PikaPlugInProcedureClass))
|
||||
#define PIKA_IS_PLUG_IN_PROCEDURE(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), PIKA_TYPE_PLUG_IN_PROCEDURE))
|
||||
#define PIKA_IS_PLUG_IN_PROCEDURE_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), PIKA_TYPE_PLUG_IN_PROCEDURE))
|
||||
#define PIKA_PLUG_IN_PROCEDURE_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), PIKA_TYPE_PLUG_IN_PROCEDURE, PikaPlugInProcedureClass))
|
||||
|
||||
|
||||
typedef struct _PikaPlugInProcedureClass PikaPlugInProcedureClass;
|
||||
|
||||
struct _PikaPlugInProcedure
|
||||
{
|
||||
PikaProcedure parent_instance;
|
||||
|
||||
/* common members */
|
||||
GFile *file;
|
||||
GQuark help_domain;
|
||||
gchar *menu_label;
|
||||
GList *menu_paths;
|
||||
gchar *help_id_with_domain;
|
||||
PikaIconType icon_type;
|
||||
gint icon_data_length;
|
||||
guint8 *icon_data;
|
||||
gchar *image_types;
|
||||
PikaPlugInImageType image_types_val;
|
||||
gchar *insensitive_reason;
|
||||
gint sensitivity_mask;
|
||||
gint64 mtime;
|
||||
gboolean installed_during_init;
|
||||
|
||||
/* file proc specific members */
|
||||
gboolean file_proc;
|
||||
gboolean generic_file_proc; /* not returning an image. */
|
||||
gchar *extensions;
|
||||
gchar *prefixes;
|
||||
gchar *magics;
|
||||
gint priority;
|
||||
gchar *mime_types;
|
||||
gboolean handles_remote;
|
||||
gboolean handles_raw;
|
||||
gboolean batch_interpreter;
|
||||
gchar *batch_interpreter_name;
|
||||
GSList *extensions_list;
|
||||
GSList *prefixes_list;
|
||||
GSList *magics_list;
|
||||
GSList *mime_types_list;
|
||||
gchar *thumb_loader;
|
||||
};
|
||||
|
||||
struct _PikaPlugInProcedureClass
|
||||
{
|
||||
PikaProcedureClass parent_class;
|
||||
|
||||
/* virtual functions */
|
||||
GFile * (* get_file) (PikaPlugInProcedure *procedure);
|
||||
|
||||
/* signals */
|
||||
void (* menu_path_added) (PikaPlugInProcedure *procedure,
|
||||
const gchar *menu_path);
|
||||
};
|
||||
|
||||
|
||||
GType pika_plug_in_procedure_get_type (void) G_GNUC_CONST;
|
||||
|
||||
PikaProcedure * pika_plug_in_procedure_new (PikaPDBProcType proc_type,
|
||||
GFile *file);
|
||||
|
||||
PikaPlugInProcedure * pika_plug_in_procedure_find (GSList *list,
|
||||
const gchar *proc_name);
|
||||
|
||||
GFile * pika_plug_in_procedure_get_file (PikaPlugInProcedure *proc);
|
||||
|
||||
void pika_plug_in_procedure_set_help_domain (PikaPlugInProcedure *proc,
|
||||
const gchar *help_domain);
|
||||
const gchar * pika_plug_in_procedure_get_help_domain (PikaPlugInProcedure *proc);
|
||||
|
||||
gboolean pika_plug_in_procedure_set_menu_label (PikaPlugInProcedure *proc,
|
||||
const gchar *menu_label,
|
||||
GError **error);
|
||||
|
||||
gboolean pika_plug_in_procedure_add_menu_path (PikaPlugInProcedure *proc,
|
||||
const gchar *menu_path,
|
||||
GError **error);
|
||||
|
||||
gboolean pika_plug_in_procedure_set_icon (PikaPlugInProcedure *proc,
|
||||
PikaIconType type,
|
||||
const guint8 *data,
|
||||
gint data_length,
|
||||
GError **error);
|
||||
gboolean pika_plug_in_procedure_take_icon (PikaPlugInProcedure *proc,
|
||||
PikaIconType type,
|
||||
guint8 *data,
|
||||
gint data_length,
|
||||
GError **error);
|
||||
|
||||
void pika_plug_in_procedure_set_image_types (PikaPlugInProcedure *proc,
|
||||
const gchar *image_types);
|
||||
void pika_plug_in_procedure_set_sensitivity_mask (PikaPlugInProcedure *proc,
|
||||
gint sensitivity_mask);
|
||||
|
||||
void pika_plug_in_procedure_set_file_proc (PikaPlugInProcedure *proc,
|
||||
const gchar *extensions,
|
||||
const gchar *prefixes,
|
||||
const gchar *magics);
|
||||
void pika_plug_in_procedure_set_generic_file_proc (PikaPlugInProcedure *proc,
|
||||
gboolean is_generic_file_proc);
|
||||
void pika_plug_in_procedure_set_priority (PikaPlugInProcedure *proc,
|
||||
gint priority);
|
||||
void pika_plug_in_procedure_set_mime_types (PikaPlugInProcedure *proc,
|
||||
const gchar *mime_ypes);
|
||||
void pika_plug_in_procedure_set_handles_remote(PikaPlugInProcedure *proc);
|
||||
void pika_plug_in_procedure_set_handles_raw (PikaPlugInProcedure *proc);
|
||||
void pika_plug_in_procedure_set_thumb_loader (PikaPlugInProcedure *proc,
|
||||
const gchar *thumbnailer);
|
||||
void pika_plug_in_procedure_set_batch_interpreter (PikaPlugInProcedure *proc,
|
||||
const gchar *name);
|
||||
|
||||
void pika_plug_in_procedure_handle_return_values (PikaPlugInProcedure *proc,
|
||||
Pika *pika,
|
||||
PikaProgress *progress,
|
||||
|
||||
PikaValueArray *return_vals);
|
||||
|
||||
|
||||
#endif /* __PIKA_PLUG_IN_PROCEDURE_H__ */
|
204
app/plug-in/pikapluginprocframe.c
Normal file
204
app/plug-in/pikapluginprocframe.c
Normal file
@ -0,0 +1,204 @@
|
||||
/* PIKA - Photo and Image Kooker Application
|
||||
* a rebranding of The GNU Image Manipulation Program (created with heckimp)
|
||||
* A derived work which may be trivial. However, any changes may be (C)2023 by Aldercone Studio
|
||||
*
|
||||
* Original copyright, applying to most contents (license remains unchanged):
|
||||
* Copyright (C) 1995 Spencer Kimball and Peter Mattis
|
||||
*
|
||||
* pikapluginprocframe.c
|
||||
*
|
||||
* 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 3 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, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include "config.h"
|
||||
|
||||
#include <string.h>
|
||||
|
||||
#include <gdk-pixbuf/gdk-pixbuf.h>
|
||||
#include <gegl.h>
|
||||
|
||||
#include "libpikabase/pikabase.h"
|
||||
|
||||
#include "plug-in-types.h"
|
||||
|
||||
#include "core/pikaprogress.h"
|
||||
|
||||
#include "pdb/pikapdbcontext.h"
|
||||
#include "pdb/pikapdberror.h"
|
||||
|
||||
#include "pikaplugin.h"
|
||||
#include "pikaplugin-cleanup.h"
|
||||
#include "pikaplugin-progress.h"
|
||||
#include "pikapluginprocedure.h"
|
||||
|
||||
#include "pika-intl.h"
|
||||
|
||||
|
||||
/* public functions */
|
||||
|
||||
PikaPlugInProcFrame *
|
||||
pika_plug_in_proc_frame_new (PikaContext *context,
|
||||
PikaProgress *progress,
|
||||
PikaPlugInProcedure *procedure)
|
||||
{
|
||||
PikaPlugInProcFrame *proc_frame;
|
||||
|
||||
g_return_val_if_fail (PIKA_IS_PDB_CONTEXT (context), NULL);
|
||||
g_return_val_if_fail (progress == NULL || PIKA_IS_PROGRESS (progress), NULL);
|
||||
g_return_val_if_fail (PIKA_IS_PLUG_IN_PROCEDURE (procedure), NULL);
|
||||
|
||||
proc_frame = g_slice_new0 (PikaPlugInProcFrame);
|
||||
|
||||
proc_frame->ref_count = 1;
|
||||
|
||||
pika_plug_in_proc_frame_init (proc_frame, context, progress, procedure);
|
||||
|
||||
return proc_frame;
|
||||
}
|
||||
|
||||
void
|
||||
pika_plug_in_proc_frame_init (PikaPlugInProcFrame *proc_frame,
|
||||
PikaContext *context,
|
||||
PikaProgress *progress,
|
||||
PikaPlugInProcedure *procedure)
|
||||
{
|
||||
g_return_if_fail (proc_frame != NULL);
|
||||
g_return_if_fail (PIKA_IS_PDB_CONTEXT (context));
|
||||
g_return_if_fail (progress == NULL || PIKA_IS_PROGRESS (progress));
|
||||
g_return_if_fail (procedure == NULL ||
|
||||
PIKA_IS_PLUG_IN_PROCEDURE (procedure));
|
||||
|
||||
proc_frame->main_context = g_object_ref (context);
|
||||
proc_frame->context_stack = NULL;
|
||||
proc_frame->procedure = procedure ? g_object_ref (PIKA_PROCEDURE (procedure)) : NULL;
|
||||
proc_frame->main_loop = NULL;
|
||||
proc_frame->return_vals = NULL;
|
||||
proc_frame->progress = progress ? g_object_ref (progress) : NULL;
|
||||
proc_frame->progress_created = FALSE;
|
||||
proc_frame->progress_cancel_id = 0;
|
||||
proc_frame->error_handler = PIKA_PDB_ERROR_HANDLER_INTERNAL;
|
||||
|
||||
if (progress)
|
||||
pika_plug_in_progress_attach (progress);
|
||||
}
|
||||
|
||||
void
|
||||
pika_plug_in_proc_frame_dispose (PikaPlugInProcFrame *proc_frame,
|
||||
PikaPlugIn *plug_in)
|
||||
{
|
||||
g_return_if_fail (proc_frame != NULL);
|
||||
g_return_if_fail (PIKA_IS_PLUG_IN (plug_in));
|
||||
|
||||
if (proc_frame->progress)
|
||||
{
|
||||
pika_plug_in_progress_end (plug_in, proc_frame);
|
||||
|
||||
g_clear_object (&proc_frame->progress);
|
||||
}
|
||||
|
||||
if (proc_frame->context_stack)
|
||||
{
|
||||
g_list_free_full (proc_frame->context_stack,
|
||||
(GDestroyNotify) g_object_unref);
|
||||
proc_frame->context_stack = NULL;
|
||||
}
|
||||
|
||||
g_clear_object (&proc_frame->main_context);
|
||||
g_clear_pointer (&proc_frame->return_vals, pika_value_array_unref);
|
||||
g_clear_pointer (&proc_frame->main_loop, g_main_loop_unref);
|
||||
|
||||
if (proc_frame->image_cleanups || proc_frame->item_cleanups)
|
||||
pika_plug_in_cleanup (plug_in, proc_frame);
|
||||
|
||||
g_clear_object (&proc_frame->procedure);
|
||||
}
|
||||
|
||||
PikaPlugInProcFrame *
|
||||
pika_plug_in_proc_frame_ref (PikaPlugInProcFrame *proc_frame)
|
||||
{
|
||||
g_return_val_if_fail (proc_frame != NULL, NULL);
|
||||
|
||||
proc_frame->ref_count++;
|
||||
|
||||
return proc_frame;
|
||||
}
|
||||
|
||||
void
|
||||
pika_plug_in_proc_frame_unref (PikaPlugInProcFrame *proc_frame,
|
||||
PikaPlugIn *plug_in)
|
||||
{
|
||||
g_return_if_fail (proc_frame != NULL);
|
||||
g_return_if_fail (PIKA_IS_PLUG_IN (plug_in));
|
||||
|
||||
proc_frame->ref_count--;
|
||||
|
||||
if (proc_frame->ref_count < 1)
|
||||
{
|
||||
pika_plug_in_proc_frame_dispose (proc_frame, plug_in);
|
||||
g_slice_free (PikaPlugInProcFrame, proc_frame);
|
||||
}
|
||||
}
|
||||
|
||||
PikaValueArray *
|
||||
pika_plug_in_proc_frame_get_return_values (PikaPlugInProcFrame *proc_frame)
|
||||
{
|
||||
PikaValueArray *return_vals;
|
||||
|
||||
g_return_val_if_fail (proc_frame != NULL, NULL);
|
||||
|
||||
if (proc_frame->return_vals)
|
||||
{
|
||||
if (pika_value_array_length (proc_frame->return_vals) >=
|
||||
proc_frame->procedure->num_values + 1)
|
||||
{
|
||||
return_vals = proc_frame->return_vals;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Allocate new return values of the correct size. */
|
||||
return_vals = pika_procedure_get_return_values (proc_frame->procedure,
|
||||
TRUE, NULL);
|
||||
|
||||
/* Copy all of the arguments we can. */
|
||||
memcpy (pika_value_array_index (return_vals, 0),
|
||||
pika_value_array_index (proc_frame->return_vals, 0),
|
||||
sizeof (GValue) *
|
||||
pika_value_array_length (proc_frame->return_vals));
|
||||
|
||||
/* Free the old arguments. */
|
||||
memset (pika_value_array_index (proc_frame->return_vals, 0), 0,
|
||||
sizeof (GValue) *
|
||||
pika_value_array_length (proc_frame->return_vals));
|
||||
pika_value_array_unref (proc_frame->return_vals);
|
||||
}
|
||||
|
||||
/* We have consumed any saved values, so clear them. */
|
||||
proc_frame->return_vals = NULL;
|
||||
}
|
||||
else
|
||||
{
|
||||
PikaProcedure *procedure = proc_frame->procedure;
|
||||
GError *error;
|
||||
|
||||
error = g_error_new (PIKA_PDB_ERROR, PIKA_PDB_ERROR_INVALID_RETURN_VALUE,
|
||||
_("Procedure '%s' returned no return values"),
|
||||
pika_object_get_name (procedure));
|
||||
|
||||
return_vals = pika_procedure_get_return_values (procedure, FALSE,
|
||||
error);
|
||||
g_error_free (error);
|
||||
}
|
||||
|
||||
return return_vals;
|
||||
}
|
71
app/plug-in/pikapluginprocframe.h
Normal file
71
app/plug-in/pikapluginprocframe.h
Normal file
@ -0,0 +1,71 @@
|
||||
/* PIKA - Photo and Image Kooker Application
|
||||
* a rebranding of The GNU Image Manipulation Program (created with heckimp)
|
||||
* A derived work which may be trivial. However, any changes may be (C)2023 by Aldercone Studio
|
||||
*
|
||||
* Original copyright, applying to most contents (license remains unchanged):
|
||||
* Copyright (C) 1995 Spencer Kimball and Peter Mattis
|
||||
*
|
||||
* pikapluginprocframe.h
|
||||
*
|
||||
* 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 3 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, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#ifndef __PIKA_PLUG_IN_PROC_FRAME_H__
|
||||
#define __PIKA_PLUG_IN_PROC_FRAME_H__
|
||||
|
||||
|
||||
struct _PikaPlugInProcFrame
|
||||
{
|
||||
gint ref_count;
|
||||
|
||||
PikaContext *main_context;
|
||||
GList *context_stack;
|
||||
|
||||
PikaProcedure *procedure;
|
||||
GMainLoop *main_loop;
|
||||
|
||||
PikaValueArray *return_vals;
|
||||
|
||||
PikaProgress *progress;
|
||||
gboolean progress_created;
|
||||
gulong progress_cancel_id;
|
||||
|
||||
PikaPDBErrorHandler error_handler;
|
||||
|
||||
/* lists of things to clean up on dispose */
|
||||
GList *image_cleanups;
|
||||
GList *item_cleanups;
|
||||
};
|
||||
|
||||
|
||||
PikaPlugInProcFrame * pika_plug_in_proc_frame_new (PikaContext *context,
|
||||
PikaProgress *progress,
|
||||
PikaPlugInProcedure *procedure);
|
||||
void pika_plug_in_proc_frame_init (PikaPlugInProcFrame *proc_frame,
|
||||
PikaContext *context,
|
||||
PikaProgress *progress,
|
||||
PikaPlugInProcedure *procedure);
|
||||
|
||||
void pika_plug_in_proc_frame_dispose (PikaPlugInProcFrame *proc_frame,
|
||||
PikaPlugIn *plug_in);
|
||||
|
||||
PikaPlugInProcFrame * pika_plug_in_proc_frame_ref (PikaPlugInProcFrame *proc_frame);
|
||||
void pika_plug_in_proc_frame_unref (PikaPlugInProcFrame *proc_frame,
|
||||
PikaPlugIn *plug_in);
|
||||
|
||||
PikaValueArray * pika_plug_in_proc_frame_get_return_values
|
||||
(PikaPlugInProcFrame *proc_frame);
|
||||
|
||||
|
||||
#endif /* __PIKA_PLUG_IN_PROC_FRAME_H__ */
|
311
app/plug-in/pikapluginshm.c
Normal file
311
app/plug-in/pikapluginshm.c
Normal file
@ -0,0 +1,311 @@
|
||||
/* PIKA - Photo and Image Kooker Application
|
||||
* a rebranding of The GNU Image Manipulation Program (created with heckimp)
|
||||
* A derived work which may be trivial. However, any changes may be (C)2023 by Aldercone Studio
|
||||
*
|
||||
* Original copyright, applying to most contents (license remains unchanged):
|
||||
* Copyright (C) 1995 Spencer Kimball and Peter Mattis
|
||||
*
|
||||
* pikapluginhsm.c
|
||||
*
|
||||
* 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 3 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, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include "config.h"
|
||||
|
||||
#include <sys/types.h>
|
||||
|
||||
#include <errno.h>
|
||||
|
||||
#if defined(USE_SYSV_SHM)
|
||||
|
||||
#ifdef HAVE_IPC_H
|
||||
#include <sys/ipc.h>
|
||||
#endif
|
||||
|
||||
#ifdef HAVE_SHM_H
|
||||
#include <sys/shm.h>
|
||||
#endif
|
||||
|
||||
#elif defined(USE_POSIX_SHM)
|
||||
|
||||
#ifdef HAVE_UNISTD_H
|
||||
#include <unistd.h>
|
||||
#endif
|
||||
|
||||
#include <fcntl.h>
|
||||
#include <sys/mman.h>
|
||||
|
||||
#endif /* USE_POSIX_SHM */
|
||||
|
||||
#include <gio/gio.h>
|
||||
#include <gegl.h>
|
||||
|
||||
#if defined(G_OS_WIN32) || defined(G_WITH_CYGWIN)
|
||||
|
||||
#define STRICT
|
||||
#include <windows.h>
|
||||
#include <process.h>
|
||||
|
||||
#ifdef G_OS_WIN32
|
||||
#include <fcntl.h>
|
||||
#include <io.h>
|
||||
#endif
|
||||
|
||||
#define USE_WIN32_SHM 1
|
||||
|
||||
#endif /* G_OS_WIN32 || G_WITH_CYGWIN */
|
||||
|
||||
#include "plug-in-types.h"
|
||||
|
||||
#include "core/pika-utils.h"
|
||||
|
||||
#include "pikapluginshm.h"
|
||||
|
||||
#include "pika-log.h"
|
||||
|
||||
|
||||
#define TILE_MAP_SIZE (PIKA_PLUG_IN_TILE_WIDTH * PIKA_PLUG_IN_TILE_HEIGHT * 32)
|
||||
|
||||
#define ERRMSG_SHM_DISABLE "Disabling shared memory tile transport"
|
||||
|
||||
|
||||
struct _PikaPlugInShm
|
||||
{
|
||||
gint shm_id;
|
||||
guchar *shm_addr;
|
||||
|
||||
#if defined(USE_WIN32_SHM)
|
||||
HANDLE shm_handle;
|
||||
#endif
|
||||
};
|
||||
|
||||
|
||||
PikaPlugInShm *
|
||||
pika_plug_in_shm_new (void)
|
||||
{
|
||||
/* allocate a piece of shared memory for use in transporting tiles
|
||||
* to plug-ins. if we can't allocate a piece of shared memory then
|
||||
* we'll fall back on sending the data over the pipe.
|
||||
*/
|
||||
|
||||
PikaPlugInShm *shm = g_slice_new0 (PikaPlugInShm);
|
||||
|
||||
shm->shm_id = -1;
|
||||
|
||||
#if defined(USE_SYSV_SHM)
|
||||
|
||||
/* Use SysV shared memory mechanisms for transferring tile data. */
|
||||
{
|
||||
shm->shm_id = shmget (IPC_PRIVATE, TILE_MAP_SIZE, IPC_CREAT | 0600);
|
||||
|
||||
if (shm->shm_id != -1)
|
||||
{
|
||||
shm->shm_addr = (guchar *) shmat (shm->shm_id, NULL, 0);
|
||||
|
||||
if (shm->shm_addr == (guchar *) -1)
|
||||
{
|
||||
g_printerr ("shmat() failed: %s\n" ERRMSG_SHM_DISABLE,
|
||||
g_strerror (errno));
|
||||
shmctl (shm->shm_id, IPC_RMID, NULL);
|
||||
shm->shm_id = -1;
|
||||
}
|
||||
|
||||
#ifdef IPC_RMID_DEFERRED_RELEASE
|
||||
if (shm->shm_addr != (guchar *) -1)
|
||||
shmctl (shm->shm_id, IPC_RMID, NULL);
|
||||
#endif
|
||||
}
|
||||
else
|
||||
{
|
||||
g_printerr ("shmget() failed: %s\n" ERRMSG_SHM_DISABLE,
|
||||
g_strerror (errno));
|
||||
}
|
||||
}
|
||||
|
||||
#elif defined(USE_WIN32_SHM)
|
||||
|
||||
/* Use Win32 shared memory mechanisms for transferring tile data. */
|
||||
{
|
||||
gint pid;
|
||||
gchar fileMapName[MAX_PATH];
|
||||
wchar_t *w_fileMapName = NULL;
|
||||
|
||||
/* Our shared memory id will be our process ID */
|
||||
pid = GetCurrentProcessId ();
|
||||
|
||||
/* From the id, derive the file map name */
|
||||
g_snprintf (fileMapName, sizeof (fileMapName), "PIKA%d.SHM", pid);
|
||||
|
||||
w_fileMapName = g_utf8_to_utf16 (fileMapName, -1, NULL, NULL, NULL);
|
||||
|
||||
/* Create the file mapping into paging space */
|
||||
shm->shm_handle = CreateFileMappingW (INVALID_HANDLE_VALUE, NULL,
|
||||
PAGE_READWRITE, 0,
|
||||
TILE_MAP_SIZE,
|
||||
w_fileMapName);
|
||||
|
||||
g_free (w_fileMapName);
|
||||
w_fileMapName = NULL;
|
||||
|
||||
if (shm->shm_handle)
|
||||
{
|
||||
/* Map the shared memory into our address space for use */
|
||||
shm->shm_addr = (guchar *) MapViewOfFile (shm->shm_handle,
|
||||
FILE_MAP_ALL_ACCESS,
|
||||
0, 0, TILE_MAP_SIZE);
|
||||
|
||||
/* Verify that we mapped our view */
|
||||
if (shm->shm_addr)
|
||||
{
|
||||
shm->shm_id = pid;
|
||||
}
|
||||
else
|
||||
{
|
||||
g_printerr ("MapViewOfFile error: %u... " ERRMSG_SHM_DISABLE,
|
||||
(unsigned) GetLastError ());
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
g_printerr ("CreateFileMapping error: %u... " ERRMSG_SHM_DISABLE,
|
||||
(unsigned) GetLastError ());
|
||||
}
|
||||
}
|
||||
|
||||
#elif defined(USE_POSIX_SHM)
|
||||
|
||||
/* Use POSIX shared memory mechanisms for transferring tile data. */
|
||||
{
|
||||
gint pid;
|
||||
gchar shm_handle[32];
|
||||
gint shm_fd;
|
||||
|
||||
/* Our shared memory id will be our process ID */
|
||||
pid = pika_get_pid ();
|
||||
|
||||
/* From the id, derive the file map name */
|
||||
g_snprintf (shm_handle, sizeof (shm_handle), "/pika-shm-%d", pid);
|
||||
|
||||
/* Create the file mapping into paging space */
|
||||
shm_fd = shm_open (shm_handle, O_RDWR | O_CREAT, 0600);
|
||||
|
||||
if (shm_fd != -1)
|
||||
{
|
||||
if (ftruncate (shm_fd, TILE_MAP_SIZE) != -1)
|
||||
{
|
||||
/* Map the shared memory into our address space for use */
|
||||
shm->shm_addr = (guchar *) mmap (NULL, TILE_MAP_SIZE,
|
||||
PROT_READ | PROT_WRITE, MAP_SHARED,
|
||||
shm_fd, 0);
|
||||
|
||||
/* Verify that we mapped our view */
|
||||
if (shm->shm_addr != MAP_FAILED)
|
||||
{
|
||||
shm->shm_id = pid;
|
||||
}
|
||||
else
|
||||
{
|
||||
g_printerr ("mmap() failed: %s\n" ERRMSG_SHM_DISABLE,
|
||||
g_strerror (errno));
|
||||
|
||||
shm_unlink (shm_handle);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
g_printerr ("ftruncate() failed: %s\n" ERRMSG_SHM_DISABLE,
|
||||
g_strerror (errno));
|
||||
|
||||
shm_unlink (shm_handle);
|
||||
}
|
||||
|
||||
close (shm_fd);
|
||||
}
|
||||
else
|
||||
{
|
||||
g_printerr ("shm_open() failed: %s\n" ERRMSG_SHM_DISABLE,
|
||||
g_strerror (errno));
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
if (shm->shm_id == -1)
|
||||
{
|
||||
g_slice_free (PikaPlugInShm, shm);
|
||||
shm = NULL;
|
||||
}
|
||||
else
|
||||
{
|
||||
PIKA_LOG (SHM, "attached shared memory segment ID = %d", shm->shm_id);
|
||||
}
|
||||
|
||||
return shm;
|
||||
}
|
||||
|
||||
void
|
||||
pika_plug_in_shm_free (PikaPlugInShm *shm)
|
||||
{
|
||||
g_return_if_fail (shm != NULL);
|
||||
|
||||
if (shm->shm_id != -1)
|
||||
{
|
||||
|
||||
#if defined (USE_SYSV_SHM)
|
||||
|
||||
shmdt (shm->shm_addr);
|
||||
|
||||
#ifndef IPC_RMID_DEFERRED_RELEASE
|
||||
shmctl (shm->shm_id, IPC_RMID, NULL);
|
||||
#endif
|
||||
|
||||
#elif defined(USE_WIN32_SHM)
|
||||
|
||||
if (shm->shm_handle)
|
||||
CloseHandle (shm->shm_handle);
|
||||
|
||||
#elif defined(USE_POSIX_SHM)
|
||||
|
||||
gchar shm_handle[32];
|
||||
|
||||
munmap (shm->shm_addr, TILE_MAP_SIZE);
|
||||
|
||||
g_snprintf (shm_handle, sizeof (shm_handle), "/pika-shm-%d",
|
||||
shm->shm_id);
|
||||
|
||||
shm_unlink (shm_handle);
|
||||
|
||||
#endif
|
||||
|
||||
PIKA_LOG (SHM, "detached shared memory segment ID = %d", shm->shm_id);
|
||||
}
|
||||
|
||||
g_slice_free (PikaPlugInShm, shm);
|
||||
}
|
||||
|
||||
gint
|
||||
pika_plug_in_shm_get_id (PikaPlugInShm *shm)
|
||||
{
|
||||
g_return_val_if_fail (shm != NULL, -1);
|
||||
|
||||
return shm->shm_id;
|
||||
}
|
||||
|
||||
guchar *
|
||||
pika_plug_in_shm_get_addr (PikaPlugInShm *shm)
|
||||
{
|
||||
g_return_val_if_fail (shm != NULL, NULL);
|
||||
|
||||
return shm->shm_addr;
|
||||
}
|
35
app/plug-in/pikapluginshm.h
Normal file
35
app/plug-in/pikapluginshm.h
Normal file
@ -0,0 +1,35 @@
|
||||
/* PIKA - Photo and Image Kooker Application
|
||||
* a rebranding of The GNU Image Manipulation Program (created with heckimp)
|
||||
* A derived work which may be trivial. However, any changes may be (C)2023 by Aldercone Studio
|
||||
*
|
||||
* Original copyright, applying to most contents (license remains unchanged):
|
||||
* Copyright (C) 1995 Spencer Kimball and Peter Mattis
|
||||
*
|
||||
* pikapluginshm.h
|
||||
*
|
||||
* 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 3 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, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#ifndef __PIKA_PLUG_IN_SHM_H__
|
||||
#define __PIKA_PLUG_IN_SHM_H__
|
||||
|
||||
|
||||
PikaPlugInShm * pika_plug_in_shm_new (void);
|
||||
void pika_plug_in_shm_free (PikaPlugInShm *shm);
|
||||
|
||||
gint pika_plug_in_shm_get_id (PikaPlugInShm *shm);
|
||||
guchar * pika_plug_in_shm_get_addr (PikaPlugInShm *shm);
|
||||
|
||||
|
||||
#endif /* __PIKA_PLUG_IN_SHM_H__ */
|
160
app/plug-in/pikatemporaryprocedure.c
Normal file
160
app/plug-in/pikatemporaryprocedure.c
Normal file
@ -0,0 +1,160 @@
|
||||
/* PIKA - Photo and Image Kooker Application
|
||||
* a rebranding of The GNU Image Manipulation Program (created with heckimp)
|
||||
* A derived work which may be trivial. However, any changes may be (C)2023 by Aldercone Studio
|
||||
*
|
||||
* Original copyright, applying to most contents (license remains unchanged):
|
||||
* Copyright (C) 1995 Spencer Kimball and Peter Mattis
|
||||
*
|
||||
* pikatemporaryprocedure.c
|
||||
*
|
||||
* 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 3 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, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include "config.h"
|
||||
|
||||
#include <gdk-pixbuf/gdk-pixbuf.h>
|
||||
#include <gegl.h>
|
||||
|
||||
#include "libpikabase/pikabase.h"
|
||||
|
||||
#include "plug-in-types.h"
|
||||
|
||||
#include "core/pika.h"
|
||||
|
||||
#include "pikaplugin.h"
|
||||
#define __YES_I_NEED_PIKA_PLUG_IN_MANAGER_CALL__
|
||||
#include "pikapluginmanager-call.h"
|
||||
#include "pikatemporaryprocedure.h"
|
||||
|
||||
#include "pika-intl.h"
|
||||
|
||||
|
||||
static void pika_temporary_procedure_finalize (GObject *object);
|
||||
|
||||
static PikaValueArray * pika_temporary_procedure_execute (PikaProcedure *procedure,
|
||||
Pika *pika,
|
||||
PikaContext *context,
|
||||
PikaProgress *progress,
|
||||
PikaValueArray *args,
|
||||
GError **error);
|
||||
static void pika_temporary_procedure_execute_async (PikaProcedure *procedure,
|
||||
Pika *pika,
|
||||
PikaContext *context,
|
||||
PikaProgress *progress,
|
||||
PikaValueArray *args,
|
||||
PikaDisplay *display);
|
||||
|
||||
static GFile * pika_temporary_procedure_get_file (PikaPlugInProcedure *procedure);
|
||||
|
||||
|
||||
G_DEFINE_TYPE (PikaTemporaryProcedure, pika_temporary_procedure,
|
||||
PIKA_TYPE_PLUG_IN_PROCEDURE)
|
||||
|
||||
#define parent_class pika_temporary_procedure_parent_class
|
||||
|
||||
|
||||
static void
|
||||
pika_temporary_procedure_class_init (PikaTemporaryProcedureClass *klass)
|
||||
{
|
||||
GObjectClass *object_class = G_OBJECT_CLASS (klass);
|
||||
PikaProcedureClass *proc_class = PIKA_PROCEDURE_CLASS (klass);
|
||||
PikaPlugInProcedureClass *plug_class = PIKA_PLUG_IN_PROCEDURE_CLASS (klass);
|
||||
|
||||
object_class->finalize = pika_temporary_procedure_finalize;
|
||||
|
||||
proc_class->execute = pika_temporary_procedure_execute;
|
||||
proc_class->execute_async = pika_temporary_procedure_execute_async;
|
||||
|
||||
plug_class->get_file = pika_temporary_procedure_get_file;
|
||||
}
|
||||
|
||||
static void
|
||||
pika_temporary_procedure_init (PikaTemporaryProcedure *proc)
|
||||
{
|
||||
PIKA_PROCEDURE (proc)->proc_type = PIKA_PDB_PROC_TYPE_TEMPORARY;
|
||||
}
|
||||
|
||||
static void
|
||||
pika_temporary_procedure_finalize (GObject *object)
|
||||
{
|
||||
/* PikaTemporaryProcedure *proc = PIKA_TEMPORARY_PROCEDURE (object); */
|
||||
|
||||
G_OBJECT_CLASS (parent_class)->finalize (object);
|
||||
}
|
||||
|
||||
static PikaValueArray *
|
||||
pika_temporary_procedure_execute (PikaProcedure *procedure,
|
||||
Pika *pika,
|
||||
PikaContext *context,
|
||||
PikaProgress *progress,
|
||||
PikaValueArray *args,
|
||||
GError **error)
|
||||
{
|
||||
return pika_plug_in_manager_call_run_temp (pika->plug_in_manager,
|
||||
context, progress,
|
||||
PIKA_TEMPORARY_PROCEDURE (procedure),
|
||||
args);
|
||||
}
|
||||
|
||||
static void
|
||||
pika_temporary_procedure_execute_async (PikaProcedure *procedure,
|
||||
Pika *pika,
|
||||
PikaContext *context,
|
||||
PikaProgress *progress,
|
||||
PikaValueArray *args,
|
||||
PikaDisplay *display)
|
||||
{
|
||||
PikaTemporaryProcedure *temp_procedure = PIKA_TEMPORARY_PROCEDURE (procedure);
|
||||
PikaValueArray *return_vals;
|
||||
|
||||
return_vals = pika_plug_in_manager_call_run_temp (pika->plug_in_manager,
|
||||
context, progress,
|
||||
temp_procedure,
|
||||
args);
|
||||
|
||||
if (return_vals)
|
||||
{
|
||||
PikaPlugInProcedure *proc = PIKA_PLUG_IN_PROCEDURE (procedure);
|
||||
|
||||
pika_plug_in_procedure_handle_return_values (proc,
|
||||
pika, progress,
|
||||
return_vals);
|
||||
pika_value_array_unref (return_vals);
|
||||
}
|
||||
}
|
||||
|
||||
static GFile *
|
||||
pika_temporary_procedure_get_file (PikaPlugInProcedure *procedure)
|
||||
{
|
||||
return PIKA_TEMPORARY_PROCEDURE (procedure)->plug_in->file;
|
||||
}
|
||||
|
||||
|
||||
/* public functions */
|
||||
|
||||
PikaProcedure *
|
||||
pika_temporary_procedure_new (PikaPlugIn *plug_in)
|
||||
{
|
||||
PikaTemporaryProcedure *proc;
|
||||
|
||||
g_return_val_if_fail (PIKA_IS_PLUG_IN (plug_in), NULL);
|
||||
|
||||
proc = g_object_new (PIKA_TYPE_TEMPORARY_PROCEDURE, NULL);
|
||||
|
||||
proc->plug_in = plug_in;
|
||||
|
||||
PIKA_PLUG_IN_PROCEDURE (proc)->file = g_file_new_for_path ("none");
|
||||
|
||||
return PIKA_PROCEDURE (proc);
|
||||
}
|
59
app/plug-in/pikatemporaryprocedure.h
Normal file
59
app/plug-in/pikatemporaryprocedure.h
Normal file
@ -0,0 +1,59 @@
|
||||
/* PIKA - Photo and Image Kooker Application
|
||||
* a rebranding of The GNU Image Manipulation Program (created with heckimp)
|
||||
* A derived work which may be trivial. However, any changes may be (C)2023 by Aldercone Studio
|
||||
*
|
||||
* Original copyright, applying to most contents (license remains unchanged):
|
||||
* Copyright (C) 1995 Spencer Kimball and Peter Mattis
|
||||
*
|
||||
* pikatemporaryprocedure.h
|
||||
*
|
||||
* 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 3 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, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#ifndef __PIKA_TEMPORARY_PROCEDURE_H__
|
||||
#define __PIKA_TEMPORARY_PROCEDURE_H__
|
||||
|
||||
|
||||
#include "pikapluginprocedure.h"
|
||||
|
||||
|
||||
#define PIKA_TYPE_TEMPORARY_PROCEDURE (pika_temporary_procedure_get_type ())
|
||||
#define PIKA_TEMPORARY_PROCEDURE(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), PIKA_TYPE_TEMPORARY_PROCEDURE, PikaTemporaryProcedure))
|
||||
#define PIKA_TEMPORARY_PROCEDURE_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), PIKA_TYPE_TEMPORARY_PROCEDURE, PikaTemporaryProcedureClass))
|
||||
#define PIKA_IS_TEMPORARY_PROCEDURE(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), PIKA_TYPE_TEMPORARY_PROCEDURE))
|
||||
#define PIKA_IS_TEMPORARY_PROCEDURE_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), PIKA_TYPE_TEMPORARY_PROCEDURE))
|
||||
#define PIKA_TEMPORARY_PROCEDURE_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), PIKA_TYPE_TEMPORARY_PROCEDURE, PikaTemporaryProcedureClass))
|
||||
|
||||
|
||||
typedef struct _PikaTemporaryProcedureClass PikaTemporaryProcedureClass;
|
||||
|
||||
struct _PikaTemporaryProcedure
|
||||
{
|
||||
PikaPlugInProcedure parent_instance;
|
||||
|
||||
PikaPlugIn *plug_in;
|
||||
};
|
||||
|
||||
struct _PikaTemporaryProcedureClass
|
||||
{
|
||||
PikaPlugInProcedureClass parent_class;
|
||||
};
|
||||
|
||||
|
||||
GType pika_temporary_procedure_get_type (void) G_GNUC_CONST;
|
||||
|
||||
PikaProcedure * pika_temporary_procedure_new (PikaPlugIn *plug_in);
|
||||
|
||||
|
||||
#endif /* __PIKA_TEMPORARY_PROCEDURE_H__ */
|
119
app/plug-in/plug-in-enums.c
Normal file
119
app/plug-in/plug-in-enums.c
Normal file
@ -0,0 +1,119 @@
|
||||
|
||||
/* Generated data (by pika-mkenums) */
|
||||
|
||||
#include "stamp-plug-in-enums.h"
|
||||
#include "config.h"
|
||||
#include <gio/gio.h>
|
||||
#include "libpikabase/pikabase.h"
|
||||
#include "plug-in-enums.h"
|
||||
#include "pika-intl.h"
|
||||
|
||||
/* enumerations from "plug-in-enums.h" */
|
||||
GType
|
||||
pika_plug_in_image_type_get_type (void)
|
||||
{
|
||||
static const GFlagsValue values[] =
|
||||
{
|
||||
{ PIKA_PLUG_IN_RGB_IMAGE, "PIKA_PLUG_IN_RGB_IMAGE", "rgb-image" },
|
||||
{ PIKA_PLUG_IN_GRAY_IMAGE, "PIKA_PLUG_IN_GRAY_IMAGE", "gray-image" },
|
||||
{ PIKA_PLUG_IN_INDEXED_IMAGE, "PIKA_PLUG_IN_INDEXED_IMAGE", "indexed-image" },
|
||||
{ PIKA_PLUG_IN_RGBA_IMAGE, "PIKA_PLUG_IN_RGBA_IMAGE", "rgba-image" },
|
||||
{ PIKA_PLUG_IN_GRAYA_IMAGE, "PIKA_PLUG_IN_GRAYA_IMAGE", "graya-image" },
|
||||
{ PIKA_PLUG_IN_INDEXEDA_IMAGE, "PIKA_PLUG_IN_INDEXEDA_IMAGE", "indexeda-image" },
|
||||
{ 0, NULL, NULL }
|
||||
};
|
||||
|
||||
static const PikaFlagsDesc descs[] =
|
||||
{
|
||||
{ PIKA_PLUG_IN_RGB_IMAGE, "PIKA_PLUG_IN_RGB_IMAGE", NULL },
|
||||
{ PIKA_PLUG_IN_GRAY_IMAGE, "PIKA_PLUG_IN_GRAY_IMAGE", NULL },
|
||||
{ PIKA_PLUG_IN_INDEXED_IMAGE, "PIKA_PLUG_IN_INDEXED_IMAGE", NULL },
|
||||
{ PIKA_PLUG_IN_RGBA_IMAGE, "PIKA_PLUG_IN_RGBA_IMAGE", NULL },
|
||||
{ PIKA_PLUG_IN_GRAYA_IMAGE, "PIKA_PLUG_IN_GRAYA_IMAGE", NULL },
|
||||
{ PIKA_PLUG_IN_INDEXEDA_IMAGE, "PIKA_PLUG_IN_INDEXEDA_IMAGE", NULL },
|
||||
{ 0, NULL, NULL }
|
||||
};
|
||||
|
||||
static GType type = 0;
|
||||
|
||||
if (G_UNLIKELY (! type))
|
||||
{
|
||||
type = g_flags_register_static ("PikaPlugInImageType", values);
|
||||
pika_type_set_translation_context (type, "plug-in-image-type");
|
||||
pika_flags_set_value_descriptions (type, descs);
|
||||
}
|
||||
|
||||
return type;
|
||||
}
|
||||
|
||||
GType
|
||||
pika_plug_in_call_mode_get_type (void)
|
||||
{
|
||||
static const GEnumValue values[] =
|
||||
{
|
||||
{ PIKA_PLUG_IN_CALL_NONE, "PIKA_PLUG_IN_CALL_NONE", "none" },
|
||||
{ PIKA_PLUG_IN_CALL_RUN, "PIKA_PLUG_IN_CALL_RUN", "run" },
|
||||
{ PIKA_PLUG_IN_CALL_QUERY, "PIKA_PLUG_IN_CALL_QUERY", "query" },
|
||||
{ PIKA_PLUG_IN_CALL_INIT, "PIKA_PLUG_IN_CALL_INIT", "init" },
|
||||
{ 0, NULL, NULL }
|
||||
};
|
||||
|
||||
static const PikaEnumDesc descs[] =
|
||||
{
|
||||
{ PIKA_PLUG_IN_CALL_NONE, "PIKA_PLUG_IN_CALL_NONE", NULL },
|
||||
{ PIKA_PLUG_IN_CALL_RUN, "PIKA_PLUG_IN_CALL_RUN", NULL },
|
||||
{ PIKA_PLUG_IN_CALL_QUERY, "PIKA_PLUG_IN_CALL_QUERY", NULL },
|
||||
{ PIKA_PLUG_IN_CALL_INIT, "PIKA_PLUG_IN_CALL_INIT", NULL },
|
||||
{ 0, NULL, NULL }
|
||||
};
|
||||
|
||||
static GType type = 0;
|
||||
|
||||
if (G_UNLIKELY (! type))
|
||||
{
|
||||
type = g_enum_register_static ("PikaPlugInCallMode", values);
|
||||
pika_type_set_translation_context (type, "plug-in-call-mode");
|
||||
pika_enum_set_value_descriptions (type, descs);
|
||||
}
|
||||
|
||||
return type;
|
||||
}
|
||||
|
||||
GType
|
||||
pika_file_procedure_group_get_type (void)
|
||||
{
|
||||
static const GEnumValue values[] =
|
||||
{
|
||||
{ PIKA_FILE_PROCEDURE_GROUP_NONE, "PIKA_FILE_PROCEDURE_GROUP_NONE", "none" },
|
||||
{ PIKA_FILE_PROCEDURE_GROUP_ANY, "PIKA_FILE_PROCEDURE_GROUP_ANY", "any" },
|
||||
{ PIKA_FILE_PROCEDURE_GROUP_OPEN, "PIKA_FILE_PROCEDURE_GROUP_OPEN", "open" },
|
||||
{ PIKA_FILE_PROCEDURE_GROUP_SAVE, "PIKA_FILE_PROCEDURE_GROUP_SAVE", "save" },
|
||||
{ PIKA_FILE_PROCEDURE_GROUP_EXPORT, "PIKA_FILE_PROCEDURE_GROUP_EXPORT", "export" },
|
||||
{ 0, NULL, NULL }
|
||||
};
|
||||
|
||||
static const PikaEnumDesc descs[] =
|
||||
{
|
||||
{ PIKA_FILE_PROCEDURE_GROUP_NONE, "PIKA_FILE_PROCEDURE_GROUP_NONE", NULL },
|
||||
{ PIKA_FILE_PROCEDURE_GROUP_ANY, "PIKA_FILE_PROCEDURE_GROUP_ANY", NULL },
|
||||
{ PIKA_FILE_PROCEDURE_GROUP_OPEN, "PIKA_FILE_PROCEDURE_GROUP_OPEN", NULL },
|
||||
{ PIKA_FILE_PROCEDURE_GROUP_SAVE, "PIKA_FILE_PROCEDURE_GROUP_SAVE", NULL },
|
||||
{ PIKA_FILE_PROCEDURE_GROUP_EXPORT, "PIKA_FILE_PROCEDURE_GROUP_EXPORT", NULL },
|
||||
{ 0, NULL, NULL }
|
||||
};
|
||||
|
||||
static GType type = 0;
|
||||
|
||||
if (G_UNLIKELY (! type))
|
||||
{
|
||||
type = g_enum_register_static ("PikaFileProcedureGroup", values);
|
||||
pika_type_set_translation_context (type, "file-procedure-group");
|
||||
pika_enum_set_value_descriptions (type, descs);
|
||||
}
|
||||
|
||||
return type;
|
||||
}
|
||||
|
||||
|
||||
/* Generated data ends here */
|
||||
|
68
app/plug-in/plug-in-enums.h
Normal file
68
app/plug-in/plug-in-enums.h
Normal file
@ -0,0 +1,68 @@
|
||||
/* PIKA - Photo and Image Kooker Application
|
||||
* a rebranding of The GNU Image Manipulation Program (created with heckimp)
|
||||
* A derived work which may be trivial. However, any changes may be (C)2023 by Aldercone Studio
|
||||
*
|
||||
* Original copyright, applying to most contents (license remains unchanged):
|
||||
* Copyright (C) 1995 Spencer Kimball and Peter Mattis
|
||||
*
|
||||
* 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 3 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, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#ifndef __PLUG_IN_ENUMS_H__
|
||||
#define __PLUG_IN_ENUMS_H__
|
||||
|
||||
|
||||
#define PIKA_TYPE_PLUG_IN_IMAGE_TYPE (pika_plug_in_image_type_get_type ())
|
||||
|
||||
GType pika_plug_in_image_type_get_type (void) G_GNUC_CONST;
|
||||
|
||||
typedef enum
|
||||
{
|
||||
PIKA_PLUG_IN_RGB_IMAGE = 1 << 0,
|
||||
PIKA_PLUG_IN_GRAY_IMAGE = 1 << 1,
|
||||
PIKA_PLUG_IN_INDEXED_IMAGE = 1 << 2,
|
||||
PIKA_PLUG_IN_RGBA_IMAGE = 1 << 3,
|
||||
PIKA_PLUG_IN_GRAYA_IMAGE = 1 << 4,
|
||||
PIKA_PLUG_IN_INDEXEDA_IMAGE = 1 << 5
|
||||
} PikaPlugInImageType;
|
||||
|
||||
|
||||
#define PIKA_TYPE_PLUG_CALL_MODE (pika_plug_in_call_mode_get_type ())
|
||||
|
||||
GType pika_plug_in_call_mode_get_type (void) G_GNUC_CONST;
|
||||
|
||||
typedef enum
|
||||
{
|
||||
PIKA_PLUG_IN_CALL_NONE,
|
||||
PIKA_PLUG_IN_CALL_RUN,
|
||||
PIKA_PLUG_IN_CALL_QUERY,
|
||||
PIKA_PLUG_IN_CALL_INIT
|
||||
} PikaPlugInCallMode;
|
||||
|
||||
|
||||
#define PIKA_TYPE_FILE_PROCEDURE_GROUP (pika_file_procedure_group_get_type ())
|
||||
|
||||
GType pika_file_procedure_group_get_type (void) G_GNUC_CONST;
|
||||
|
||||
typedef enum
|
||||
{
|
||||
PIKA_FILE_PROCEDURE_GROUP_NONE,
|
||||
PIKA_FILE_PROCEDURE_GROUP_ANY,
|
||||
PIKA_FILE_PROCEDURE_GROUP_OPEN,
|
||||
PIKA_FILE_PROCEDURE_GROUP_SAVE,
|
||||
PIKA_FILE_PROCEDURE_GROUP_EXPORT
|
||||
} PikaFileProcedureGroup;
|
||||
|
||||
|
||||
#endif /* __PLUG_IN_ENUMS_H__ */
|
125
app/plug-in/plug-in-menu-path.c
Normal file
125
app/plug-in/plug-in-menu-path.c
Normal file
@ -0,0 +1,125 @@
|
||||
/* PIKA - Photo and Image Kooker Application
|
||||
* a rebranding of The GNU Image Manipulation Program (created with heckimp)
|
||||
* A derived work which may be trivial. However, any changes may be (C)2023 by Aldercone Studio
|
||||
*
|
||||
* Original copyright, applying to most contents (license remains unchanged):
|
||||
* Copyright (C) 1995 Spencer Kimball and Peter Mattis
|
||||
*
|
||||
* plug-in-menu-path.c
|
||||
*
|
||||
* 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 3 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, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include "config.h"
|
||||
|
||||
#include <string.h>
|
||||
|
||||
#include <gio/gio.h>
|
||||
|
||||
#include "libpikabase/pikabase.h"
|
||||
|
||||
#include "plug-in-types.h"
|
||||
|
||||
#include "plug-in-menu-path.h"
|
||||
|
||||
|
||||
typedef struct _MenuPathMapping MenuPathMapping;
|
||||
|
||||
struct _MenuPathMapping
|
||||
{
|
||||
const gchar *orig_path;
|
||||
const gchar *label;
|
||||
const gchar *mapped_path;
|
||||
};
|
||||
|
||||
|
||||
static const MenuPathMapping menu_path_mappings[] =
|
||||
{
|
||||
{ "<Image>/File/Acquire", NULL, "<Image>/File/Create/Acquire" },
|
||||
{ "<Image>/File/New", NULL, "<Image>/File/Create" },
|
||||
{ "<Image>/Image/Mode/Color Profile", NULL, "<Image>/Image/Color Management" },
|
||||
{ NULL, NULL, NULL }
|
||||
};
|
||||
|
||||
|
||||
gchar *
|
||||
plug_in_menu_path_map (const gchar *menu_path,
|
||||
const gchar *menu_label)
|
||||
{
|
||||
const MenuPathMapping *mapping;
|
||||
gchar *stripped_label = NULL;
|
||||
|
||||
g_return_val_if_fail (menu_path != NULL, NULL);
|
||||
|
||||
if (menu_label)
|
||||
stripped_label = pika_strip_uline (menu_label);
|
||||
|
||||
for (mapping = menu_path_mappings; mapping->orig_path; mapping++)
|
||||
{
|
||||
if (g_str_has_prefix (menu_path, mapping->orig_path))
|
||||
{
|
||||
gint orig_len = strlen (mapping->orig_path);
|
||||
gchar *mapped_path;
|
||||
|
||||
/* if the mapping has a label, only map if the passed label
|
||||
* is identical and the paths' lengths match exactly.
|
||||
*/
|
||||
if (mapping->label &&
|
||||
(! stripped_label ||
|
||||
strlen (menu_path) != orig_len ||
|
||||
strcmp (mapping->label, stripped_label)))
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
if (strlen (menu_path) > orig_len)
|
||||
mapped_path = g_strconcat (mapping->mapped_path,
|
||||
menu_path + orig_len,
|
||||
NULL);
|
||||
else
|
||||
mapped_path = g_strdup (mapping->mapped_path);
|
||||
|
||||
#if PIKA_UNSTABLE
|
||||
{
|
||||
gchar *orig;
|
||||
gchar *mapped;
|
||||
|
||||
if (menu_label)
|
||||
{
|
||||
orig = g_strdup_printf ("%s/%s", menu_path, stripped_label);
|
||||
mapped = g_strdup_printf ("%s/%s", mapped_path, stripped_label);
|
||||
}
|
||||
else
|
||||
{
|
||||
orig = g_strdup (menu_path);
|
||||
mapped = g_strdup (mapped_path);
|
||||
}
|
||||
|
||||
g_printerr (" mapped '%s' to '%s'\n", orig, mapped);
|
||||
|
||||
g_free (orig);
|
||||
g_free (mapped);
|
||||
}
|
||||
#endif
|
||||
|
||||
g_free (stripped_label);
|
||||
|
||||
return mapped_path;
|
||||
}
|
||||
}
|
||||
|
||||
g_free (stripped_label);
|
||||
|
||||
return g_strdup (menu_path);
|
||||
}
|
32
app/plug-in/plug-in-menu-path.h
Normal file
32
app/plug-in/plug-in-menu-path.h
Normal file
@ -0,0 +1,32 @@
|
||||
/* PIKA - Photo and Image Kooker Application
|
||||
* a rebranding of The GNU Image Manipulation Program (created with heckimp)
|
||||
* A derived work which may be trivial. However, any changes may be (C)2023 by Aldercone Studio
|
||||
*
|
||||
* Original copyright, applying to most contents (license remains unchanged):
|
||||
* Copyright (C) 1995 Spencer Kimball and Peter Mattis
|
||||
*
|
||||
* plug-in-menu-path.h
|
||||
*
|
||||
* 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 3 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, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#ifndef __PLUG_IN_MENU_PATH_H__
|
||||
#define __PLUG_IN_MENU_PATH_H__
|
||||
|
||||
|
||||
gchar * plug_in_menu_path_map (const gchar *menu_path,
|
||||
const gchar *menu_label);
|
||||
|
||||
|
||||
#endif /* __PLUG_IN_MENU_PATH_H__ */
|
1333
app/plug-in/plug-in-rc.c
Normal file
1333
app/plug-in/plug-in-rc.c
Normal file
File diff suppressed because it is too large
Load Diff
37
app/plug-in/plug-in-rc.h
Normal file
37
app/plug-in/plug-in-rc.h
Normal file
@ -0,0 +1,37 @@
|
||||
/* PIKA - Photo and Image Kooker Application
|
||||
* a rebranding of The GNU Image Manipulation Program (created with heckimp)
|
||||
* A derived work which may be trivial. However, any changes may be (C)2023 by Aldercone Studio
|
||||
*
|
||||
* Original copyright, applying to most contents (license remains unchanged):
|
||||
* Copyright (C) 1995 Spencer Kimball and Peter Mattis
|
||||
*
|
||||
* plug-in-rc.h
|
||||
* Copyright (C) 2001 Sven Neumann <sven@gimp.org>
|
||||
*
|
||||
* 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 3 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, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#ifndef __PLUG_IN_RC_H__
|
||||
#define __PLUG_IN_RC_H__
|
||||
|
||||
|
||||
GSList * plug_in_rc_parse (Pika *pika,
|
||||
GFile *file,
|
||||
GError **error);
|
||||
gboolean plug_in_rc_write (GSList *plug_in_defs,
|
||||
GFile *file,
|
||||
GError **error);
|
||||
|
||||
|
||||
#endif /* __PLUG_IN_RC_H__ */
|
44
app/plug-in/plug-in-types.h
Normal file
44
app/plug-in/plug-in-types.h
Normal file
@ -0,0 +1,44 @@
|
||||
/* PIKA - Photo and Image Kooker Application
|
||||
* a rebranding of The GNU Image Manipulation Program (created with heckimp)
|
||||
* A derived work which may be trivial. However, any changes may be (C)2023 by Aldercone Studio
|
||||
*
|
||||
* Original copyright, applying to most contents (license remains unchanged):
|
||||
* Copyright (C) 1995 Spencer Kimball and Peter Mattis
|
||||
*
|
||||
* 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 3 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, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#ifndef __PLUG_IN_TYPES_H__
|
||||
#define __PLUG_IN_TYPES_H__
|
||||
|
||||
|
||||
#include "core/core-types.h"
|
||||
|
||||
#include "plug-in/plug-in-enums.h"
|
||||
|
||||
|
||||
#define PIKA_PLUG_IN_TILE_WIDTH 128
|
||||
#define PIKA_PLUG_IN_TILE_HEIGHT 128
|
||||
|
||||
|
||||
typedef struct _PikaPlugIn PikaPlugIn;
|
||||
typedef struct _PikaPlugInDebug PikaPlugInDebug;
|
||||
typedef struct _PikaPlugInDef PikaPlugInDef;
|
||||
typedef struct _PikaPlugInManager PikaPlugInManager;
|
||||
typedef struct _PikaPlugInMenuBranch PikaPlugInMenuBranch;
|
||||
typedef struct _PikaPlugInProcFrame PikaPlugInProcFrame;
|
||||
typedef struct _PikaPlugInShm PikaPlugInShm;
|
||||
|
||||
|
||||
#endif /* __PLUG_IN_TYPES_H__ */
|
Reference in New Issue
Block a user