122 lines
6.0 KiB
C
122 lines
6.0 KiB
C
/* Extensiones nativas en C (y base de las de Lua).
|
|
*
|
|
* ADVERTENCIA DE SEGURIDAD: una extensión nativa es código que se ejecuta
|
|
* DENTRO del proceso de Tahgibu con sus mismos permisos. Los permisos
|
|
* (capabilities) de abajo controlan qué funciones del host se le ofrecen,
|
|
* pero NO pueden impedir que el código nativo lea/escriba memoria o
|
|
* archivos por su cuenta. Instala solo extensiones de origen confiable.
|
|
*
|
|
* Una extensión nativa es una biblioteca compartida (.so/.dll) que exporta:
|
|
* const uint32_t tgb_plugin_api_version; (usa TGB_PLUGIN_DECLARE_API_VERSION)
|
|
* tgb_status tgb_plugin_init(const tgb_host_api *host, tgb_plugin_handle *self,
|
|
* tgb_plugin_info *info);
|
|
* void tgb_plugin_shutdown(tgb_plugin_handle *self); (opcional)
|
|
*
|
|
* Las funciones de lectura/edición del host solo funcionan DENTRO de un
|
|
* comando (mientras Tahgibu ejecuta tgb_plugin_command_fn), nunca en init. */
|
|
#ifndef TAHGIBU_PLUGIN_H
|
|
#define TAHGIBU_PLUGIN_H
|
|
|
|
#include "tahgibu/document.h"
|
|
|
|
#ifdef __cplusplus
|
|
extern "C" {
|
|
#endif
|
|
|
|
#define TGB_PLUGIN_API_VERSION 1
|
|
|
|
#if defined(_WIN32)
|
|
#define TGB_PLUGIN_EXPORT __declspec(dllexport)
|
|
#else
|
|
#define TGB_PLUGIN_EXPORT __attribute__((visibility("default")))
|
|
#endif
|
|
|
|
/* Declara la versión de API con la que se compiló la extensión. Sin ella (o con otra) no se carga. */
|
|
#define TGB_PLUGIN_DECLARE_API_VERSION TGB_PLUGIN_EXPORT const uint32_t tgb_plugin_api_version = TGB_PLUGIN_API_VERSION
|
|
|
|
typedef enum tgb_capability {
|
|
TGB_CAP_READ_DOCUMENT = 1u << 0, /* leer dimensiones, fotogramas, píxeles */
|
|
TGB_CAP_EDIT_DOCUMENT = 1u << 1, /* modificar el documento (siempre con historial) */
|
|
TGB_CAP_EVENTS = 1u << 2 /* recibir eventos */
|
|
} tgb_capability;
|
|
|
|
typedef struct tgb_plugin_handle tgb_plugin_handle; /* identidad de la extensión (opaco) */
|
|
|
|
typedef struct tgb_plugin_info {
|
|
const char *name; /* nombre legible */
|
|
const char *version; /* p. ej. "1.0.0" */
|
|
uint32_t required_caps; /* combinación de tgb_capability */
|
|
} tgb_plugin_info;
|
|
|
|
/* Un comando recibe el documento activo a través del host (no directamente). */
|
|
typedef tgb_status (*tgb_plugin_command_fn)(tgb_plugin_handle *self, void *user);
|
|
|
|
typedef struct tgb_host_api {
|
|
uint32_t api_version; /* = TGB_PLUGIN_API_VERSION */
|
|
uint32_t struct_size; /* sizeof(tgb_host_api) del host */
|
|
uint32_t (*granted_caps)(tgb_plugin_handle *self);
|
|
void (*log)(tgb_plugin_handle *self, const char *message);
|
|
tgb_status (*register_command)(tgb_plugin_handle *self, const char *name,
|
|
tgb_plugin_command_fn fn, void *user);
|
|
/* TGB_CAP_EVENTS */
|
|
tgb_status (*subscribe)(tgb_plugin_handle *self, tgb_event_fn fn, void *user);
|
|
/* TGB_CAP_READ_DOCUMENT */
|
|
int (*doc_width)(tgb_plugin_handle *self);
|
|
int (*doc_height)(tgb_plugin_handle *self);
|
|
size_t (*doc_frame_count)(tgb_plugin_handle *self);
|
|
size_t (*doc_layer_count)(tgb_plugin_handle *self);
|
|
tgb_color (*get_pixel)(tgb_plugin_handle *self, size_t frame, size_t layer, int x, int y);
|
|
/* TGB_CAP_EDIT_DOCUMENT: todo lo editado entre begin y end es una operación deshacible */
|
|
tgb_status (*edit_begin)(tgb_plugin_handle *self, size_t frame, size_t layer);
|
|
tgb_status (*put_pixel)(tgb_plugin_handle *self, int x, int y, tgb_color color);
|
|
tgb_status (*fill_rect)(tgb_plugin_handle *self, tgb_rect r, tgb_color color);
|
|
tgb_status (*edit_end)(tgb_plugin_handle *self);
|
|
tgb_status (*add_frame)(tgb_plugin_handle *self, size_t index);
|
|
} tgb_host_api;
|
|
|
|
/* ---------------- Gestor de extensiones (lado de la aplicación) ---------------- */
|
|
typedef struct tgb_plugin_manager tgb_plugin_manager;
|
|
|
|
typedef struct tgb_plugin_entry_info {
|
|
char id[64];
|
|
char kind[8]; /* "native" o "lua" */
|
|
char file[256];
|
|
char name[64];
|
|
char version[32];
|
|
bool enabled;
|
|
bool loaded;
|
|
uint32_t granted_caps;
|
|
uint32_t required_caps;
|
|
char last_error[160];
|
|
} tgb_plugin_entry_info;
|
|
|
|
/* El registro vive en <config_dir>/extensions.json; los archivos instalados
|
|
* en <data_dir>/extensions/. NUNCA se carga nada que no esté en el registro
|
|
* y habilitado explícitamente. */
|
|
tgb_status tgb_plugin_manager_create(tgb_context *ctx, tgb_plugin_manager **out);
|
|
void tgb_plugin_manager_destroy(tgb_plugin_manager *mgr); /* descarga todo */
|
|
/* Copia el archivo a la carpeta de extensiones y lo registra DESHABILITADO. */
|
|
tgb_status tgb_plugin_install(tgb_plugin_manager *mgr, const char *source_path,
|
|
const char *id, size_t *out_index); /* id: [a-z0-9_-], 1..48; .lua = Lua */
|
|
/* granted_caps = permisos que el usuario concede. Falla si no cubren los requeridos. */
|
|
tgb_status tgb_plugin_enable(tgb_plugin_manager *mgr, size_t index, uint32_t granted_caps);
|
|
tgb_status tgb_plugin_disable(tgb_plugin_manager *mgr, size_t index);
|
|
tgb_status tgb_plugin_remove(tgb_plugin_manager *mgr, size_t index); /* borra archivo y registro */
|
|
size_t tgb_plugin_count(const tgb_plugin_manager *mgr);
|
|
tgb_status tgb_plugin_info_at(const tgb_plugin_manager *mgr, size_t index, tgb_plugin_entry_info *out);
|
|
/* OJO: los índices de comandos CAMBIAN al habilitar, deshabilitar o eliminar extensiones.
|
|
* Una interfaz debe guardar el NOMBRE ("id:comando") y ejecutar con tgb_plugin_run_command_named. */
|
|
size_t tgb_plugin_command_count(const tgb_plugin_manager *mgr);
|
|
tgb_status tgb_plugin_command_name(const tgb_plugin_manager *mgr, size_t cmd_index,
|
|
char *buf, size_t buf_size);
|
|
/* Ejecuta un comando sobre un documento como UNA operación deshacible.
|
|
* Si el comando falla, se deshace todo lo que hizo (el documento queda como estaba). */
|
|
tgb_status tgb_plugin_run_command(tgb_plugin_manager *mgr, size_t cmd_index, tgb_document *doc);
|
|
/* Igual, pero identificando el comando por su nombre estable "id:comando". TGB_ERR_NOT_FOUND si no existe. */
|
|
tgb_status tgb_plugin_run_command_named(tgb_plugin_manager *mgr, const char *full_name, tgb_document *doc);
|
|
|
|
#ifdef __cplusplus
|
|
}
|
|
#endif
|
|
#endif
|