aboutsummaryrefslogtreecommitdiff
path: root/pd/src/g_guiconnect.c
blob: 561ee1a8d75e9d6ccaefa6ee7c94d819d0b59d17 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
/* Copyright (c) 1997-2000 Miller Puckette.
* For information on usage and redistribution, and for a DISCLAIMER OF ALL
* WARRANTIES, see the file, "LICENSE.txt," in this distribution.  */

/*  a thing to forward messages from the GUI, dealing with race conditions
in which the "target" gets deleted while the GUI is sending it something.
*/

#include "m_pd.h"
#include "g_canvas.h"

struct _guiconnect
{
    t_object x_obj;
    t_pd *x_who;
    t_symbol *x_sym;
    t_clock *x_clock;
};

static t_class *guiconnect_class;

t_guiconnect *guiconnect_new(t_pd *who, t_symbol *sym)
{
    t_guiconnect *x = (t_guiconnect *)pd_new(guiconnect_class);
    x->x_who = who;
    x->x_sym = sym;
    pd_bind(&x->x_obj.ob_pd, sym);
    return (x);
}

    /* cleanup routine; delete any resources we have */
static void guiconnect_free(t_guiconnect *x)
{
    if (x->x_sym)
        pd_unbind(&x->x_obj.ob_pd, x->x_sym);
    if (x->x_clock)
        clock_free(x->x_clock); 
}

    /* this is called when the clock times out to indicate the GUI should
    be gone by now. */
static void guiconnect_tick(t_guiconnect *x)
{
    pd_free(&x->x_obj.ob_pd);
}

    /* the target calls this to disconnect.  If the gui has "signed off"
    we're ready to delete the object; otherwise we wait either for signoff
    or for a timeout. */
void guiconnect_notarget(t_guiconnect *x, double timedelay)
{
    if (!x->x_sym)
        pd_free(&x->x_obj.ob_pd);
    else
    {
        x->x_who = 0;
        if (timedelay > 0)
        {
            x->x_clock = clock_new(x, (t_method)guiconnect_tick);
            clock_delay(x->x_clock, timedelay);
        }
    }    
}

    /* the GUI calls this to send messages to the target. */
static void guiconnect_anything(t_guiconnect *x,
    t_symbol *s, int ac, t_atom *av)
{
    if (x->x_who)
        typedmess(x->x_who, s, ac, av);
}

    /* the GUI calls this when it disappears.  (If there's any chance the
    GUI will fail to do this, the "target", when it signs off, should specify
    a timeout after which the guiconnect will disappear.) */
static void guiconnect_signoff(t_guiconnect *x)
{
    if (!x->x_who)
        pd_free(&x->x_obj.ob_pd);
    else
    {
        pd_unbind(&x->x_obj.ob_pd, x->x_sym);
        x->x_sym = 0;
    }
}

void g_guiconnect_setup(void)
{
    guiconnect_class = class_new(gensym("guiconnect"), 0,
        (t_method)guiconnect_free, sizeof(t_guiconnect), CLASS_PD, 0);
    class_addanything(guiconnect_class, guiconnect_anything);
    class_addmethod(guiconnect_class, (t_method)guiconnect_signoff,
        gensym("signoff"), 0);
}