mirror of
https://github.com/profanity-im/profanity.git
synced 2024-11-03 19:37:16 -05:00
Added plugin load list as preference, moved python hooks
This commit is contained in:
parent
140a2ad0e3
commit
580b14ab68
@ -24,7 +24,8 @@ profanity_SOURCES = \
|
||||
src/config/theme.c src/config/theme.h \
|
||||
src/plugins/plugins.h src/plugins/plugins.c \
|
||||
src/plugins/api.h src/plugins/api.c \
|
||||
src/plugins/callbacks.h src/plugins/callbacks.c
|
||||
src/plugins/callbacks.h src/plugins/callbacks.c \
|
||||
src/plugins/python_plugins.h src/plugins/python_plugins.c
|
||||
|
||||
TESTS = tests/testsuite
|
||||
check_PROGRAMS = tests/testsuite
|
||||
|
@ -257,6 +257,19 @@ prefs_set_autoaway_time(gint value)
|
||||
_save_prefs();
|
||||
}
|
||||
|
||||
gchar **
|
||||
prefs_get_plugins(void)
|
||||
{
|
||||
if (!g_key_file_has_group(prefs, "plugins")) {
|
||||
return NULL;
|
||||
}
|
||||
if (!g_key_file_has_key(prefs, "plugins", "load", NULL)) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return g_key_file_get_string_list(prefs, "plugins", "load", NULL, NULL);
|
||||
}
|
||||
|
||||
static void
|
||||
_save_prefs(void)
|
||||
{
|
||||
|
@ -84,6 +84,8 @@ gint prefs_get_autoping(void);
|
||||
gint prefs_get_autoaway_time(void);
|
||||
void prefs_set_autoaway_time(gint value);
|
||||
|
||||
gchar** prefs_get_plugins(void);
|
||||
|
||||
void prefs_add_login(const char *jid);
|
||||
|
||||
gboolean prefs_get_boolean(preference_t pref);
|
||||
|
@ -134,7 +134,7 @@ api_send_line(PyObject *self, PyObject *args)
|
||||
}
|
||||
|
||||
static PyObject *
|
||||
api_get_current_recipient(void)
|
||||
api_get_current_recipient(PyObject *self, PyObject *args)
|
||||
{
|
||||
win_type_t win_type = ui_current_win_type();
|
||||
if (win_type == WIN_CHAT) {
|
||||
|
@ -22,74 +22,104 @@
|
||||
|
||||
#include <Python.h>
|
||||
|
||||
#include "config/preferences.h"
|
||||
#include "plugins/api.h"
|
||||
#include "plugins/callbacks.h"
|
||||
#include "plugins/plugins.h"
|
||||
#include "plugins/python_plugins.h"
|
||||
#include "ui/ui.h"
|
||||
|
||||
static GSList* _get_module_names(void);
|
||||
static void _run_plugins(const char * const function, PyObject *p_args);
|
||||
|
||||
static GSList* plugins;
|
||||
|
||||
static void
|
||||
_check_error(void)
|
||||
{
|
||||
if (PyErr_Occurred()) {
|
||||
PyErr_Print();
|
||||
PyErr_Clear();
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
plugins_init(void)
|
||||
{
|
||||
plugins = NULL;
|
||||
PyObject *p_module;
|
||||
|
||||
GSList *module_names = _get_module_names();
|
||||
|
||||
// initialse python and path
|
||||
Py_Initialize();
|
||||
_check_error();
|
||||
python_check_error();
|
||||
api_init();
|
||||
_check_error();
|
||||
|
||||
python_check_error();
|
||||
// TODO change to use XDG spec
|
||||
GString *path = g_string_new(Py_GetPath());
|
||||
g_string_append(path, ":./plugins/");
|
||||
PySys_SetPath(path->str);
|
||||
_check_error();
|
||||
python_check_error();
|
||||
g_string_free(path, TRUE);
|
||||
|
||||
if (module_names != NULL) {
|
||||
cons_show("Loading plugins...");
|
||||
|
||||
GSList *module_name = module_names;
|
||||
|
||||
while (module_name != NULL) {
|
||||
p_module = PyImport_ImportModule(module_name->data);
|
||||
_check_error();
|
||||
if (p_module != NULL) {
|
||||
cons_show("Loaded plugin: %s", module_name->data);
|
||||
plugins = g_slist_append(plugins, p_module);
|
||||
// load plugins
|
||||
gchar **plugins_load = prefs_get_plugins();
|
||||
if (plugins_load != NULL) {
|
||||
int i;
|
||||
for (i = 0; i < g_strv_length(plugins_load); i++)
|
||||
{
|
||||
gchar *filename = plugins_load[i];
|
||||
if (g_str_has_suffix(filename, ".py")) {
|
||||
gchar *module_name = g_strndup(filename, strlen(filename) - 3);
|
||||
p_module = PyImport_ImportModule(module_name);
|
||||
python_check_error();
|
||||
if (p_module != NULL) {
|
||||
cons_show("Loaded plugin: %s", module_name);
|
||||
ProfPlugin *plugin = malloc(sizeof(ProfPlugin));
|
||||
plugin->name = module_name;
|
||||
plugin->lang = PYTHON;
|
||||
plugin->module = p_module;
|
||||
plugin->init_func = python_init_hook;
|
||||
plugin->on_start_func = python_on_start_hook;
|
||||
plugin->on_connect_func = python_on_connect_hook;
|
||||
plugin->on_message_func = python_on_message_hook;
|
||||
plugins = g_slist_append(plugins, plugin);
|
||||
}
|
||||
g_free(module_name);
|
||||
}
|
||||
|
||||
module_name = g_slist_next(module_name);
|
||||
}
|
||||
|
||||
PyObject *p_args = Py_BuildValue("ss", PACKAGE_VERSION, PACKAGE_STATUS);
|
||||
_run_plugins("prof_init", p_args);
|
||||
Py_XDECREF(p_args);
|
||||
_check_error();
|
||||
// initialise plugins
|
||||
GSList *curr = plugins;
|
||||
while (curr != NULL) {
|
||||
ProfPlugin *plugin = curr->data;
|
||||
plugin->init_func(plugin, PACKAGE_VERSION, PACKAGE_STATUS);
|
||||
python_check_error();
|
||||
curr = g_slist_next(curr);
|
||||
}
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
void
|
||||
plugins_on_start(void)
|
||||
{
|
||||
_run_plugins("prof_on_start", NULL);
|
||||
_check_error();
|
||||
GSList *curr = plugins;
|
||||
while (curr != NULL) {
|
||||
ProfPlugin *plugin = curr->data;
|
||||
plugin->on_start_func(plugin);
|
||||
curr = g_slist_next(curr);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
plugins_on_connect(void)
|
||||
{
|
||||
GSList *curr = plugins;
|
||||
while (curr != NULL) {
|
||||
ProfPlugin *plugin = curr->data;
|
||||
plugin->on_connect_func(plugin);
|
||||
curr = g_slist_next(curr);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
plugins_on_message(const char * const jid, const char * const message)
|
||||
{
|
||||
GSList *curr = plugins;
|
||||
while (curr != NULL) {
|
||||
ProfPlugin *plugin = curr->data;
|
||||
plugin->on_message_func(plugin, jid, message);
|
||||
curr = g_slist_next(curr);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
@ -97,63 +127,3 @@ plugins_shutdown(void)
|
||||
{
|
||||
Py_Finalize();
|
||||
}
|
||||
|
||||
void
|
||||
plugins_on_connect(void)
|
||||
{
|
||||
_run_plugins("prof_on_connect", NULL);
|
||||
}
|
||||
|
||||
void
|
||||
plugins_on_message(const char * const jid, const char * const message)
|
||||
{
|
||||
PyObject *p_args = Py_BuildValue("ss", jid, message);
|
||||
_run_plugins("prof_on_message", p_args);
|
||||
Py_XDECREF(p_args);
|
||||
}
|
||||
|
||||
static GSList *
|
||||
_get_module_names(void)
|
||||
{
|
||||
GSList *result = NULL;
|
||||
|
||||
// TODO change to use XDG
|
||||
GDir *plugins_dir = g_dir_open("./plugins", 0, NULL);
|
||||
|
||||
if (plugins_dir != NULL) {
|
||||
const gchar *file = g_dir_read_name(plugins_dir);
|
||||
while (file != NULL) {
|
||||
if (g_str_has_suffix(file, ".py")) {
|
||||
gchar *module_name = g_strndup(file, strlen(file) - 3);
|
||||
result = g_slist_append(result, module_name);
|
||||
}
|
||||
file = g_dir_read_name(plugins_dir);
|
||||
}
|
||||
g_dir_close(plugins_dir);
|
||||
return result;
|
||||
} else {
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
_run_plugins(const char * const function, PyObject *p_args)
|
||||
{
|
||||
GSList *plugin = plugins;
|
||||
PyObject *p_function;
|
||||
|
||||
while (plugin != NULL) {
|
||||
PyObject *p_module = plugin->data;
|
||||
if (PyObject_HasAttrString(p_module, function)) {
|
||||
p_function = PyObject_GetAttrString(p_module, function);
|
||||
_check_error();
|
||||
if (p_function && PyCallable_Check(p_function)) {
|
||||
PyObject_CallObject(p_function, p_args);
|
||||
_check_error();
|
||||
Py_XDECREF(p_function);
|
||||
}
|
||||
}
|
||||
|
||||
plugin = g_slist_next(plugin);
|
||||
}
|
||||
}
|
||||
|
@ -23,6 +23,22 @@
|
||||
#ifndef PLUGINS_H
|
||||
#define PLUGINS_H
|
||||
|
||||
typedef enum {
|
||||
PYTHON
|
||||
} lang_t;
|
||||
|
||||
typedef struct prof_plugin_t {
|
||||
char *name;
|
||||
lang_t lang;
|
||||
void *module;
|
||||
void (*init_func)(struct prof_plugin_t* plugin, const char * const version,
|
||||
const char * const status);
|
||||
void (*on_start_func)(struct prof_plugin_t* plugin);
|
||||
void (*on_connect_func)(struct prof_plugin_t* plugin);
|
||||
void (*on_message_func)(struct prof_plugin_t* plugin,
|
||||
const char * const jid, const char * const message);
|
||||
} ProfPlugin;
|
||||
|
||||
void plugins_init(void);
|
||||
void plugins_on_start(void);
|
||||
void plugins_on_connect(void);
|
||||
|
109
src/plugins/python_plugins.c
Normal file
109
src/plugins/python_plugins.c
Normal file
@ -0,0 +1,109 @@
|
||||
/*
|
||||
* python_plugins.c
|
||||
*
|
||||
* Copyright (C) 2012, 2013 James Booth <boothj5@gmail.com>
|
||||
*
|
||||
* This file is part of Profanity.
|
||||
*
|
||||
* Profanity 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.
|
||||
*
|
||||
* Profanity 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 Profanity. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
#include <Python.h>
|
||||
|
||||
#include "config/preferences.h"
|
||||
#include "plugins/api.h"
|
||||
#include "plugins/callbacks.h"
|
||||
#include "plugins/plugins.h"
|
||||
#include "plugins/python_plugins.h"
|
||||
#include "ui/ui.h"
|
||||
|
||||
void
|
||||
python_init_hook(ProfPlugin *plugin, const char * const version, const char * const status)
|
||||
{
|
||||
PyObject *p_args = Py_BuildValue("ss", version, status);
|
||||
PyObject *p_function;
|
||||
|
||||
PyObject *p_module = plugin->module;
|
||||
if (PyObject_HasAttrString(p_module, "prof_init")) {
|
||||
p_function = PyObject_GetAttrString(p_module, "prof_init");
|
||||
python_check_error();
|
||||
if (p_function && PyCallable_Check(p_function)) {
|
||||
PyObject_CallObject(p_function, p_args);
|
||||
python_check_error();
|
||||
Py_XDECREF(p_function);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
python_on_start_hook(ProfPlugin *plugin)
|
||||
{
|
||||
PyObject *p_function;
|
||||
|
||||
PyObject *p_module = plugin->module;
|
||||
if (PyObject_HasAttrString(p_module, "prof_on_start")) {
|
||||
p_function = PyObject_GetAttrString(p_module, "prof_on_start");
|
||||
python_check_error();
|
||||
if (p_function && PyCallable_Check(p_function)) {
|
||||
PyObject_CallObject(p_function, NULL);
|
||||
python_check_error();
|
||||
Py_XDECREF(p_function);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
python_on_connect_hook(ProfPlugin *plugin)
|
||||
{
|
||||
PyObject *p_function;
|
||||
|
||||
PyObject *p_module = plugin->module;
|
||||
if (PyObject_HasAttrString(p_module, "prof_on_connect")) {
|
||||
p_function = PyObject_GetAttrString(p_module, "prof_on_connect");
|
||||
python_check_error();
|
||||
if (p_function && PyCallable_Check(p_function)) {
|
||||
PyObject_CallObject(p_function, NULL);
|
||||
python_check_error();
|
||||
Py_XDECREF(p_function);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
python_on_message_hook(ProfPlugin *plugin, const char * const jid, const char * const message)
|
||||
{
|
||||
PyObject *p_args = Py_BuildValue("ss", jid, message);
|
||||
PyObject *p_function;
|
||||
|
||||
PyObject *p_module = plugin->module;
|
||||
if (PyObject_HasAttrString(p_module, "prof_on_message")) {
|
||||
p_function = PyObject_GetAttrString(p_module, "prof_on_message");
|
||||
python_check_error();
|
||||
if (p_function && PyCallable_Check(p_function)) {
|
||||
PyObject_CallObject(p_function, p_args);
|
||||
python_check_error();
|
||||
Py_XDECREF(p_function);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
python_check_error(void)
|
||||
{
|
||||
if (PyErr_Occurred()) {
|
||||
PyErr_Print();
|
||||
PyErr_Clear();
|
||||
}
|
||||
}
|
35
src/plugins/python_plugins.h
Normal file
35
src/plugins/python_plugins.h
Normal file
@ -0,0 +1,35 @@
|
||||
/*
|
||||
* python_plugins.h
|
||||
*
|
||||
* Copyright (C) 2012, 2013 James Booth <boothj5@gmail.com>
|
||||
*
|
||||
* This file is part of Profanity.
|
||||
*
|
||||
* Profanity 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.
|
||||
*
|
||||
* Profanity 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 Profanity. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef PYTHON_PLUGINS_H
|
||||
#define PYTHON_PLUGINS_H
|
||||
|
||||
#include "plugins/plugins.h"
|
||||
|
||||
void python_init_hook(ProfPlugin *plugin, const char * const version, const char * const status);
|
||||
void python_on_start_hook(ProfPlugin *plugin);
|
||||
void python_on_connect_hook(ProfPlugin *plugin);
|
||||
void python_on_message_hook(ProfPlugin *plugin, const char * const jid, const char * const message);
|
||||
|
||||
void python_check_error(void);
|
||||
|
||||
#endif
|
Loading…
Reference in New Issue
Block a user