Show
Ignore:
Timestamp:
06/05/07 19:14:45 (2 years ago)
Author:
dsmith
Message:

wminput plugin refactoring

Files:

Legend:

Unmodified
Added
Removed
Modified
Copied
Moved
  • branches/dev/wminput/Makefile.in

    r120 r124  
    55APP_NAME = wminput 
    66 
    7 SOURCES = main.c conf.c pyplugin.c uinput.c action_enum.c parser.c lexer.c util.c 
     7SOURCES = main.c conf.c c_plugin.c py_plugin.c uinput.c action_enum.c parser.c \ 
     8        lexer.c util.c 
    89 
    910WMINPUT_CONFIG_DIR = $(CWIID_CONFIG_DIR)/wminput 
  • branches/dev/wminput/conf.c

    r121 r124  
    1616 * 
    1717 *  ChangeLog: 
     18 *  2007-06-05 L. Donnie Smith <cwiid@abstrakraft.org> 
     19 *  * refactored to isolate plugin logic 
     20 * 
    1821 *  2007-06-03 L. Donnie Smith <cwiid@abstrakraft.org> 
    1922 *  * fixed plugin->data malloc bug 
     
    3538 */ 
    3639 
    37 #include "Python.h" 
    38  
    3940#include <stdint.h> 
    4041#include <stdio.h> 
     
    4243#include <string.h> 
    4344 
    44 #include <sys/types.h> 
    45 #include <sys/stat.h> 
    46 #include <dlfcn.h> 
    47 #include <unistd.h> 
    48  
    4945#include "conf.h" 
    5046#include "util.h" 
    5147#include "y.tab.h" 
    52 #include "pyplugin.h" 
     48#include "c_plugin.h" 
     49#include "py_plugin.h" 
    5350 
    5451extern FILE *yyin; 
     
    9794                        switch (conf->plugins[i].type) { 
    9895                        case PLUGIN_C: 
    99                                 dlclose(conf->plugins[i].handle); 
     96                                c_plugin_close(&conf->plugins[i]); 
    10097                                break; 
    10198                        case PLUGIN_PYTHON: 
    102                                 free(conf->plugins[i].info); 
    103                                 free(conf->plugins[i].data); 
    104                                 Py_DECREF((PyObject *)conf->plugins[i].PyInfo); 
    105                                 Py_DECREF((PyObject *)conf->plugins[i].init); 
    106                                 Py_DECREF((PyObject *)conf->plugins[i].exec); 
    107                                 Py_DECREF((PyObject *)conf->plugins[i].handle); 
     99                                py_plugin_close(&conf->plugins[i]); 
    108100                                break; 
    109101                        } 
    110                 } 
    111                 else { 
    112                         break; 
    113102                } 
    114103        } 
     
    331320        int i; 
    332321        unsigned char param_found = 0; 
    333         PyObject *PyObj; 
    334322 
    335323        if ((plugin = get_plugin(conf, name)) == NULL) { 
     
    351339        switch (plugin->type) { 
    352340        case PLUGIN_C: 
    353                 switch (plugin->info->param_info[i].type) { 
    354                 case WMPLUGIN_PARAM_INT: 
    355                         *(int *)plugin->info->param_info[i].ptr = value; 
    356                         break; 
    357                 case WMPLUGIN_PARAM_FLOAT: 
    358                         *(float *)plugin->info->param_info[i].ptr = value; 
    359                         break; 
    360                 default: 
    361                         wminput_err("unknown parameter type: %s.%s", name, param); 
     341                if (c_plugin_param_int(plugin, i, value)) { 
    362342                        return -1; 
    363                        break; 
    364                 } 
     343                } 
     344                break; 
    365345        case PLUGIN_PYTHON: 
    366                 switch (plugin->info->param_info[i].type) { 
    367                 case WMPLUGIN_PARAM_INT: 
    368                         PyObj = PyInt_FromLong(value); 
    369                         if (PyObject_SetAttrString(plugin->handle, 
    370                                                    plugin->info->param_info[i].name, 
    371                                                    PyObj)) { 
    372                                 PyErr_Print(); 
    373                                 return -1; 
    374                         } 
    375                         break; 
    376                 case WMPLUGIN_PARAM_FLOAT: 
    377                         PyObj = PyFloat_FromDouble((double)value); 
    378                         if (PyObject_SetAttrString(plugin->handle, 
    379                                                    plugin->info->param_info[i].name, 
    380                                                    PyObj)) { 
    381                                 PyErr_Print(); 
    382                                 return -1; 
    383                         } 
    384                         break; 
    385                 default: 
    386                         wminput_err("unknown parameter type: %s.%s", name, param); 
     346                if (py_plugin_param_int(plugin, i, value)) { 
    387347                        return -1; 
    388                        break; 
    389                 } 
     348                } 
     349                break; 
    390350        } 
    391351 
     
    399359        int i; 
    400360        unsigned char param_found = 0; 
    401         PyObject *PyObj; 
    402361 
    403362        if ((plugin = get_plugin(conf, name)) == NULL) { 
     
    419378        switch (plugin->type) { 
    420379        case PLUGIN_C: 
    421                 switch (plugin->info->param_info[i].type) { 
    422                 case WMPLUGIN_PARAM_INT: 
    423                         wminput_err("possible loss of precision: %s.%s " 
    424                                     "(cast float to int)", name, param); 
    425                         *(int *)plugin->info->param_info[i].ptr = value; 
    426                         break; 
    427                 case WMPLUGIN_PARAM_FLOAT: 
    428                         *(float *)plugin->info->param_info[i].ptr = value; 
    429                         break; 
    430                 default: 
    431                         wminput_err("unknown parameter type: %s.%s", name, param); 
     380                if (c_plugin_param_float(plugin, i, value)) { 
    432381                        return -1; 
    433                        break; 
    434                 } 
     382                } 
     383                break; 
    435384        case PLUGIN_PYTHON: 
    436                 switch (plugin->info->param_info[i].type) { 
    437                 case WMPLUGIN_PARAM_INT: 
    438                         wminput_err("possible loss of precision: %s.%s " 
    439                                     "(cast float to int)", name, param); 
    440                         PyObj = PyInt_FromLong((int)value); 
    441                         if (PyObject_SetAttrString(plugin->handle, 
    442                                                    plugin->info->param_info[i].name, 
    443                                                    PyObj)) { 
    444                                 PyErr_Print(); 
    445                                 return -1; 
    446                         } 
    447                         break; 
    448                 case WMPLUGIN_PARAM_FLOAT: 
    449                         PyObj = PyFloat_FromDouble((double)value); 
    450                         if (PyObject_SetAttrString(plugin->handle, 
    451                                                    plugin->info->param_info[i].name, 
    452                                                    PyObj)) { 
    453                                 PyErr_Print(); 
    454                                 return -1; 
    455                         } 
    456                         break; 
    457                 default: 
    458                         wminput_err("unknown parameter type: %s.%s", name, param); 
     385                if (py_plugin_param_float(plugin, i, value)) { 
    459386                        return -1; 
    460                        break; 
    461                 } 
     387                } 
     388                break; 
    462389        } 
    463390 
     
    536463        for (i=0; i < CONF_MAX_PLUGINS; i++) { 
    537464                conf->plugins[i].name = NULL; 
    538                 conf->plugins[i].PyInfo = NULL; 
    539465                conf->plugins[i].rpt_mode_flags = 0; 
    540466                conf->plugins[i].prev_buttons = 0; 
     
    639565} 
    640566 
    641 #define PLUGIN_PATHNAME_LEN     128 
    642567struct plugin *get_plugin(struct conf *conf, const char *name) 
    643568{ 
    644569        int i; 
    645         char pathname[PLUGIN_PATHNAME_LEN]
     570        char plugin_found = 0
    646571        struct plugin *plugin; 
    647         struct stat buf; 
    648         void *info; 
    649  
    650         /* TODO: replace PyErr_Print with wminput_err */ 
     572 
    651573        for (i=0; i < CONF_MAX_PLUGINS; i++) { 
    652574                if (!conf->plugins[i].name) { 
     
    662584                return NULL; 
    663585        } 
    664         else { 
    665                 plugin = &conf->plugins[i]; 
    666                 plugin->name = (char *)name; 
    667  
    668                 for (i=0; conf->plugin_search_dirs[i]; i++) { 
    669                         snprintf(pathname, PLUGIN_PATHNAME_LEN, "%s/%s.so", 
    670                                  conf->plugin_search_dirs[i], name); 
    671                         if (!stat(pathname, &buf)) { 
    672                                 if (!(plugin->handle = dlopen(pathname, RTLD_NOW))) { 
    673                                         wminput_err(dlerror()); 
    674                                 } 
    675                                 else { 
    676                                         plugin->type = PLUGIN_C; 
    677                                 } 
    678                                 break; 
    679                         } 
    680                         if (!chdir(conf->plugin_search_dirs[i])) { 
    681                                 if ((plugin->handle = PyImport_ImportModule((char *)name))) { 
    682                                         plugin->type = PLUGIN_PYTHON; 
    683                                         break; 
    684                                 } 
    685                                 else { 
    686                                         /* TODO: print only syntax errors, not "module not found errors" */ 
    687                                         PyErr_Print(); 
    688                                 } 
    689                                 /* TODO: restore directory */ 
    690                         } 
    691                 } 
    692  
    693                 if (!plugin->handle) { 
    694                         wminput_err("plugin not found: %s", name); 
    695                         free(plugin->name); 
    696                         plugin->name = NULL; 
    697                         return NULL; 
    698                 } 
    699  
    700                 switch (plugin->type) { 
    701                 case PLUGIN_C: 
    702                         if (!(info = dlsym(plugin->handle, "wmplugin_info"))) { 
    703                                 wminput_err("Unable to load plugin info function: %s", 
    704                                             dlerror()); 
    705                                 free(plugin->name); 
    706                                 plugin->name = NULL; 
    707                                 dlclose(plugin->handle); 
    708                                 return NULL; 
    709                         } 
    710                         if (!(plugin->info = (*(wmplugin_info_t *)info)())) { 
    711                                 wminput_err("Invalid plugin info from %s", plugin->name); 
    712                                 free(plugin->name); 
    713                                 plugin->name = NULL; 
    714                                 dlclose(plugin->handle); 
    715                                 return NULL; 
    716                         } 
    717                         if (!(plugin->init = dlsym(plugin->handle, "wmplugin_init"))) { 
    718                                 wminput_err("Unable to load plugin init function: %s", 
    719                                             dlerror()); 
    720                                 free(plugin->name); 
    721                                 plugin->name = NULL; 
    722                                 dlclose(plugin->handle); 
    723                                 return NULL; 
    724                         } 
    725                         if (!(plugin->exec = dlsym(plugin->handle, "wmplugin_exec"))) { 
    726                                 wminput_err("Unable to load plugin exec function: %s", 
    727                                             dlerror()); 
    728                                 free(plugin->name); 
    729                                 plugin->name = NULL; 
    730                                 dlclose(plugin->handle); 
    731                                 return NULL; 
    732                         } 
     586 
     587        plugin = &conf->plugins[i]; 
     588        plugin->name = (char *)name; 
     589 
     590        for (i=0; conf->plugin_search_dirs[i]; i++) { 
     591                if (!c_plugin_open(plugin, conf->plugin_search_dirs[i])) { 
     592                        plugin_found = 1; 
    733593                        break; 
    734                 case PLUGIN_PYTHON: 
    735                         if (!(info = PyObject_GetAttrString(plugin->handle, 
    736                                                             "wmplugin_info"))) { 
    737                                 PyErr_Print(); 
    738                                 Py_DECREF((PyObject *)plugin->handle); 
    739                                 free(plugin->name); 
    740                                 plugin->name = NULL; 
    741                                 return NULL; 
    742                         } 
    743                         if (!PyCallable_Check(info)) { 
    744                                 wminput_err("Unable to load plugin info function: " 
    745                                             "not callable"); 
    746                                 Py_DECREF((PyObject *)info); 
    747                                 Py_DECREF((PyObject *)plugin->handle); 
    748                                 free(plugin->name); 
    749                                 plugin->name = NULL; 
    750                                 return NULL; 
    751                         } 
    752                         if (!(plugin->init = PyObject_GetAttrString(plugin->handle, 
    753                                                                     "wmplugin_init"))) { 
    754                                 PyErr_Print(); 
    755                                 Py_DECREF((PyObject *)info); 
    756                                 Py_DECREF((PyObject *)plugin->handle); 
    757                                 free(plugin->name); 
    758                                 plugin->name = NULL; 
    759                                 return NULL; 
    760                         } 
    761                         if (!PyCallable_Check(plugin->init)) { 
    762                                 wminput_err("Unable to load plugin init function: " 
    763                                             "not callable"); 
    764                                 Py_DECREF((PyObject *)info); 
    765                                 Py_DECREF((PyObject *)plugin->init); 
    766                                 Py_DECREF((PyObject *)plugin->handle); 
    767                                 free(plugin->name); 
    768                                 plugin->name = NULL; 
    769                                 return NULL; 
    770                         } 
    771                         if (!(plugin->exec = PyObject_GetAttrString(plugin->handle, 
    772                                                                     "wmplugin_exec"))) { 
    773                                 PyErr_Print(); 
    774                                 Py_DECREF((PyObject *)info); 
    775                                 Py_DECREF((PyObject *)plugin->init); 
    776                                 Py_DECREF((PyObject *)plugin->handle); 
    777                                 free(plugin->name); 
    778                                 plugin->name = NULL; 
    779                                 return NULL; 
    780                         } 
    781                         if (!PyCallable_Check(plugin->exec)) { 
    782                                 wminput_err("Unable to load plugin exec function: " 
    783                                             "not callable"); 
    784                                 Py_DECREF((PyObject *)info); 
    785                                 Py_DECREF((PyObject *)plugin->init); 
    786                                 Py_DECREF((PyObject *)plugin->exec); 
    787                                 Py_DECREF((PyObject *)plugin->handle); 
    788                                 free(plugin->name); 
    789                                 plugin->name = NULL; 
    790                                 return NULL; 
    791                         } 
    792                         if (python_info(info, plugin)) { 
    793                                 wminput_err("python_info error"); 
    794                                 Py_DECREF((PyObject *)info); 
    795                                 Py_DECREF((PyObject *)plugin->init); 
    796                                 Py_DECREF((PyObject *)plugin->exec); 
    797                                 Py_DECREF((PyObject *)plugin->handle); 
    798                                 free(plugin->name); 
    799                                 plugin->name = NULL; 
    800                                 return NULL; 
    801                         } 
    802                         if (!(plugin->data = malloc(sizeof *plugin->data))) { 
    803                                 wminput_err("malloc error"); 
    804                                 Py_DECREF((PyObject *)info); 
    805                                 Py_DECREF((PyObject *)plugin->init); 
    806                                 Py_DECREF((PyObject *)plugin->exec); 
    807                                 Py_DECREF((PyObject *)plugin->handle); 
    808                                 free(plugin->name); 
    809                                 plugin->name = NULL; 
    810                                 return NULL; 
    811                         } 
    812                         Py_DECREF((PyObject *)info); 
     594                } 
     595                if (!py_plugin_open(plugin, conf->plugin_search_dirs[i])) { 
     596                        plugin_found = 1; 
    813597                        break; 
    814598                } 
    815599        } 
    816600 
     601        if (!plugin_found) { 
     602                wminput_err("plugin not found: %s", name); 
     603                free(plugin->name); 
     604                plugin->name = NULL; 
     605                return NULL; 
     606        } 
     607 
    817608        return plugin; 
    818609} 
  • branches/dev/wminput/conf.h

    r118 r124  
    1616 * 
    1717 *  ChangeLog: 
     18 *  2007-06-05 L. Donnie Smith <cwiid@abstrakraft.org> 
     19 *  * refactored to isolate plugin logic 
     20 * 
    1821 *  2007-06-01 L. Donnie Smith <cwiid@abstrakraft.org> 
    1922 *  * added python plugin support 
     
    143146struct plugin { 
    144147        char *name; 
     148        enum plugin_type type; 
     149        uint8_t rpt_mode_flags; 
    145150        struct wmplugin_info *info; 
    146151        struct wmplugin_data *data; 
    147         void *PyInfo; 
    148         enum plugin_type type; 
    149         void *handle; 
    150         void *init; 
    151         void *exec; 
    152         uint8_t rpt_mode_flags; 
    153152        uint16_t prev_buttons; 
    154153        struct btn_map bmap[WMPLUGIN_MAX_BUTTON_COUNT]; 
    155154        struct axis_map amap[WMPLUGIN_MAX_AXIS_COUNT]; 
     155        void *p; 
    156156}; 
    157157 
  • branches/dev/wminput/main.c

    r120 r124  
    1616 * 
    1717 *  ChangeLog: 
     18 *  2007-06-05 L. Donnie Smith <cwiid@abstrakraft.org> 
     19 *  * refactored to isolate plugin logic 
     20 * 
    1821 *  2007-06-01 Nick <nickishappy@gmail.com> 
    1922 *  * reworked command-line options (added standard options, long options) 
     
    4447 */ 
    4548 
    46 #include "Python.h" 
    47  
    4849#include <stdint.h> 
    4950#include <stdio.h> 
     
    6162#include "util.h" 
    6263#include "wmplugin.h" 
    63 #include "pyplugin.h" 
     64#include "c_plugin.h" 
     65#include "py_plugin.h" 
    6466 
    6567struct conf conf; 
     
    7577/* Globals */ 
    7678cwiid_wiimote_t *wiimote; 
    77 PyObject *PyCWiidModule; 
    78 PyObject *PyWiimote; 
    79 static PyObject *(*ConvertMesgArray)(int, union cwiid_mesg[]); 
    8079char init; 
    8180 
     
    110109        struct uinput_listen_data uinput_listen_data; 
    111110        pthread_t uinput_listen_thread; 
    112         PyObject *PyCObj; 
    113         PyObject *(*Wiimote_FromC)(cwiid_wiimote_t *); 
    114111 
    115112        init = 1; 
     
    158155        } 
    159156 
    160         /* Python Init */ 
    161         /* TODO: DECREF global objects and finalize on error and exit */ 
    162         Py_Initialize(); 
    163         if (initwmplugin()) { 
    164                 return -1; 
    165         } 
    166         PyRun_SimpleString("import sys; sys.path.append('.')"); 
    167         if (!(PyCWiidModule = PyImport_ImportModule("cwiid"))) { 
    168                 PyErr_Print(); 
    169                 return -1; 
    170         } 
    171  
    172         if (!(PyCObj = PyObject_GetAttrString(PyCWiidModule, "Wiimote_FromC"))) { 
    173                 PyErr_Print(); 
    174                 return -1; 
    175         } 
    176         Wiimote_FromC = PyCObject_AsVoidPtr(PyCObj); 
    177  
    178         if (!(PyCObj = PyObject_GetAttrString(PyCWiidModule, 
    179                                               "ConvertMesgArray"))) { 
    180                 PyErr_Print(); 
    181                 return -1; 
    182         } 
    183         ConvertMesgArray = PyCObject_AsVoidPtr(PyCObj); 
     157        if (c_init()) { 
     158                return -1; 
     159        } 
     160        if (py_init()) { 
     161                return -1; 
     162        } 
    184163 
    185164        /* Load Config */ 
     165        /* Setup search directory arrays */ 
    186166        if ((tmp = getenv("HOME")) == NULL) { 
    187167                wminput_err("unable to find home directory"); 
     
    205185        } 
    206186 
    207         /* BDADDR */ 
     187        /* Determine BDADDR */ 
     188        /* priority: command-line option, environment variable, BDADDR_ANY */ 
    208189        if (optind < argc) { 
    209190                if (str2ba(argv[optind], &bdaddr)) { 
     
    229210        } 
    230211 
    231         /* Wiimote connect */ 
     212        /* TODO: fix wait_forever logic - currently assumes bdaddr is unspecified */ 
     213        /* Wiimote Connect */ 
    232214        printf("Put Wiimote in discoverable mode now (press 1+2)...\n"); 
    233215        if (wait_forever) { 
     
    249231        } 
    250232 
    251         if (!(PyWiimote = Wiimote_FromC(wiimote))) { 
    252                 PyErr_Print(); 
     233        if (c_wiimote(wiimote)) { 
     234                conf_unload(&conf); 
     235                return -1; 
     236        } 
     237        if (py_wiimote(wiimote)) { 
    253238                conf_unload(&conf); 
    254239                return -1; 
     
    259244                switch (conf.plugins[i].type) { 
    260245                case PLUGIN_C: 
    261                         if ((*(wmplugin_init_t *)conf.plugins[i].init)(i, wiimote)) { 
     246                        if (c_plugin_init(&conf.plugins[i], i)) { 
    262247                                wminput_err("error on %s init", conf.plugins[i].name); 
    263248                                conf_unload(&conf); 
     
    267252                        break; 
    268253                case PLUGIN_PYTHON: 
    269                         if (python_init(&conf.plugins[i], i, PyWiimote)) { 
     254                        if (py_plugin_init(&conf.plugins[i], i)) { 
    270255                                wminput_err("error %s init", conf.plugins[i].name); 
    271256                                conf_unload(&conf); 
     
    327312        } 
    328313 
     314        py_deinit(); 
     315 
    329316        return ret; 
     317} 
     318 
     319int wminput_set_report_mode() 
     320{ 
     321        unsigned char rpt_mode_flags; 
     322        int i; 
     323 
     324        rpt_mode_flags = conf.rpt_mode_flags; 
     325 
     326        for (i=0; (i < CONF_MAX_PLUGINS) && conf.plugins[i].name; i++) { 
     327                rpt_mode_flags |= conf.plugins[i].rpt_mode_flags; 
     328        } 
     329 
     330        if (cwiid_set_rpt_mode(wiimote, rpt_mode_flags)) { 
     331                wminput_err("error setting report mode"); 
     332                return -1; 
     333        } 
     334 
     335        return 0; 
    330336} 
    331337 
     
    336342        if (!init) { 
    337343                wminput_set_report_mode(); 
    338         } 
    339  
    340         return 0; 
    341 } 
    342  
    343 int wminput_set_report_mode() 
    344 { 
    345         unsigned char rpt_mode_flags; 
    346         int i; 
    347  
    348         rpt_mode_flags = conf.rpt_mode_flags; 
    349  
    350         for (i=0; (i < CONF_MAX_PLUGINS) && conf.plugins[i].name; i++) { 
    351                 rpt_mode_flags |= conf.plugins[i].rpt_mode_flags; 
    352         } 
    353  
    354         if (cwiid_set_rpt_mode(wiimote, rpt_mode_flags)) { 
    355                 wminput_err("error setting report mode"); 
    356                 return -1; 
    357344        } 
    358345 
     
    646633                switch (plugin->type) { 
    647634                case PLUGIN_C: 
    648                         if (!(plugin->data = 
    649                           (*(wmplugin_exec_t *)plugin->exec)(plugin_mesg_count, 
    650                                                              plugin_mesg))) { 
     635                        if (c_plugin_exec(plugin, plugin_mesg_count, plugin_mesg)) { 
    651636                                return; 
    652637                        } 
    653638                        break; 
    654639                case PLUGIN_PYTHON: 
    655                         if (python_exec(plugin, ConvertMesgArray, plugin_mesg_count, 
    656                                         plugin_mesg)) { 
     640                        if (py_plugin_exec(plugin, plugin_mesg_count, plugin_mesg)) { 
    657641                                return; 
    658642                        } 
  • branches/dev/wminput/py_plugin.c

    r121 r124  
    1616 * 
    1717 *  ChangeLog: 
     18 *  2007-06-05 L. Donnie Smith <cwiid@abstrakraft.org> 
     19 *  * relocated all python plugin logic here 
     20 *  * now imports plugins without changing directories 
     21 * 
    1822 *  2007-06-03 L. Donnie Smith <cwiid@abstrakraft.org> 
    1923 *  * added WMPLUGIN_ABS and WMPLUGIN_REL constants 
     
    2832#include <stdlib.h> 
    2933 
     34#include <unistd.h> 
     35 
    3036#include "structmember.h" 
    3137#include "cwiid.h" 
     
    3743/* TODO: print error messages */ 
    3844/* TODO: improve error checking */ 
    39 static PyObject *set_rpt_mode(PyObject *self, PyObject *args, PyObject *kwds) 
    40 
    41         static char *kwlist[] = {"id", "rpt_mode", NULL}; 
    42         int id, rpt_mode; 
    43  
    44         if (!PyArg_ParseTupleAndKeywords(args, kwds, "ii:wmplugin:set_rpt_mode", 
    45                                          kwlist, &id, &rpt_mode)) { 
    46                 return NULL; 
    47         } 
    48  
    49         if (wmplugin_set_rpt_mode(id, rpt_mode)) { 
    50                 return NULL; 
    51         } 
    52  
    53         Py_RETURN_NONE; 
    54 
    55  
    56 /* CWiid constants, enumerations */ 
     45 
     46struct py_plugin { 
     47        PyObject *PyInfo; 
     48        PyObject *handle; 
     49        PyObject *init; 
     50        PyObject *exec; 
     51}; 
     52 
     53static PyObject *PyCWiidModule = NULL; 
     54static PyObject *PySysModule = NULL; 
     55static PyObject *PyPath = NULL; 
     56static PyObject *PyWiimote = NULL; 
     57static PyObject *(*ConvertMesgArray)(int, union cwiid_mesg[]); 
     58 
     59static int py_plugin_info(struct plugin *, PyObject *); 
     60static PyObject *set_rpt_mode(PyObject *, PyObject *, PyObject *); 
     61 
    5762#define WMPLUGIN_CONST_MACRO(a) {#a, WMPLUGIN_##a} 
    5863static struct { 
     
    6772}; 
    6873 
    69 /* Associates cwiid functions with python ones */ 
    7074static PyMethodDef Module_Methods[] =  
    7175{ 
     
    7579}; 
    7680 
    77 int initwmplugin(void) 
    78 { 
    79         PyObject *Module; 
     81int py_init(void) 
     82{ 
     83        PyObject *PyObj, *PyWmPluginModule; 
    8084        int i; 
    8185 
    82         if (!(Module = Py_InitModule3("wmplugin", Module_Methods, 
    83           "plugin interface for wminput"))) { 
    84                 PyErr_Print(); 
    85                 return -1; 
     86        Py_Initialize(); 
     87 
     88        if (!(PyCWiidModule = PyImport_ImportModule("cwiid"))) { 
     89                PyErr_Print(); 
     90                goto ERR_HND; 
     91        } 
     92 
     93        if (!(PySysModule = PyImport_ImportModule("sys"))) { 
     94                PyErr_Print(); 
     95                goto ERR_HND; 
     96        } 
     97 
     98        if (!(PyPath = PyObject_GetAttrString(PySysModule, "path"))) { 
     99                PyErr_Print(); 
     100                goto ERR_HND; 
     101        } 
     102 
     103        if (!(PyObj = PyObject_GetAttrString(PyCWiidModule, 
     104                                              "ConvertMesgArray"))) { 
     105                PyErr_Print(); 
     106                goto ERR_HND; 
     107        } 
     108        ConvertMesgArray = PyCObject_AsVoidPtr(PyObj); 
     109        Py_DECREF(PyObj); 
     110 
     111        /* note: PyWmPluginModule is a borrowed reference - do not decref */ 
     112        if (!(PyWmPluginModule = Py_InitModule3("wmplugin", Module_Methods, 
     113                                               "plugin interface for wminput"))) { 
     114                PyErr_Print(); 
     115                goto ERR_HND; 
    86116        } 
    87117 
    88118        for (i = 0; wmplugin_constants[i].name; i++) { 
    89                 if (PyModule_AddIntConstant(Module, wmplugin_constants[i].name, 
     119                if (PyModule_AddIntConstant(PyWmPluginModule, 
     120                                            wmplugin_constants[i].name, 
    90121                                            wmplugin_constants[i].value)) { 
    91122                        PyErr_Print(); 
    92                         return -1; 
    93                 } 
    94         } 
    95  
    96         return 0; 
    97 
    98  
    99 int python_info(PyObject *Info, struct plugin *plugin) 
     123                        goto ERR_HND; 
     124                } 
     125        } 
     126 
     127        PyRun_SimpleString("import sys; sys.path.append('.')"); 
     128 
     129        return 0; 
     130 
     131ERR_HND: 
     132        if (PyCWiidModule) { 
     133                Py_DECREF(PyCWiidModule); 
     134                PyCWiidModule = NULL; 
     135        } 
     136 
     137        if (PyPath) { 
     138                Py_DECREF(PyPath); 
     139                PyPath = NULL; 
     140        } 
     141 
     142        if (PySysModule) { 
     143                Py_DECREF(PySysModule); 
     144                PySysModule = NULL; 
     145        } 
     146 
     147        Py_Finalize(); 
     148 
     149        return -1; 
     150
     151 
     152int py_wiimote(cwiid_wiimote_t *wiimote) 
     153
     154        PyObject *PyWiimoteType, *PyCObject, *PyArgs; 
     155 
     156        if (!(PyWiimoteType = PyObject_GetAttrString(PyCWiidModule, "Wiimote"))) { 
     157                PyErr_Print(); 
     158                return -1; 
     159        } 
     160 
     161        if (!(PyCObject = PyCObject_FromVoidPtr(wiimote, NULL))) { 
     162                PyErr_Print(); 
     163                Py_DECREF(PyWiimoteType); 
     164                return -1; 
     165        } 
     166 
     167        if (!(PyArgs = Py_BuildValue("(O)", PyCObject))) { 
     168                PyErr_Print(); 
     169                Py_DECREF(PyCObject); 
     170                Py_DECREF(PyWiimoteType); 
     171                return -1; 
     172        } 
     173 
     174        Py_DECREF(PyCObject); 
     175 
     176        if (!(PyWiimote = PyObject_CallObject(PyWiimoteType, PyArgs))) { 
     177                PyErr_Print(); 
     178                Py_DECREF(PyArgs); 
     179                Py_DECREF(PyWiimoteType); 
     180                return -1; 
     181        } 
     182 
     183        Py_DECREF(PyArgs); 
     184        Py_DECREF(PyWiimoteType); 
     185 
     186        return 0; 
     187
     188 
     189void py_deinit(void) 
     190
     191        Py_DECREF(PyWiimote); 
     192        Py_DECREF(PyCWiidModule); 
     193        Py_DECREF(PyPath); 
     194        Py_DECREF(PySysModule); 
     195        Py_Finalize(); 
     196
     197 
     198int py_plugin_open(struct plugin *plugin, char *dir) 
     199
     200        PyObject *handle, *info; 
     201        PyObject *PyStr; 
     202 
     203        if (!(PyStr = PyString_FromString(dir))) { 
     204                PyErr_Print(); 
     205                return -1; 
     206        } 
     207 
     208        if (PyList_Insert(PyPath, 0, PyStr)) { 
     209                Py_DECREF(PyStr); 
     210                return -1; 
     211        } 
     212 
     213        if (!(handle = PyImport_ImportModule(plugin->name))) { 
     214                /* TODO: print only syntax errors, not "module not found errors" */ 
     215                PyErr_Print(); 
     216                if (PySequence_DelItem(PyPath, 0)) { 
     217                        PyErr_Print(); 
     218                } 
     219                Py_DECREF(PyStr); 
     220                return -1; 
     221        } 
     222 
     223        if (PySequence_DelItem(PyPath, 0)) { 
     224                PyErr_Print(); 
     225        } 
     226        Py_DECREF(PyStr); 
     227 
     228        if (!(plugin->p = malloc(sizeof(struct py_plugin)))) { 
     229                wminput_err("malloc error"); 
     230                return -1; 
     231        } 
     232 
     233        plugin->type = PLUGIN_PYTHON; 
     234        plugin->info = NULL; 
     235        plugin->data = NULL; 
     236        ((struct py_plugin *) plugin->p)->init = NULL; 
     237        ((struct py_plugin *) plugin->p)->exec = NULL; 
     238 
     239        if (!(plugin->info = malloc(sizeof *plugin->info))) { 
     240                wminput_err("malloc error"); 
     241                goto ERR_HND; 
     242        } 
     243        if (!(plugin->data = malloc(sizeof *plugin->data))) { 
     244                wminput_err("malloc error"); 
     245                goto ERR_HND; 
     246        } 
     247        if (!(((struct py_plugin *)plugin->p)->init = 
     248          PyObject_GetAttrString(handle, "wmplugin_init"))) { 
     249                PyErr_Print(); 
     250                goto ERR_HND; 
     251        } 
     252        if (!PyCallable_Check(((struct py_plugin *)plugin->p)->init)) { 
     253                wminput_err("Unable to load plugin init function: not callable"); 
     254                goto ERR_HND; 
     255        } 
     256        if (!(((struct py_plugin *)plugin->p)->exec = 
     257          PyObject_GetAttrString(handle, "wmplugin_exec"))) { 
     258                PyErr_Print(); 
     259                goto ERR_HND; 
     260        } 
     261        if (!PyCallable_Check(((struct py_plugin *)plugin->p)->exec)) { 
     262                wminput_err("Unable to load plugin exec function: not callable"); 
     263                goto ERR_HND; 
     264        } 
     265        if (!(info = PyObject_GetAttrString(handle, "wmplugin_info"))) { 
     266                PyErr_Print(); 
     267                goto ERR_HND; 
     268        } 
     269        if (!PyCallable_Check(info)) { 
     270                wminput_err("Unable to load plugin info function: not callable"); 
     271                Py_DECREF((PyObject *)info); 
     272                goto ERR_HND; 
     273        } 
     274        if (py_plugin_info(plugin, info)) { 
     275                wminput_err("python_info error"); 
     276                Py_DECREF((PyObject *)info); 
     277                goto