From 0e13a1f1bc87eaa5ccf88acaba87dd0449d64697 Mon Sep 17 00:00:00 2001 From: jakob Date: Mon, 15 May 2017 20:17:23 -0400 Subject: [PATCH] Implemented a basic Python scripting engine, optional compilation. --- cfg/checks/audio.mk | 2 +- cfg/checks/check_features.mk | 6 +++ cfg/checks/python.mk | 20 ++++++++++ cfg/targets/help.mk | 1 + src/api.c | 59 ++++++++++++++++++++++++++++++ src/api.h | 30 +++++++++++++++ src/execute.c | 3 ++ src/global_commands.h | 4 ++ src/help.c | 20 ++++++++-- src/python_api.c | 71 ++++++++++++++++++++++++++++++++++++ src/python_api.h | 33 +++++++++++++++++ src/toxic.c | 14 +++++++ 12 files changed, 258 insertions(+), 5 deletions(-) create mode 100644 cfg/checks/python.mk create mode 100644 src/api.c create mode 100644 src/api.h create mode 100644 src/python_api.c create mode 100644 src/python_api.h diff --git a/cfg/checks/audio.mk b/cfg/checks/audio.mk index eceba9e..6e2cf84 100644 --- a/cfg/checks/audio.mk +++ b/cfg/checks/audio.mk @@ -18,4 +18,4 @@ else ifneq ($(MAKECMDGOALS), clean) $(warning WARNING -- Toxic will be compiled without audio support) $(warning WARNING -- You need these libraries for audio support) $(warning WARNING -- $(MISSING_AUDIO_LIBS)) -endif \ No newline at end of file +endif diff --git a/cfg/checks/check_features.mk b/cfg/checks/check_features.mk index f739cba..aa66ad1 100644 --- a/cfg/checks/check_features.mk +++ b/cfg/checks/check_features.mk @@ -40,6 +40,12 @@ ifneq ($(QR_PNG), disabled) -include $(CHECKS_DIR)/qr_png.mk endif +# Check if we want build Python scripting support +PYTHON = $(shell if [ -z "$(DISABLE_PYTHON)" ] || [ "$(DISABLE_PYTHON)" = "0" ] ; then echo enabled ; else echo disabled ; fi) +ifneq ($(PYTHON), disabled) + -include $(CHECKS_DIR)/python.mk +endif + # Check if we can build Toxic CHECK_LIBS = $(shell $(PKG_CONFIG) --exists $(LIBS) || echo -n "error") ifneq ($(CHECK_LIBS), error) diff --git a/cfg/checks/python.mk b/cfg/checks/python.mk new file mode 100644 index 0000000..34216b8 --- /dev/null +++ b/cfg/checks/python.mk @@ -0,0 +1,20 @@ +# Variables for Python scripting support +PYTHON_LIBS = python3 +PYTHON_CFLAGS = -DPYTHON +PYTHON_OBJ = api.o python_api.o + +# Check if we can build Python scripting support +CHECK_PYTHON_LIBS = $(shell $(PKG_CONFIG) --exists $(PYTHON_LIBS) || echo -n "error") +ifneq ($(CHECK_PYTHON_LIBS), error) + # LIBS += $(PYTHON_LIBS) + + # Unwise hacks... You will pay for this. + LDFLAGS += $(shell python3-config --ldflags) + CFLAGS += $(PYTHON_CFLAGS) $(shell python3-config --cflags) + OBJ += $(PYTHON_OBJ) +else ifneq ($(MAKECMDGOALS), clean) + MISSING_AUDIO_LIBS = $(shell for lib in $(PYTHON_LIBS) ; do if ! $(PKG_CONFIG) --exists $$lib ; then echo $$lib ; fi ; done) + $(warning WARNING -- Toxic will be compiled without Python scripting support) + $(warning WARNING -- You need these libraries for Python scripting support) + $(warning WARNING -- $(MISSING_AUDIO_LIBS)) +endif diff --git a/cfg/targets/help.mk b/cfg/targets/help.mk index b99c897..1d09520 100644 --- a/cfg/targets/help.mk +++ b/cfg/targets/help.mk @@ -15,6 +15,7 @@ help: @echo " DISABLE_SOUND_NOTIFY: Set to \"1\" to force building without sound notification support" @echo " DISABLE_DESKTOP_NOTIFY: Set to \"1\" to force building without desktop notifications support" @echo " DISABLE_QRPNG: Set to \"1\" to force building without QR exported as PNG support" + @echo " DISABLE_PYTHON: Set to \"1\" to force building without Python scripting support" @echo " USER_CFLAGS: Add custom flags to default CFLAGS" @echo " USER_LDFLAGS: Add custom flags to default LDFLAGS" @echo " PREFIX: Specify a prefix directory for binaries, data files,... (default is \"$(abspath $(PREFIX))\")" diff --git a/src/api.c b/src/api.c new file mode 100644 index 0000000..65cf667 --- /dev/null +++ b/src/api.c @@ -0,0 +1,59 @@ +/* api.c + * + * + * Copyright (C) 2017 Toxic All Rights Reserved. + * + * This file is part of Toxic. + * + * Toxic 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. + * + * Toxic 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 Toxic. If not, see . + * + */ + +#include "line_info.h" +#include "python_api.h" +#include "windows.h" + +extern ToxWindow *prompt; + +void api_display(const char * const msg) +{ + if (msg == NULL) + return; + + line_info_add(prompt, NULL, NULL, NULL, SYS_MSG, 0, 0, msg); +} + +void cmd_run(WINDOW *window, ToxWindow *self, Tox *m, int argc, char (*argv)[MAX_STR_SIZE]) +{ + FILE *fp; + const char *error_str; + + if ( argc != 1 ) { + if ( argc < 1 ) error_str = "Path must be specified!"; + else error_str = "Only one argument allowed!"; + + line_info_add(self, NULL, NULL, NULL, SYS_MSG, 0, 0, error_str); + return; + } + + fp = fopen(argv[1], "r"); + if ( fp == NULL ) { + error_str = "Path does not exist!"; + + line_info_add(self, NULL, NULL, NULL, SYS_MSG, 0, 0, error_str); + return; + } + run_python(fp, argv[1]); + fclose(fp); +} diff --git a/src/api.h b/src/api.h new file mode 100644 index 0000000..86c33a2 --- /dev/null +++ b/src/api.h @@ -0,0 +1,30 @@ +/* api.h + * + * + * Copyright (C) 2014 Toxic All Rights Reserved. + * + * This file is part of Toxic. + * + * Toxic 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. + * + * Toxic 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 Toxic. If not, see . + * + */ + +#ifndef API_H +#define API_H + +#include "windows.h" + +void api_display(const char * const msg); + +#endif /* #define API_H */ diff --git a/src/execute.c b/src/execute.c index b0d3d9d..6b0f4c2 100644 --- a/src/execute.c +++ b/src/execute.c @@ -67,6 +67,9 @@ static struct cmd_func global_commands[] = { { "/lsvdev", cmd_list_video_devices }, { "/svdev" , cmd_change_video_device }, #endif /* VIDEO */ +#ifdef PYTHON + { "/run", cmd_run }, +#endif /* PYTHON */ { NULL, NULL }, }; diff --git a/src/global_commands.h b/src/global_commands.h index 8c5c3e7..bd9a519 100644 --- a/src/global_commands.h +++ b/src/global_commands.h @@ -56,4 +56,8 @@ void cmd_list_video_devices(WINDOW *, ToxWindow *, Tox *, int argc, char (*argv) void cmd_change_video_device(WINDOW *, ToxWindow *, Tox *, int argc, char (*argv)[MAX_STR_SIZE]); #endif /* VIDEO */ +#ifdef PYTHON +void cmd_run(WINDOW *, ToxWindow *, Tox *, int argc, char (*argv)[MAX_STR_SIZE]); +#endif + #endif /* #define GLOBAL_COMMANDS_H */ diff --git a/src/help.c b/src/help.c index 13b127c..b8c193e 100644 --- a/src/help.c +++ b/src/help.c @@ -185,6 +185,14 @@ static void help_draw_global(ToxWindow *self) wprintw(win, " /svdev : Set active video device\n"); #endif /* VIDEO */ +#ifdef PYTHON + wattron(win, A_BOLD); + wprintw(win, "\n Scripting:\n"); + wattroff(win, A_BOLD); + + wprintw(win, " /run : Load and run the script at path\n"); +#endif /* PYTHON */ + help_draw_bottom_menu(win); box(win, ACS_VLINE, ACS_HLINE); @@ -302,6 +310,7 @@ static void help_draw_contacts(ToxWindow *self) void help_onKey(ToxWindow *self, wint_t key) { + int height; switch (key) { case 'x': case T_KEY_ESC: @@ -320,13 +329,16 @@ void help_onKey(ToxWindow *self, wint_t key) break; case 'g': + height = 22; #ifdef VIDEO - help_init_window(self, 30, 80); + height += 8; #elif AUDIO - help_init_window(self, 26, 80); -#else - help_init_window(self, 22, 80); + height += 4; #endif +#ifdef PYTHON + height += 2; +#endif + help_init_window(self, height, 80); self->help->type = HELP_GLOBAL; break; diff --git a/src/python_api.c b/src/python_api.c new file mode 100644 index 0000000..f06715e --- /dev/null +++ b/src/python_api.c @@ -0,0 +1,71 @@ +/* python_api.c + * + * + * Copyright (C) 2017 Toxic All Rights Reserved. + * + * This file is part of Toxic. + * + * Toxic 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. + * + * Toxic 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 Toxic. If not, see . + * + */ + +#include + +#include "api.h" + +static PyObject *python_api_display(PyObject *self, PyObject *args) +{ + const char *msg; + if (!PyArg_ParseTuple(args, "s", &msg)) + return NULL; + + api_display(msg); + + Py_RETURN_NONE; +} + +static PyMethodDef ToxicApiMethods[] = { + {"display", python_api_display, METH_VARARGS, "Display a message to the primary prompt"}, + {NULL, NULL, 0, NULL}, +}; + +static struct PyModuleDef toxic_api_module = { + PyModuleDef_HEAD_INIT, + "toxic_api", + NULL, /* TODO: Module documentation. */ + -1, /* TODO: Assumption that no per-interpreter state is maintained. */ + ToxicApiMethods +}; + +PyMODINIT_FUNC PyInit_toxic_api(void) +{ + return PyModule_Create(&toxic_api_module); +} + +void terminate_python(void) +{ + Py_FinalizeEx(); +} + +void init_python(void) +{ + PyImport_AppendInittab("toxic_api", PyInit_toxic_api); + /* TODO: Set Python program name. */ + Py_Initialize(); +} + +void run_python(FILE *fp, char *path) +{ + PyRun_SimpleFile(fp, path); +} diff --git a/src/python_api.h b/src/python_api.h new file mode 100644 index 0000000..214230f --- /dev/null +++ b/src/python_api.h @@ -0,0 +1,33 @@ +/* python_api.h + * + * + * Copyright (C) 2017 Toxic All Rights Reserved. + * + * This file is part of Toxic. + * + * Toxic 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. + * + * Toxic 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 Toxic. If not, see . + * + */ + +#ifndef PYTHON_API_H +#define PYTHON_API_H + +#include + +PyMODINIT_FUNC PyInit_toxic_api(void); +void terminate_python(void); +void init_python(void); +void run_python(FILE *fp, char *path); + +#endif /* #define PYTHON_API_H */ diff --git a/src/toxic.c b/src/toxic.c index 358e45d..6c0f63d 100644 --- a/src/toxic.c +++ b/src/toxic.c @@ -75,6 +75,10 @@ ToxAV *av; #endif /* AUDIO */ +#ifdef PYTHON +#include "python_api.h" +#endif + #ifndef PACKAGE_DATADIR #define PACKAGE_DATADIR "." #endif @@ -162,6 +166,10 @@ void exit_toxic_success(Tox *m) terminate_audio(); #endif /* AUDIO */ +#ifdef PYTHON + terminate_python(); +#endif /* PYTHON */ + free_global_data(); tox_kill(m); endwin(); @@ -1211,6 +1219,12 @@ int main(int argc, char **argv) #endif /* AUDIO */ +#ifdef PYTHON + + init_python(); + +#endif /* PYTHON */ + init_notify(60, 3000); /* screen/tmux auto-away timer */