#include <Python.h>
#include <time.h>
#include <stdio.h>
#include <stdlib.h>
#include <ctype.h>
#include <string.h>
#include <unistd.h>
#include <signal.h>
#include <time.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include "rtapi.h"
#include "hal.h"
#include "streamer.h"
int comp_id = -1;
int shmem_id = -1;
int exitval = 1;
int ignore_sig = 0;
char comp_name[HAL_NAME_LEN+1];
int dbg = 0;
int vdbg = 0;
int keydown = 0xC0;
int keyup = 0x80;
int nochange = 0x40;
int rowshift;
int ncols = 8;
int nrows = 8;
int rollover = 2; int s = 0; int r; int c; int num_keys; long int raw; long int keycode; long int start_time;
long int last_heartbeat;
long int heartbeat_difference;
struct timespec gettime_now;
PyObject *pExit,*pValue;
static sig_atomic_t stop;
static void quit(int sig)
{
if ( ignore_sig ) {
return;
}
stop = 1;
}
#define BUF_SIZE 4000
int main(int argc, char **argv)
{
int n, channel, tag;
long int samples;
unsigned this_sample, last_sample=0;
char *cp, *cp2;
hal_stream_t stream;
exitval = 1;
channel = 0;
tag = 0;
samples = -1;
for ( n = 1 ; n < argc ; n++ ) {
cp = argv[n];
if ( *cp != '-' ) {
break;
}
switch ( *(++cp) ) {
case 'c':
if (( *(++cp) == '\0' ) && ( ++n < argc )) {
cp = argv[n];
}
channel = strtol(cp, &cp2, 10);
if (( *cp2 ) || ( channel < 0 ) || ( channel >= MAX_SAMPLERS )) {
fprintf(stderr,"ERROR: invalid channel number '%s'\n", cp );
exit(1);
}
break;
case 'n':
if (( *(++cp) == '\0' ) && ( ++n < argc )) {
cp = argv[n];
}
samples = strtol(cp, &cp2, 10);
if (( *cp2 ) || ( samples < 0 )) {
fprintf(stderr, "ERROR: invalid sample count '%s'\n", cp );
exit(1);
}
break;
case 't':
tag = 1;
break;
case 'd':
dbg = 1;
break;
case 'v':
vdbg = 1;
break;
default:
fprintf(stderr,"ERROR: unknown option '%s'\n", cp );
exit(1);
break;
}
}
if(n < argc) {
int fd;
if(argc > n+1) {
fprintf(stderr, "ERROR: At most one filename may be specified\n");
exit(1);
}
fd = open(argv[n], O_WRONLY | O_CREAT, 0666);
close(1);
dup2(fd, 1);
}
PyObject *pModule, *pFunc, *pPeriodicFunc, *pClass;
Py_SetProgramName("panelui");
Py_Initialize();
PyRun_SimpleString("import pyui\n"
"pyui.instance = pyui.master.keyboard()\n"
"pyui.exit_funct = pyui.instance.exit\n"
"pyui.update_funct = pyui.master.keyboard.update\n"
"pyui.periodic_funct = pyui.master.keyboard.periodic\n");
if (vdbg == 1){
PyRun_SimpleString("pyui.intilize = pyui.instance.build(2)\n");
}else if (dbg == 1){
PyRun_SimpleString("pyui.intilize = pyui.instance.build(1)\n");
}else{
PyRun_SimpleString("pyui.intilize = pyui.instance.build(0)\n");
}
pModule = PyImport_ImportModule("pyui");
if (pModule != NULL) {
pFunc = PyObject_GetAttrString(pModule, "update_funct");
pPeriodicFunc = PyObject_GetAttrString(pModule, "periodic_funct");
pClass = PyObject_GetAttrString(pModule, "instance");
pExit = PyObject_GetAttrString(pModule, "exit_funct");
if (pFunc == NULL){
fprintf(stderr, "Panelui: Failed to find update function in python section\n");
exit(1);
}
if (pFunc && PyCallable_Check(pFunc)) {
pValue = PyObject_CallFunction(pFunc, "Olllh", pClass, 0, 0, 0, 0);
if (pValue == NULL){
fprintf(stderr, "Panelui: update function failed: returned NULL\n");
}
}else{
if (PyErr_Occurred()){
PyErr_Print();
}
fprintf(stderr, "Panelui: Failed python function");
exit(1);
}
}else {
PyErr_Print();
fprintf(stderr, "Panelui: Failed to load \"%s\"\n", "pyui");
exit(1);
}
for (rowshift = 1; ncols > (1 << rowshift); rowshift++);
signal(SIGINT, quit);
signal(SIGTERM, quit);
signal(SIGPIPE, quit);
snprintf(comp_name, sizeof(comp_name), "panelui");
ignore_sig = 1;
comp_id = hal_init(comp_name);
ignore_sig = 0;
if (comp_id < 0) {
fprintf(stderr, "ERROR: hal_init() failed: %d\n", comp_id );
goto out;
}
hal_ready(comp_id);
int res = hal_stream_attach(&stream, comp_id, SAMPLER_SHMEM_KEY+channel, "u");
if (res < 0) {
errno = -res;
perror("hal_stream_attach");
goto out;
}
clock_gettime(CLOCK_REALTIME, &gettime_now);
last_heartbeat = gettime_now.tv_nsec;
while ( samples != 0 ) {
union hal_stream_data buf[1];
hal_stream_wait_readable(&stream, &stop);
if(stop) break;
int res = hal_stream_read(&stream, buf, &this_sample);
if (res < 0) {
errno = -res;
perror("hal_stream_read");
goto out;
}
++last_sample;
if ( this_sample != last_sample ) {
printf ( "overrun\n");
last_sample = this_sample;
}
if ( tag ) {
printf ( "%d ", this_sample-1 );
}
raw = (unsigned long)buf[0].u;
keycode = (raw & ~(keydown | keyup));
r = keycode >> rowshift;
c = keycode & ~(0xFFFFFFFF << rowshift);
if (r < 0
|| c < 0
|| r >= nrows
|| c >= ncols){
goto skip;
}
if (raw == nochange) goto skip;
if ((raw & keydown) == keydown){
if (num_keys >= rollover) goto skip;
num_keys++;
s = 1;
}else if ((raw & keyup) == keyup){
if (num_keys > 0) num_keys--;
s = 0;
}else if (raw != 0) goto skip;
pValue = PyObject_CallFunction(pFunc, "Olllh",pClass, raw, r, c, s);
if (PyErr_Occurred()) PyErr_Print();
if (pValue == NULL){
fprintf(stderr, "Panelui's python update function failed: returned NULL\n");
}
skip:
if ( samples > 0 ) samples--;
clock_gettime(CLOCK_REALTIME, &gettime_now);
heartbeat_difference = gettime_now.tv_nsec - last_heartbeat; if (heartbeat_difference < 0)
heartbeat_difference += 1000000000; if (heartbeat_difference > 100000000){ last_heartbeat += 100000000;
if (last_heartbeat > 1000000000) last_heartbeat -= 1000000000;
pValue = PyObject_CallFunction(pPeriodicFunc, "O",pClass);
if (PyErr_Occurred()) PyErr_Print();
}
}
exitval = 0;
out:
ignore_sig = 1;
hal_stream_detach(&stream);
if ( comp_id >= 0 ) {
hal_exit(comp_id);
}
PyRun_SimpleString("print '''Exiting panelui's python module '''");
pValue = PyObject_CallObject(pExit, NULL);
if (PyErr_Occurred()) {
PyErr_Print();
}
Py_Finalize();
return exitval;
}