4 GObject Introspection
GStreamer is the core framework that powers the multimedia capabilities of Overscan. GStreamer is also a C framework, which means that a big part of Overscan’s codebase is dedicated to the interop between Racket and C. Racket provides a phenomenal Foreign Interface, but to create foreign functions for all the relevant portions of GStreamer would be cumbersome, at best.
Luckily, GStreamer is written with GLib and contains GObject Introspection metadata. GObject Introspection (aka GIR) is an interface description layer that allows for a language to read this metadata and dynamically create bindings for the C library.
The Overscan package provides a module designed to accompany Racket’s FFI collection. This module brings additional functionality and C Types for working with introspected C libraries. This module powers the GStreamer module, but can be used outside of Overscan for working with other GLib libraries.
(require ffi/unsafe/introspection) | package: overscan |
4.1 Basic Usage
Using GIR will typically go as follows: Introspect a namespace that you have a typelib for with introspection, call that namespace as a procedure to look up a binding, work with that binding either as a procedure or some other value (typically a gobject).
In this case of a typical "Hello, world" style example with GStreamer, that would look like this:
(define gst (introspection 'Gst)) (define gst-version (gst 'version_string)) (printf "This program is linked against ~a" (gst-version))
This will result in the string "This program is linked against GStreamer 1.10.4" being printed, or whatever version of GStreamer is available.
In the second line of this program, the 'version_string symbol is looked up against the GStreamer typelib and a gi-function? is returned. That can then be called as a procedure, which in this case takes no arguments.
4.2 GIRepository
GIR’s GIRepository API manages the namespaces provided by the GIR system and type libraries. Each namespace contains metadata entries that map to C functionality. In the case of GStreamer, the 'Gst namespace contains all of the introspection information used to power that interface.
procedure
(introspection namespace [version]) → gi-repository?
namespace : symbol? version : string? = #f
An example for loading the GStreamer namespace:
> (define gst (introspection 'Gst)) #<procedure:gi-repository>
This is the only provided mechanism to construct a gi-repository.
struct
(struct gi-repository (namespace version info-hash))
namespace : symbol? version : string? info-hash : (hash/c symbol? gi-base?)
When called as in the first form, without an argument, the proc will return a hash of all of the known members of the namespace.When called as the second form, this is the equivalent to gi-repository-find-name with the first argument already set. e.g.
> (gst 'version) #<procedure:gi-function> This will return an introspected foreign binding to the gst_version() C function, represented as a gi-function?.
procedure
(gi-repository-find-name repo name) → gi-base?
repo : gi-repository? name : symbol?
procedure
(gi-repository->ffi-lib repo) → ffi-lib?
repo : gi-repository?
procedure
(gir-member/c namespace) → flat-contract?
namespace : symbol?
procedure
(gi-repository-member/c repo) → flat-contract?
repo : gi-repository?
4.3 GIBaseInfo
The GIBaseInfo C Struct is the base struct for all GIR metadata entries. Whenever you do some lookup within GIR, what’s returned is an instance of a descendant from this struct. The gi-base struct is the Racket equivalent, and introspection will return entities that inherit from this base struct.
When a GIR metadata entry is located it will usually be a subtype of gi-base. Most of those subtypes implement prop:procedure and are designed to be called on return to produce meaningful values.
The typical subtypes are:
An introspected C function. Call this as you would any other Racket procedure. C functions have a tendency to mutate call-by-reference pointers, and when that is the case calling a gi-function returns multiple values. The first return value is always the return value of the function.
gi-base
(gi-constant) → any/c
Calling a gi-constant as a procedure returns its value.
The first argument to a gi-struct is the name of a method, with subsequent arguments passed in to that method call. This procedure form is mainly used for calling factory style methods, and more useful for the similar gi-object. Usually, you’ll be working with instances of this type, gstructs.
Like gi-struct, calling a gi-object as a procedure will accept a method name and subsequent arguments. This is the preferred form for calling constructors that will return gobjects.
gi-registered-type
gi-enum : gi-enum?
A gi-enum represents an enumeration of values and, unlike other gi-base subtypes, is not represented as a procedure. The main use case is to transform it into some other Racket representation, i.e. with gi-enum->list.
procedure
(gi-base-name info) → symbol?
info : gi-base?
procedure
(gi-function? v) → boolean?
v : any/c
procedure
(gi-registered-type? v) → boolean?
v : any/c
procedure
(gi-bitmask? v) → boolean?
v : any/c
procedure
(gi-enum->list enum) → list?
enum : gi-enum?
procedure
(gi-enum->hash enum) → hash?
enum : gi-enum?
procedure
(gi-enum-value/c enum) → flat-contract?
enum : gi-enum?
procedure
(gi-bitmask-value/c enum) → list-contract?
enum : gi-bitmask?
procedure
(gi-object? v) → boolean?
v : any/c
See GObjects for more information about using GObjects from within Racket.
procedure
(gi-struct? v) → boolean?
v : any/c
procedure
(_gi-object obj) → ctype?
obj : gi-object?
struct
(struct gi-instance (type pointer))
type : gi-registered-type? pointer : cpointer?
procedure
(gi-instance-name instance) → symbol?
instance : gi-instance?
procedure
v : any/c type : gi-registered-type?
procedure
(is-gtype?/c type) → flat-contract?
type : gi-registered-type?
procedure
(gtype-name gtype) → symbol?
gtype : gtype?
struct
(struct gstruct gi-instance (type pointer))
type : gi-struct? pointer : cpointer?
4.4 GObjects
A gobject instance, like the introspected metadata entries provided by GIR, is a transparent pointer with additional utilities to be called as an object within Racket. GObjects behave like Racket objects, with the exception that they aren’t backed by classes in the racket/class sense, but instead are derived from the introspected metadata.
procedure
(gobject/c type) → flat-contract?
type : gi-registered-type?
procedure
(gobject-ptr obj) → gi-instance?
obj : gobject?
procedure
(gobject-gtype obj) → gtype?
obj : gobject?
procedure
(gobject-send obj method-name argument ...) → any
obj : gobject? method-name : symbol? argument : any/c
procedure
(gobject-get-field field-name obj) → any
field-name : symbol? obj : gobject?
procedure
(gobject-set-field! field-name obj v) → void?
field-name : symbol? obj : gobject? v : any/c
procedure
(gobject-responds-to? obj method-name) → boolean?
obj : gobject? method-name : symbol?
procedure
(gobject-responds-to?/c method-name) → flat-contract?
method-name : symbol?
procedure
(method-names obj) → (listof symbol?)
obj : gobject?
procedure
(connect obj signal-name handler [ #:data data #:cast _user-data]) → exact-integer? obj : gobject? signal-name : symbol? handler : procedure? data : any/c = #f _user-data : (or/c ctype? gi-object?) = #f
procedure
(gobject-cast pointer obj) → gobject?
pointer : cpointer? obj : gi-object?
procedure
(gobject-get obj propname ctype) → any?
obj : gobject? propname : string? ctype : (or/c ctype? gi-registered-type? (listof symbol?))
procedure
(gobject-set! obj propname v [ctype]) → void?
obj : gobject? propname : string? v : any/c ctype : (or/c ctype? (listof symbol?)) = #f
procedure
(gobject-with-properties obj properties) → gobject?
obj : gobject? properties : (hash/c symbol? any/c)
procedure
(make-gobject-property-procedures propname ctype)
→
(-> gobject? any) (-> gobject? any/c void?) propname : string? ctype : (or/c ctype? gi-registered-type? (listof symbol?))
A convenient mechanism for creating a getter and a setter for a GObject property.
The prop:gobject property allows a GObject instance to be transparently wrapped by a structure that may have additional values or properties.
|
| ||
superclass: object% | ||
|
constructor
pointer : gi-instance?
syntax
(make-gobject-delegate method-decl ...)
method-decl = id | (id internal-method)
internal-method : symbol?
(make-gobject-delegate get-name get-factory [static-pad 'get_static_pad])
(mixin (gobject<%>) (gobject<%>) (super-new) (inherit-field pointer) (define/public (get-name . args) (apply gobject-send pointer 'get_name args)) (define/public (get-factory . args) (apply gobject-send pointer 'get_factory args)) (define/public (static-pad . args) (apply gobject-send pointer 'get_static_pad args)))