The Programs of the First Week of October
This Weak Program: Oct 2 - Oct 6
Do you see it? This email’s easter egg? It’s my clever joke.
Oh hi friends thank you for reading about my esoteric program. Yes I’m still working on it. This is the hardest side project in the world to describe.
This week I continued to make progress on my Racket bindings for the multimedia C framework that will power my live coding environment for live streaming video. Cool, right? The coolest?
708d000d47a170587698132f8e3bc6705743d5c1
I continue my build-out of Racket classes that delegate to
GObjects. Here’s pipeline%
, which is the piece of the puzzle that
lets me finally actually make video.
12b0b1150879f77db81931407ed7ee4e40dcdd87
Now that I’m pulling these pieces together in a cohesive manner, I can
do some patterns I didn’t think about doing before, like wrapping
last week’s bin%-compose
in a pipeline%
object. pipeline%-compose
let’s me quickly create a GStreamer
pipeline.
So I can do something like this:
(pipeline%-compose "borat-voice:my-pipes"
(element-factory%-make "videotestsrc")
(element-factory%-make "osxvideosink")
This makes a pipeline, and then I can play it! Simple as pie(-pline).
b1a4f8929ee6e8ec7b2ef42148d600647d952483
I rename the introspection functions is-a?
and is-a?/c
to
is-gtype?
and is-gtype/c?
. The latter forms are more descriptive
about what’s actually being checked and they don’t conflict with
identifiers from racket/class
. I think I might end up renaming or
removing a bunch of functionality in ffi/unsafe/introspection
so
that there are no conflicts with racket/class
at all. Now that I
have gobject<%>
, I think I’ve done enough real-world programming to
show how the world of Racket OOP and GIR can coexist.
6d67c6fd2012a960af220c53c5c94cc4faf78c27
Everybody get on the bus%
! Here I’m reworking how I can pull
messages from a pipeline off a FIFO queue. 🚌
1871749bee5035dbf43f751bf3d3d54613b31ec3
Here’s a couple of handy functions for working with the generic
gobject
interface I set up a few weeks ago (the same one that all of
these gobject%
subclasses implement). gobject-ptr
will extract a
gtype-instance
pointer out of anything that implements
prop:gobject
, and gobject/c
is a contract similar to
is-gtype?/c
, but accepts gobject
values. I’ll use these later to
have the make-bus-channel
a little cleaner and able to operate on
any Bus derivative.
b92404cc4b71e6addf69f081995646a7d161e09b
A couple of more helpers for working with GIR bitmasks. A bitmask is a
special case of gi-enum
, and these functions just help me clarify
some contracts for working with them.
ef257cd9ccf67a85d9cebf86e95984f19b6b2fe2
Some more refinements to working with GStreamer buses and
messages. When a bus channel gets an end of stream or error message,
it should close down. The internal implementation of these channels
utilize Racket places. A place is something between a
thread, a CSP routine, and a fork of the Racket process. I don’t want
it to utilize system resources when it’s not being used, mostly
because I have no idea what system resources are being utilized when a
Place exists. The output of the place has been a message from the bus,
which I wrap and cast into the right kind of interface. But now I do a
select
kind of operation to see if there’s a message waiting or if
the place has closed down. The function to do this select (that
terminology should be familiar to Golang fans) is called choice-evt
,
and one of the choices is place-dead-evt
. This is a Racket event that can
be synchronized when a place has terminated.
Now make-bus-channel
returns a channel that has three kinds of
results when synchronized (with sync
, naturally):
- A
message
from the bus #f
(that’s false) when there’s a NULL pointer (to be expected with the particulars of the underlying bus operation).- The
place-dead-evt
, which can be checked withevt?
, for when the bus channel has closed down. Once the channel has closed, this will always be the synchronization result and doing async
won’t ever block.
One of these days I’ll write a big blog post (or something) about thinking in CSP across various languages (Clojure with core.async, my limited understanding of Go routines, and Racket). It’s a dope way of managing concurrent operations. Would you be interested in something like that?
With this week’s contribution, I can now begin closing out the
gstreamer
module with some final utility functions and structures
and a whole bunch of documentation. Feels like a good week!
🍂 Mark