GOT THE PYTHON RENDERING TO AN X WINDOW

This commit is contained in:
XANTRONIX Development 2024-01-08 21:32:30 -05:00
parent a9878c921d
commit 977734b00b
6 changed files with 202 additions and 47 deletions

5
bin/hexagram-app Executable file
View file

@ -0,0 +1,5 @@
#! /usr/bin/env python3
from hexagram.app import main
exit(main())

104
py/hexagram/app.pyx Executable file
View file

@ -0,0 +1,104 @@
import sys
import cairo
from Xlib.X import MapNotify, Expose
from libc.stdio cimport printf
from libc.string cimport memcpy
from posix.select cimport *
from hexagram.can cimport *
from hexagram.window cimport *
from hexagram.cluster import Cluster
CLUSTER_WIDTH = 1280
CLUSTER_HEIGHT = 480
CLUSTER_RPM_MIN = 1200
CLUSTER_RPM_REDLINE = 6500
CLUSTER_RPM_MAX = 8000
def usage(message=None):
if message:
print(message, file=sys.stderr)
print("usage: %s canif" % sys.argv[0], file=sys.stderr)
cdef handle_xevents(hexagram_window *window,
cluster: Cluster,
Display *display,
fg: cairo.Context):
cdef XEvent e
while XPending(display) > 0:
XNextEvent(display, &e)
if e.type == MapNotify or e.type == Expose:
hexagram_window_refresh_bg(window)
cluster.draw_fg(fg)
hexagram_window_swap_buffer(window)
def main():
cdef fd_set rfds, rready
cdef can_frame frame
import_cairo()
if len(sys.argv) != 2:
usage("No CAN interface specified")
can_if = hexagram_can_if_open(bytes(sys.argv[1], 'utf8'))
if can_if is NULL:
raise Exception("hexagram_can_if_open()")
window = hexagram_window_new_x11(NULL, CLUSTER_WIDTH, CLUSTER_HEIGHT)
if window is NULL:
raise Exception("hexagram_window_new_x11()")
cluster = Cluster(CLUSTER_RPM_MIN, CLUSTER_RPM_REDLINE, CLUSTER_RPM_MAX)
if hexagram_cluster_filter_can_if(can_if) < 0:
raise Exception("hexagram_cluster_filter_can_if()")
display = hexagram_window_display(window)
fd = hexagram_can_if_fd(can_if)
fd2 = hexagram_window_display_fd(window)
#
# Set up rendering surfaces
#
fg = PycairoContext_FromContext(hexagram_window_get_fg_context(window),
ctx_type(),
NULL)
bg = PycairoContext_FromContext(hexagram_window_get_bg_context(window),
ctx_type(),
NULL)
cluster.draw_bg(<object>bg)
hexagram_window_show(window)
FD_ZERO(&rfds)
FD_SET(fd, &rfds)
FD_SET(fd2, &rfds)
while True:
nfds = fd2 + 1
handle_xevents(window, cluster, display, <object>fg)
memcpy(&rready, &rfds, sizeof(rfds))
if select(nfds, &rready, NULL, NULL, NULL) < 0:
break
if FD_ISSET(fd, &rready):
hexagram_can_if_read(can_if, &frame)
hexagram_window_destroy(window)
return 0

28
py/hexagram/can.pxd Normal file
View file

@ -0,0 +1,28 @@
cdef extern from "sys/select.h":
ctypedef struct fd_set:
pass
cdef extern from "linux/can.h":
cdef struct can_frame:
pass
cdef extern from "hexagram/can.h":
ctypedef struct hexagram_can_if:
pass
hexagram_can_if *hexagram_can_if_open(const char *name)
void hexagram_can_if_close(hexagram_can_if *can_if)
int hexagram_can_if_read(hexagram_can_if *can_if, can_frame *frame)
int hexagram_can_if_write(hexagram_can_if *can_if, can_frame *frame)
int hexagram_can_if_fd(hexagram_can_if *can_if);
void hexagram_can_if_fd_set(hexagram_can_if *can_if, fd_set *fds)
int hexagram_can_if_fd_isset(hexagram_can_if *can_if, fd_set *fds)
cdef extern from "hexagram/cluster.h":
int hexagram_cluster_filter_can_if(hexagram_can_if *can_if)

View file

@ -1,41 +0,0 @@
from cpython.ref cimport PyObject, PyTypeObject, Py_INCREF
from hexagram.cluster import Cluster
cdef extern from "linux/can.h":
cdef struct can_frame:
pass
cdef extern from "cairo.h":
ctypedef struct cairo_t:
pass
cdef extern from "py3cairo.h":
cdef PyObject *PycairoContext_FromContext(cairo_t *ctx, PyTypeObject *type, PyObject *base)
ctypedef struct Pycairo_CAPI_t:
pass
cdef extern Pycairo_CAPI_t *Pycairo_CAPI
cdef extern from *:
"""
#define ctx_type (Pycairo_CAPI->Context_Type)
"""
cdef extern PyTypeObject *ctx_type
cdef class Cluster_py:
cdef object _obj
def __cinit__(self, double rpm_min, double rpm_redline, double rpm_max):
self._obj = <object>Cluster(rpm_min, rpm_redline, rpm_max)
cdef draw_bg(self, cairo_t *cr):
ctx = <object>PycairoContext_FromContext(cr, ctx_type, NULL)
self._obj.draw_bg(ctx)
cdef draw_fg(self, cairo_t *cr):
ctx = <object>PycairoContext_FromContext(cr, ctx_type, NULL)
self._obj.draw_fg(ctx)

54
py/hexagram/window.pxd Normal file
View file

@ -0,0 +1,54 @@
from cpython.ref cimport PyObject, PyTypeObject, Py_INCREF
cdef extern from "X11/Xlib.h":
ctypedef struct Display:
pass
ctypedef struct XEvent:
int type
long pad[24]
int XPending(Display *display)
int XNextEvent(Display *display, XEvent *event_return)
cdef extern from "cairo.h":
ctypedef struct cairo_t:
pass
cdef extern from "py3cairo.h":
cdef PyObject *PycairoContext_FromContext(cairo_t *ctx, PyTypeObject *type, PyObject *base)
cdef extern from *:
"""
#define ctx_api() (Pycairo_CAPI)
#define ctx_type() (Pycairo_CAPI->Context_Type)
"""
cdef int import_cairo()
cdef void *ctx_api()
cdef PyTypeObject *ctx_type()
cdef extern from "hexagram/window.h":
ctypedef struct hexagram_window:
pass
hexagram_window *hexagram_window_new_x11(const char *display,
int width,
int height)
void hexagram_window_destroy(hexagram_window *window)
Display *hexagram_window_display(hexagram_window *window)
int hexagram_window_display_fd(hexagram_window *window)
int hexagram_window_show(hexagram_window *window)
int hexagram_window_refresh_bg(hexagram_window *window)
int hexagram_window_swap_buffer(hexagram_window *window)
cairo_t *hexagram_window_get_bg_context(hexagram_window *window)
cairo_t *hexagram_window_get_fg_context(hexagram_window *window)

View file

@ -11,10 +11,15 @@ setup(
packages = [
'hexagram'
],
ext_modules = cythonize(
Extension(
"*", ["py/hexagram/*.pyx"],
include_dirs = ["./include", "/usr/include/cairo", "/usr/include/pycairo"]
), language_level = 3,
)
ext_modules = cythonize(Extension("*", [
"py/hexagram/*.pyx"
], include_dirs = [
"./include",
"/usr/include/cairo",
"/usr/include/pycairo"
], library_dirs = [
"src"
], libraries = [
"hexagram"
]), language_level = 3, gdb_debug = True)
)