/* 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 * * pikaloadprocedure.c * Copyright (C) 2019 Michael Natterer * * 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 . */ #include "config.h" #include "pika.h" #include "pikaloadprocedure.h" #include "pikapdb_pdb.h" /** * PikaLoadProcedure: * * A [class@Procedure] subclass that makes it easier to write file load * procedures. * * It automatically adds the standard * * ( [enum@RunMode], [iface@Gio.File] ) * * arguments and the standard * * ( [class@Image] ) * * return value of a load procedure. It is possible to add additional * arguments. * * When invoked via [method@Procedure.run], it unpacks these standard * arguments and calls @run_func which is a [callback@RunImageFunc]. The * "args" [struct@ValueArray] of [callback@RunImageFunc] only contains * additionally added arguments. */ struct _PikaLoadProcedurePrivate { PikaRunLoadFunc run_func; gpointer run_data; GDestroyNotify run_data_destroy; gboolean handles_raw; gchar *thumbnail_proc; }; static void pika_load_procedure_constructed (GObject *object); static void pika_load_procedure_finalize (GObject *object); static void pika_load_procedure_install (PikaProcedure *procedure); static PikaValueArray * pika_load_procedure_run (PikaProcedure *procedure, const PikaValueArray *args); static PikaProcedureConfig * pika_load_procedure_create_config (PikaProcedure *procedure, GParamSpec **args, gint n_args); G_DEFINE_TYPE_WITH_PRIVATE (PikaLoadProcedure, pika_load_procedure, PIKA_TYPE_FILE_PROCEDURE) #define parent_class pika_load_procedure_parent_class static void pika_load_procedure_class_init (PikaLoadProcedureClass *klass) { GObjectClass *object_class = G_OBJECT_CLASS (klass); PikaProcedureClass *procedure_class = PIKA_PROCEDURE_CLASS (klass); object_class->constructed = pika_load_procedure_constructed; object_class->finalize = pika_load_procedure_finalize; procedure_class->install = pika_load_procedure_install; procedure_class->run = pika_load_procedure_run; procedure_class->create_config = pika_load_procedure_create_config; } static void pika_load_procedure_init (PikaLoadProcedure *procedure) { procedure->priv = pika_load_procedure_get_instance_private (procedure); } static void pika_load_procedure_constructed (GObject *object) { PikaProcedure *procedure = PIKA_PROCEDURE (object); G_OBJECT_CLASS (parent_class)->constructed (object); PIKA_PROC_ARG_FILE (procedure, "file", "File", "The file to load", PIKA_PARAM_READWRITE); PIKA_PROC_VAL_IMAGE (procedure, "image", "Image", "Output image", TRUE, PIKA_PARAM_READWRITE); } static void pika_load_procedure_finalize (GObject *object) { PikaLoadProcedure *procedure = PIKA_LOAD_PROCEDURE (object); if (procedure->priv->run_data_destroy) procedure->priv->run_data_destroy (procedure->priv->run_data); g_clear_pointer (&procedure->priv->thumbnail_proc, g_free); G_OBJECT_CLASS (parent_class)->finalize (object); } static void pika_load_procedure_install (PikaProcedure *procedure) { PikaLoadProcedure *load_proc = PIKA_LOAD_PROCEDURE (procedure); PikaFileProcedure *file_proc = PIKA_FILE_PROCEDURE (procedure); const gchar *mime_types; gint priority; PIKA_PROCEDURE_CLASS (parent_class)->install (procedure); _pika_pdb_set_file_proc_load_handler (pika_procedure_get_name (procedure), pika_file_procedure_get_extensions (file_proc), pika_file_procedure_get_prefixes (file_proc), pika_file_procedure_get_magics (file_proc)); if (pika_file_procedure_get_handles_remote (file_proc)) _pika_pdb_set_file_proc_handles_remote (pika_procedure_get_name (procedure)); mime_types = pika_file_procedure_get_mime_types (file_proc); if (mime_types) _pika_pdb_set_file_proc_mime_types (pika_procedure_get_name (procedure), mime_types); priority = pika_file_procedure_get_priority (file_proc); if (priority != 0) _pika_pdb_set_file_proc_priority (pika_procedure_get_name (procedure), priority); if (load_proc->priv->handles_raw) _pika_pdb_set_file_proc_handles_raw (pika_procedure_get_name (procedure)); if (load_proc->priv->thumbnail_proc) _pika_pdb_set_file_proc_thumbnail_loader (pika_procedure_get_name (procedure), load_proc->priv->thumbnail_proc); } #define ARG_OFFSET 2 static PikaValueArray * pika_load_procedure_run (PikaProcedure *procedure, const PikaValueArray *args) { PikaLoadProcedure *load_proc = PIKA_LOAD_PROCEDURE (procedure); PikaValueArray *remaining; PikaValueArray *return_values; PikaRunMode run_mode; GFile *file; gint i; run_mode = PIKA_VALUES_GET_ENUM (args, 0); file = PIKA_VALUES_GET_FILE (args, 1); remaining = pika_value_array_new (pika_value_array_length (args) - ARG_OFFSET); for (i = ARG_OFFSET; i < pika_value_array_length (args); i++) { GValue *value = pika_value_array_index (args, i); pika_value_array_append (remaining, value); } return_values = load_proc->priv->run_func (procedure, run_mode, file, remaining, load_proc->priv->run_data); pika_value_array_unref (remaining); return return_values; } static PikaProcedureConfig * pika_load_procedure_create_config (PikaProcedure *procedure, GParamSpec **args, gint n_args) { if (n_args > ARG_OFFSET) { args += ARG_OFFSET; n_args -= ARG_OFFSET; } else { args = NULL; n_args = 0; } return PIKA_PROCEDURE_CLASS (parent_class)->create_config (procedure, args, n_args); } /* public functions */ /** * pika_load_procedure_new: * @plug_in: a #PikaPlugIn. * @name: the new procedure's name. * @proc_type: the new procedure's #PikaPDBProcType. * @run_func: the run function for the new procedure. * @run_data: user data passed to @run_func. * @run_data_destroy: (nullable): free function for @run_data, or %NULL. * * Creates a new load procedure named @name which will call @run_func * when invoked. * * See pika_procedure_new() for information about @proc_type. * * Returns: (transfer full): a new #PikaProcedure. * * Since: 3.0 **/ PikaProcedure * pika_load_procedure_new (PikaPlugIn *plug_in, const gchar *name, PikaPDBProcType proc_type, PikaRunLoadFunc run_func, gpointer run_data, GDestroyNotify run_data_destroy) { PikaLoadProcedure *procedure; g_return_val_if_fail (PIKA_IS_PLUG_IN (plug_in), NULL); g_return_val_if_fail (pika_is_canonical_identifier (name), NULL); g_return_val_if_fail (proc_type != PIKA_PDB_PROC_TYPE_INTERNAL, NULL); g_return_val_if_fail (proc_type != PIKA_PDB_PROC_TYPE_EXTENSION, NULL); g_return_val_if_fail (run_func != NULL, NULL); procedure = g_object_new (PIKA_TYPE_LOAD_PROCEDURE, "plug-in", plug_in, "name", name, "procedure-type", proc_type, NULL); procedure->priv->run_func = run_func; procedure->priv->run_data = run_data; procedure->priv->run_data_destroy = run_data_destroy; return PIKA_PROCEDURE (procedure); } /** * pika_load_procedure_set_handles_raw: * @procedure: A load procedure object. * @handles_raw: The procedure's handles raw flag. * * Registers a load procedure as capable of handling raw digital camera loads. * * Since: 3.0 **/ void pika_load_procedure_set_handles_raw (PikaLoadProcedure *procedure, gint handles_raw) { g_return_if_fail (PIKA_IS_LOAD_PROCEDURE (procedure)); procedure->priv->handles_raw = handles_raw; } /** * pika_load_procedure_get_handles_raw: * @procedure: A load procedure object. * * Returns the procedure's 'handles raw' flag as set with * [method@GimpLoadProcedure.set_handles_raw]. * * Returns: The procedure's 'handles raw' flag. * * Since: 3.0 **/ gint pika_load_procedure_get_handles_raw (PikaLoadProcedure *procedure) { g_return_val_if_fail (PIKA_IS_LOAD_PROCEDURE (procedure), 0); return procedure->priv->handles_raw; } /** * pika_load_procedure_set_thumbnail_loader: * @procedure: A load procedure object. * @thumbnail_proc: The name of the thumbnail load procedure. * * Associates a thumbnail loader with a file load procedure. * * Some file formats allow for embedded thumbnails, other file formats * contain a scalable image or provide the image data in different * resolutions. A file plug-in for such a format may register a * special procedure that allows PIKA to load a thumbnail preview of * the image. This procedure is then associated with the standard * load procedure using this function. * * Since: 3.0 **/ void pika_load_procedure_set_thumbnail_loader (PikaLoadProcedure *procedure, const gchar *thumbnail_proc) { g_return_if_fail (PIKA_IS_LOAD_PROCEDURE (procedure)); g_free (procedure->priv->thumbnail_proc); procedure->priv->thumbnail_proc = g_strdup (thumbnail_proc); } /** * pika_load_procedure_get_thumbnail_loader: * @procedure: A load procedure object. * * Returns the procedure's thumbnail loader procedure as set with * [method@GimpLoadProcedure.set_thumbnail_loader]. * * Returns: The procedure's thumbnail loader procedure * * Since: 3.0 **/ const gchar * pika_load_procedure_get_thumbnail_loader (PikaLoadProcedure *procedure) { g_return_val_if_fail (PIKA_IS_LOAD_PROCEDURE (procedure), NULL); return procedure->priv->thumbnail_proc; }