Add event-hooking.
[screen-lua.git] / src / python.c
blobd314db47613161f5e6d7b3fcf922cc681c2fd1a3
1 /* Python scripting support
3 * Copyright (c) 2009 Sadrul Habib Chowdhury (sadrul@users.sf.net)
5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation; either version 3, or (at your option)
8 * any later version.
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
15 * You should have received a copy of the GNU General Public License
16 * along with this program (see the file COPYING); if not, write to the
17 * Free Software Foundation, Inc.,
18 * 51 Franklin Street, Fifth Floor, Boston, MA 02111-1301 USA
20 ****************************************************************
22 #include <sys/types.h>
24 #include "config.h"
25 #include "screen.h"
26 #include "script.h"
27 #include <sys/stat.h>
28 #include <unistd.h>
30 #include <stdio.h>
31 #include <string.h>
32 #include <stdlib.h>
34 #include "extern.h"
35 #include "logfile.h"
37 #include <Python.h>
38 #include <structmember.h>
40 extern struct win *windows;
41 extern struct display *display, *displays;
43 static PyObject * SPy_Get(PyObject *obj, void *closure);
44 static PyObject * SPy_Set(PyObject *obj, PyObject *value, void *closure);
45 static int PyDispatch(void *handler, const char *params, va_list va);
47 typedef struct
49 char *name;
50 char *doc;
52 int type;
53 size_t offset1;
54 size_t offset2;
55 PyObject * (*conv)(void *);
56 } SPyClosure;
58 #define REGISTER_TYPE(type, Type, closures) \
59 static int \
60 register_##type(PyObject *module) \
61 { \
62 static PyGetSetDef getsets[sizeof(closures)]; \
63 int i, count = sizeof(closures); \
64 for (i = 0; i < count; i++) \
65 { \
66 getsets[i].name = closures[i].name; \
67 getsets[i].doc = closures[i].doc; \
68 getsets[i].closure = &closures[i]; \
69 getsets[i].get = SPy_Get; \
70 getsets[i].set = SPy_Set; \
71 } \
72 PyType##Type.tp_getset = getsets; \
73 PyType_Ready(&PyType##Type); \
74 Py_INCREF(&PyType##Type); \
75 PyModule_AddObject(module, #Type, (PyObject *)&PyType##Type); \
76 return 1; \
79 #define DEFINE_TYPE(str, Type) \
80 typedef struct \
81 { \
82 PyObject_HEAD \
83 str *_obj; \
84 } Py##Type; \
86 static PyTypeObject PyType##Type = \
87 { \
88 PyObject_HEAD_INIT(NULL) \
89 .ob_size = 0, \
90 .tp_name = "screen." #Type, \
91 .tp_basicsize = sizeof(Py##Type), \
92 .tp_flags = Py_TPFLAGS_DEFAULT, \
93 .tp_doc = #Type " object", \
94 .tp_methods = NULL, \
95 .tp_getset = NULL, \
96 }; \
98 static PyObject * \
99 PyObject_From##Type(str *_obj) \
101 Py##Type *obj = PyType##Type.tp_alloc(&PyType##Type, 0); \
102 obj->_obj = _obj; \
103 return (PyObject *)obj; \
106 static PyObject *
107 PyString_FromStringSafe(const char *str)
109 if (str)
110 return PyString_FromString(str);
111 Py_INCREF(Py_None);
112 return Py_None;
115 /** Window {{{ */
116 DEFINE_TYPE(struct win, Window)
118 #define SPY_CLOSURE(name, doc, type, member, func) \
119 {name, doc, type, offsetof(PyWindow, _obj), offsetof(struct win, member), func}
120 static SPyClosure wclosures[] =
122 SPY_CLOSURE("title", "Window title", T_STRING, w_title, NULL),
123 SPY_CLOSURE("number", "Window number", T_INT, w_number, NULL),
124 SPY_CLOSURE("dir", "Window directory", T_STRING, w_dir, NULL),
125 SPY_CLOSURE("tty", "TTY belonging to the window", T_STRING_INPLACE, w_tty, NULL),
126 SPY_CLOSURE("group", "The group the window belongs to", T_OBJECT_EX, w_group, PyObject_FromWindow),
127 SPY_CLOSURE("pid", "Window pid", T_INT, w_pid, NULL),
128 {NULL}
130 REGISTER_TYPE(window, Window, wclosures)
131 #undef SPY_CLOSURE
132 /** }}} */
134 /** Display {{{ */
135 DEFINE_TYPE(struct display, Display)
137 #define SPY_CLOSURE(name, doc, type, member, func) \
138 {name, doc, type, offsetof(PyDisplay, _obj), offsetof(struct display, member), func}
139 static SPyClosure dclosures[] =
141 SPY_CLOSURE("tty", "Display TTY", T_STRING_INPLACE, d_usertty, NULL),
142 SPY_CLOSURE("term", "Display Term", T_STRING_INPLACE, d_termname, NULL),
143 SPY_CLOSURE("fore", "Foreground window of the display", T_OBJECT_EX, d_fore, PyObject_FromWindow),
144 SPY_CLOSURE("width", "Display width", T_INT, d_width, NULL),
145 SPY_CLOSURE("height", "Display height", T_INT, d_height, NULL),
146 {NULL}
148 REGISTER_TYPE(display, Display, dclosures)
149 #undef SPY_CLOSURE
150 /** }}} */
152 static PyObject *
153 SPy_Get(PyObject *obj, void *closure)
155 SPyClosure *sc = closure;
156 char **first = (char *)obj + sc->offset1;
157 char **second = (char *)*first + sc->offset2;
158 PyObject *(*cb)(void *) = sc->conv;
159 void *data = *second;
161 if (!cb)
163 switch (sc->type)
165 case T_STRING:
166 cb = PyString_FromStringSafe;
167 data = *second;
168 break;
169 case T_STRING_INPLACE:
170 cb = PyString_FromStringSafe;
171 data = second;
172 break;
173 case T_INT:
174 cb = PyInt_FromLong;
175 data = *second;
176 break;
179 return cb(data);
182 static PyObject *
183 SPy_Set(PyObject *obj, PyObject *value, void *closure)
185 return NULL;
188 static int
189 PyDispatch(void *handler, const char *params, va_list va)
191 PyObject *callback = handler;
192 PyObject *args, *ret;
193 int count, retval;
194 char *p;
196 for (count = 0, p = params; *p; p++, count++)
198 if (count > 0)
199 args = PyTuple_New(count);
200 else
201 args = NULL;
203 for (count = 0, p = params; *p; p++, count++)
205 PyObject *item = NULL;
206 switch (*p)
208 case 's':
209 item = PyString_FromStringSafe(va_arg(va, char *));
210 break;
211 case 'S':
213 const char **ls = va_arg(va, char **), **iter;
214 int c = 0;
215 for (iter = ls; iter && *iter; iter++, c++)
217 if (c == 0)
218 break;
219 item = PyTuple_New(c);
220 for (c = 0, iter = ls; iter && *iter; iter++, c++)
221 PyTuple_SetItem(item, c, PyString_FromStringSafe(*iter));
223 break;
224 case 'i':
225 item = PyInt_FromLong(va_arg(va, int));
226 break;
227 case 'd':
228 item = PyObject_FromDisplay(va_arg(va, struct display *));
229 break;
232 if (!item)
234 item = Py_None;
235 Py_INCREF(Py_None);
237 PyTuple_SetItem(args, count, item);
240 ret = PyObject_CallObject(callback, args);
241 retval = (int)PyInt_AsLong(ret);
243 Py_DECREF(args);
244 Py_DECREF(ret);
245 return retval;
248 /** Screen {{{ */
249 static PyObject *
250 screen_display(PyObject *self)
252 if (!display)
254 Py_INCREF(Py_None);
255 return Py_None;
257 return PyObject_FromDisplay(display);
260 static PyObject *
261 screen_displays(PyObject *self)
263 struct display *d = displays;
264 int count = 0;
265 for (; d; d = d->d_next)
266 ++count;
267 PyObject *tuple = PyTuple_New(count);
269 for (d = displays, count = 0; d; d = d->d_next, ++count)
270 PyTuple_SetItem(tuple, count, PyObject_FromDisplay(d));
272 return tuple;
275 static PyObject *
276 screen_windows(PyObject *self)
278 struct win *w = windows;
279 int count = 0;
280 for (; w; w = w->w_next)
281 ++count;
282 PyObject *tuple = PyTuple_New(count);
284 for (w = windows, count = 0; w; w = w->w_next, ++count)
285 PyTuple_SetItem(tuple, count, PyObject_FromWindow(w));
287 return tuple;
290 static PyObject *
291 hook_event(PyObject *self, PyObject *args, PyObject *kw)
293 static char *kwlist[] = {"event", "callback", NULL};
294 PyObject *callback;
295 char *name;
297 struct script_event *sev;
298 struct listener *l;
300 if (!PyArg_ParseTuple(args, "sO:screen.hook", &name, &callback))
301 return NULL; /* Return Py_None instead? */
303 if (!PyCallable_Check(callback))
305 PyErr_SetString(PyExc_TypeError, "The event-callback functions must be callable.");
306 LMsg(0, "The event-callback functions must be callable.");
307 return NULL;
310 sev = object_get_event(NULL, name);
311 if (!sev)
313 LMsg(0, "No event named '%s'", name);
314 return NULL;
317 l = malloc(sizeof(struct listener));
319 l->handler = callback;
320 l->priv = 0;
321 l->dispatcher = PyDispatch;
322 Py_INCREF(callback);
323 if (register_listener(sev, l))
325 Free(l);
326 Py_DECREF(callback);
327 LMsg(0, "Hook could not be registered.");
329 Py_INCREF(Py_None);
330 return Py_None;
333 Py_INCREF(callback);
334 return callback;
337 const PyMethodDef py_methods[] = {
338 {"display", (PyCFunction)screen_display, METH_NOARGS, "Get the current display."},
339 {"displays", (PyCFunction)screen_displays, METH_NOARGS, "Get the list of displays."},
340 {"hook", (PyCFunction)hook_event, METH_VARARGS|METH_KEYWORDS, "Hook a callback to an event."},
341 {"windows", (PyCFunction)screen_windows, METH_NOARGS, "Get the list of windows."},
342 {NULL, NULL, 0, NULL}
345 /** }}} */
347 static int
348 SPyInit(void)
350 PyObject *m;
352 Py_Initialize();
354 m = Py_InitModule3 ("screen", py_methods, NULL);
355 register_window(m);
356 register_display(m);
358 return 0;
361 static int
362 SPyFinit(void)
364 Py_Finalize();
365 return 0;
368 static int
369 SPySource(const char *file, int async)
371 FILE *f = fopen(file, "rb");
372 int ret = PyRun_SimpleFile(f, file);
373 fclose(f);
375 if (ret == 0)
376 return 1; /* Success */
378 if (PyErr_Occurred())
380 PyErr_Print();
381 return 0;
384 return 1;
387 struct binding py_binding =
389 "python",
392 SPyInit,
393 SPyFinit,
395 SPySource,