795f80f42affdc5f14094aee1afbb8d8bd42416d
[screen-lua.git] / src / python.c
blob795f80f42affdc5f14094aee1afbb8d8bd42416d
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;
42 extern struct layer *flayer;
44 static PyObject * SPy_Get(PyObject *obj, void *closure);
45 static PyObject * SPy_Set(PyObject *obj, PyObject *value, void *closure);
46 static int PyDispatch(void *handler, const char *params, va_list va);
48 typedef struct
50 PyObject *callback;
51 struct listener *listener;
52 } SPyCallback;
54 typedef struct
56 char *name;
57 char *doc;
59 int type;
60 size_t offset1;
61 size_t offset2;
62 PyObject * (*conv)(void *);
63 } SPyClosure;
65 #define REGISTER_TYPE(type, Type, closures, methods) \
66 static int \
67 register_##type(PyObject *module) \
68 { \
69 static PyGetSetDef getsets[sizeof(closures)]; \
70 int i, count = sizeof(closures); \
71 for (i = 0; i < count; i++) \
72 { \
73 getsets[i].name = closures[i].name; \
74 getsets[i].doc = closures[i].doc; \
75 getsets[i].closure = &closures[i]; \
76 getsets[i].get = SPy_Get; \
77 getsets[i].set = SPy_Set; \
78 } \
79 PyType##Type.tp_getset = getsets; \
80 PyType##Type.tp_methods = methods; \
81 PyType_Ready(&PyType##Type); \
82 Py_INCREF(&PyType##Type); \
83 PyModule_AddObject(module, #Type, (PyObject *)&PyType##Type); \
84 return 1; \
87 #define DEFINE_TYPE(str, Type) \
88 typedef struct \
89 { \
90 PyObject_HEAD \
91 str *_obj; \
92 } Py##Type; \
94 static PyTypeObject PyType##Type = \
95 { \
96 PyObject_HEAD_INIT(NULL) \
97 .ob_size = 0, \
98 .tp_name = "screen." #Type, \
99 .tp_basicsize = sizeof(Py##Type), \
100 .tp_flags = Py_TPFLAGS_DEFAULT, \
101 .tp_doc = #Type " object", \
102 .tp_methods = NULL, \
103 .tp_getset = NULL, \
104 }; \
106 static PyObject * \
107 PyObject_From##Type(str *_obj) \
109 Py##Type *obj = PyType##Type.tp_alloc(&PyType##Type, 0); \
110 obj->_obj = _obj; \
111 return (PyObject *)obj; \
114 static PyObject *
115 PyString_FromStringSafe(const char *str)
117 if (str)
118 return PyString_FromString(str);
119 Py_INCREF(Py_None);
120 return Py_None;
123 /** Window {{{ */
124 DEFINE_TYPE(struct win, Window)
126 #define SPY_CLOSURE(name, doc, type, member, func) \
127 {name, doc, type, offsetof(PyWindow, _obj), offsetof(struct win, member), func}
128 static SPyClosure wclosures[] =
130 SPY_CLOSURE("title", "Window title", T_STRING, w_title, NULL),
131 SPY_CLOSURE("number", "Window number", T_INT, w_number, NULL),
132 SPY_CLOSURE("dir", "Window directory", T_STRING, w_dir, NULL),
133 SPY_CLOSURE("tty", "TTY belonging to the window", T_STRING_INPLACE, w_tty, NULL),
134 SPY_CLOSURE("group", "The group the window belongs to", T_OBJECT_EX, w_group, PyObject_FromWindow),
135 SPY_CLOSURE("pid", "Window pid", T_INT, w_pid, NULL),
136 {NULL}
138 REGISTER_TYPE(window, Window, wclosures, NULL)
139 #undef SPY_CLOSURE
140 /** }}} */
142 /** Display {{{ */
143 DEFINE_TYPE(struct display, Display)
145 #define SPY_CLOSURE(name, doc, type, member, func) \
146 {name, doc, type, offsetof(PyDisplay, _obj), offsetof(struct display, member), func}
147 static SPyClosure dclosures[] =
149 SPY_CLOSURE("tty", "Display TTY", T_STRING_INPLACE, d_usertty, NULL),
150 SPY_CLOSURE("term", "Display Term", T_STRING_INPLACE, d_termname, NULL),
151 SPY_CLOSURE("fore", "Foreground window of the display", T_OBJECT_EX, d_fore, PyObject_FromWindow),
152 SPY_CLOSURE("width", "Display width", T_INT, d_width, NULL),
153 SPY_CLOSURE("height", "Display height", T_INT, d_height, NULL),
154 {NULL}
156 REGISTER_TYPE(display, Display, dclosures, NULL)
157 #undef SPY_CLOSURE
158 /** }}} */
160 /** Callback {{{ */
161 DEFINE_TYPE(SPyCallback, Callback)
162 static SPyClosure cclosures[] = {{NULL}};
164 static void
165 FreeCallback(SPyCallback *scallback)
167 Py_XDECREF(scallback->callback);
168 Free(scallback);
171 static PyObject *
172 callback_unhook(PyObject *obj)
174 PyCallback *cb = obj;
175 SPyCallback *scallback = cb->_obj;
176 if (!scallback)
177 return NULL;
178 unregister_listener(scallback->listener);
179 FreeCallback(scallback);
180 cb->_obj = NULL;
181 Py_INCREF(Py_None);
182 return Py_None;
185 static PyMethodDef cmethods[] ={
186 {"unhook", (PyCFunction)callback_unhook, METH_NOARGS, "Unhook this event callback."},
187 {NULL}
189 REGISTER_TYPE(callback, Callback, cclosures, cmethods)
190 /** }}} */
192 static PyObject *
193 SPy_Get(PyObject *obj, void *closure)
195 SPyClosure *sc = closure;
196 char **first = (char *)obj + sc->offset1;
197 char **second = (char *)*first + sc->offset2;
198 PyObject *(*cb)(void *) = sc->conv;
199 void *data = *second;
201 if (!cb)
203 switch (sc->type)
205 case T_STRING:
206 cb = PyString_FromStringSafe;
207 data = *second;
208 break;
209 case T_STRING_INPLACE:
210 cb = PyString_FromStringSafe;
211 data = second;
212 break;
213 case T_INT:
214 cb = PyInt_FromLong;
215 data = *second;
216 break;
219 return cb(data);
222 static PyObject *
223 SPy_Set(PyObject *obj, PyObject *value, void *closure)
225 return NULL;
228 static int
229 PyDispatch(void *handler, const char *params, va_list va)
231 PyCallback *callback = handler;
232 PyObject *args, *ret;
233 int count, retval;
234 const char *p;
235 SPyCallback *scallback = callback->_obj;
237 for (count = 0, p = params; *p; p++, count++)
239 if (count > 0)
240 args = PyTuple_New(count);
241 else
242 args = NULL;
244 for (count = 0, p = params; *p; p++, count++)
246 PyObject *item = NULL;
247 switch (*p)
249 case 's':
250 item = PyString_FromStringSafe(va_arg(va, char *));
251 break;
252 case 'S':
254 char **ls = va_arg(va, char **), **iter;
255 int c = 0;
256 for (iter = ls; iter && *iter; iter++, c++)
258 if (c == 0)
259 break;
260 item = PyTuple_New(c);
261 for (c = 0, iter = ls; iter && *iter; iter++, c++)
262 PyTuple_SetItem(item, c, PyString_FromStringSafe(*iter));
264 break;
265 case 'i':
266 item = PyInt_FromLong(va_arg(va, int));
267 break;
268 case 'd':
269 item = PyObject_FromDisplay(va_arg(va, struct display *));
270 break;
273 if (!item)
275 item = Py_None;
276 Py_INCREF(Py_None);
278 PyTuple_SetItem(args, count, item);
281 ret = PyObject_CallObject(scallback->callback, args);
282 Py_DECREF(args);
283 if (!ret)
284 return 0;
286 retval = (int)PyInt_AsLong(ret);
287 Py_DECREF(ret);
288 return retval;
291 /** Screen {{{ */
292 static PyObject *
293 screen_display(PyObject *self)
295 if (!display)
297 Py_INCREF(Py_None);
298 return Py_None;
300 return PyObject_FromDisplay(display);
303 static PyObject *
304 screen_displays(PyObject *self)
306 struct display *d = displays;
307 int count = 0;
308 for (; d; d = d->d_next)
309 ++count;
310 PyObject *tuple = PyTuple_New(count);
312 for (d = displays, count = 0; d; d = d->d_next, ++count)
313 PyTuple_SetItem(tuple, count, PyObject_FromDisplay(d));
315 return tuple;
318 static PyObject *
319 screen_windows(PyObject *self)
321 struct win *w = windows;
322 int count = 0;
323 for (; w; w = w->w_next)
324 ++count;
325 PyObject *tuple = PyTuple_New(count);
327 for (w = windows, count = 0; w; w = w->w_next, ++count)
328 PyTuple_SetItem(tuple, count, PyObject_FromWindow(w));
330 return tuple;
333 static PyObject *
334 hook_event(PyObject *self, PyObject *args, PyObject *kw)
336 static char *kwlist[] = {"event", "callback", NULL};
337 PyObject *callback;
338 char *name;
340 struct script_event *sev;
341 struct listener *l;
342 SPyCallback *scallback;
344 if (!PyArg_ParseTupleAndKeywords(args, kw, "sO:screen.hook", kwlist, &name, &callback))
345 return NULL; /* Return Py_None instead? */
347 if (!PyCallable_Check(callback))
349 PyErr_SetString(PyExc_TypeError, "The event-callback functions must be callable.");
350 LMsg(0, "The event-callback functions must be callable.");
351 return NULL;
354 sev = object_get_event(NULL, name);
355 if (!sev)
357 LMsg(0, "No event named '%s'", name);
358 return NULL;
361 l = malloc(sizeof(struct listener));
363 scallback = malloc(sizeof(SPyCallback));
364 scallback->callback = callback;
365 scallback->listener = l;
366 Py_INCREF(scallback->callback);
368 l->handler = PyObject_FromCallback(scallback);
369 l->priv = 0;
370 l->dispatcher = PyDispatch;
371 if (register_listener(sev, l))
373 Py_DECREF((PyObject *)l->handler);
374 FreeCallback(scallback);
375 Free(l);
377 LMsg(0, "Hook could not be registered.");
379 Py_INCREF(Py_None);
380 return Py_None;
383 Py_INCREF((PyObject *)l->handler);
384 return l->handler;
387 static void
388 screen_input_cb(char *buf, int len, char *p)
390 PyObject *callback = p;
391 PyObject *str = PyTuple_New(1);
392 PyTuple_SetItem(str, 0, PyString_FromStringSafe(buf));
393 PyObject_CallObject(callback, str);
394 Py_DECREF(str);
395 Py_DECREF(callback);
398 static PyObject *
399 screen_input(PyObject *self, PyObject *args, PyObject *kw)
401 static char *kwlist[] = {"prompt", "callback", "value (optional)", NULL};
402 char *prompt, *pre = NULL;
403 PyObject *callback;
405 if (!PyArg_ParseTupleAndKeywords(args, kw, "sO|s:screen.input", kwlist, &prompt, &callback, &pre))
407 LMsg(0, "Could not parse all the parameters to screen.input call.");
408 return NULL;
411 if (!PyCallable_Check(callback))
413 LMsg(0, "Input callback must be a callable object.");
414 return NULL;
417 Py_INCREF(callback);
418 Input(prompt, 100 /* huh? */,
419 INP_COOKED, screen_input_cb, callback, 0);
421 if (pre && *pre)
423 int len = strlen(pre);
424 LayProcess(&pre, &len);
427 Py_INCREF(Py_None);
428 return Py_None;
431 const PyMethodDef py_methods[] = {
432 {"display", (PyCFunction)screen_display, METH_NOARGS, "Get the current display."},
433 {"displays", (PyCFunction)screen_displays, METH_NOARGS, "Get the list of displays."},
434 {"hook", (PyCFunction)hook_event, METH_VARARGS|METH_KEYWORDS, "Hook a callback to an event."},
435 {"input", (PyCFunction)screen_input, METH_VARARGS|METH_KEYWORDS, "Read user input interactively."},
436 {"windows", (PyCFunction)screen_windows, METH_NOARGS, "Get the list of windows."},
437 {NULL, NULL, 0, NULL}
439 /** }}} */
441 static int
442 SPyInit(void)
444 PyObject *m;
446 Py_Initialize();
448 m = Py_InitModule3 ("screen", py_methods, NULL);
449 register_window(m);
450 register_display(m);
451 register_callback(m);
453 return 0;
456 static int
457 SPyFinit(void)
459 Py_Finalize();
460 return 0;
463 static int
464 SPySource(const char *file, int async)
466 FILE *f = fopen(file, "rb");
467 int ret = PyRun_SimpleFile(f, file);
468 fclose(f);
470 if (ret == 0)
471 return 1; /* Success */
473 if (PyErr_Occurred())
475 PyErr_Print();
476 return 0;
479 return 1;
482 struct binding py_binding =
484 "python",
487 SPyInit,
488 SPyFinit,
490 SPySource,