17. Actions

An action in Gest is an event that can happen when a new target is selected.

<<typedefs>>=
typedef struct gest_action gest_action;

An action is callback that can have it's own mutable state attached to it. It is part of a linked list entry, so it has a next pointer as well.

<<structs>>=
struct gest_action {
    void (*fun)(gest_d*, void*, int);
    void *data;
    gest_action *next;
};

An action lives inside of a list of actions, creatively referred to as an action list.

<<typedefs>>=
typedef struct gest_actionlist gest_actionlist;
<<gest_actionlist_struct>>=
struct gest_actionlist {
    gest_action *head;
    gest_action *tail;
    int sz;
};

An actionlist is part of a target.

<<gest_target>>=
gest_actionlist lst;
<<gest_target_init>>=
gest_actionlist_init(&t->lst);

An actionlist can be initialized with gest_actionlist_init.

<<funcdefs>>=
void gest_actionlist_init(gest_actionlist *lst);
<<funcs>>=
void gest_actionlist_init(gest_actionlist *lst)
{
    lst->head = NULL;
    lst->tail = NULL;
    lst->sz = 0;
}

Actions are appended to an action list associated with a target (usually the actively selected one). This can be done with the static function append_action.

<<static_funcdefs>>=
static void append_action(gest_d *g,
                          gest_target *t,
                          void (*fun)(gest_d*, void*, int),
                          void *data);
<<funcs>>=
static void append_action(gest_d *g,
                          gest_target *t,
                          void (*fun)(gest_d*, void*, int),
                          void *data)
{
    gest_action *a;
    gest_actionlist *lst;

    lst = &t->lst;
    a = gest_alloc(g, sizeof(gest_action));

    a->data = data;
    a->fun = fun;
    a->next = NULL;

    if (lst->head == NULL) {
        lst->head = a;
    }

    if (lst->tail != NULL) lst->tail->next = a;
    lst->tail = a;
    lst->sz++;
}

A new action requires making a callback, and optionally some data associated with it. The callback takes in the instance of gest, the user data associated with the action, and an integer value representing the current sample position inside the current render block. This position can be used for sample-accurate timing.

When a target is set up to be the current target, it calls the actions inside the action list. This is called do_actions.

<<static_funcdefs>>=
static void do_actions(gest_d *g, gest_target *t, int pos);
<<funcs>>=
static void do_actions(gest_d *g, gest_target *t, int pos)
{
    gest_actionlist *lst;
    gest_action *a;
    int i;

    lst = &t->lst;

    a = lst->head;

    for (i = 0; i < lst->sz; i++) {
        a->fun(g, a->data, pos);
        a = a->next;
    }
}



prev | home | next