aboutsummaryrefslogtreecommitdiff
path: root/tcl_class.cxx
blob: 94c56ba57071fdd9d0ff467e23a28fcdcc71a2bf (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
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
#include "tcl_extras.h"
#include <map>
#include <string>
#include <string.h>

using namespace std;

static unsigned long objectSequentialId = 0;
map<string,t_class*> class_table;
map<string,t_pd*> object_table;

/* set up the class that handles loading of tcl classes */
t_class* tclpd_class_new(const char* name, int flags) {
    t_class* c = class_new(gensym(name), (t_newmethod)tclpd_new,
        (t_method)tclpd_free, sizeof(t_tcl), flags, A_GIMME, A_NULL);
    class_table[string(name)] = c;
    class_addanything(c, tclpd_anything);
    return c;
}

t_class* tclpd_guiclass_new(const char* name, int flags) {
    t_class* c = tclpd_class_new(name, flags);
    t_widgetbehavior* wb = (t_widgetbehavior*)getbytes(sizeof(t_widgetbehavior));
    wb->w_getrectfn = tclpd_guiclass_getrect;
    wb->w_displacefn = tclpd_guiclass_displace;
    wb->w_selectfn = tclpd_guiclass_select;
    wb->w_activatefn = NULL;
    wb->w_deletefn = tclpd_guiclass_delete;
    wb->w_visfn = tclpd_guiclass_vis;
    wb->w_clickfn = tclpd_guiclass_click;
    class_setwidget(c, wb);
    return c;
}

t_tcl* tclpd_new(t_symbol* classsym, int ac, t_atom* at) {
    const char* name = classsym->s_name;
    t_class* qlass = class_table[string(name)];
    t_tcl* self = (t_tcl*)pd_new(qlass);
    self->ninlets = 1 /* qlass->c_firstin ??? */;
    char s[64];
    snprintf(s, 64, "tclpd:%s:x%lx", name, objectSequentialId++);
    self->self = Tcl_NewStringObj(s, -1);
    Tcl_IncrRefCount(self->self);
    object_table[string(s)] = (t_pd*)self;
    Tcl_Obj *av[ac+2];
    av[0] = Tcl_NewStringObj(name, -1);
    Tcl_IncrRefCount(av[0]);
    av[1] = self->self;
    for(int i=0; i<ac; i++) {
        if(pd_to_tcl(&at[i], &av[2+i]) == TCL_ERROR) {
            tclpd_interp_error(TCL_ERROR);
            pd_free((t_pd*)self);
            return 0;
        }
    }
    if(Tcl_EvalObjv(tcl_for_pd, ac+2, av, 0) != TCL_OK) {
        tclpd_interp_error(TCL_ERROR);
        pd_free((t_pd*)self);
        return 0;
    }
    return self;
}

void tclpd_free(t_tcl* self) {
#ifdef DEBUG
    post("tclpd_free called");
#endif
}

void tclpd_anything(t_tcl* self, t_symbol* s, int ac, t_atom* at) {
    tclpd_inlet_anything(self, 0, s, ac, at);
}

void tclpd_inlet_anything(t_tcl* self, int inlet, t_symbol* s, int ac, t_atom* at) {
/* proxy method */
    Tcl_Obj* av[ac+3];
    av[0] = self->self;
    av[1] = Tcl_NewIntObj(inlet);
    Tcl_IncrRefCount(av[1]);
    av[2] = Tcl_NewStringObj(s->s_name, -1);
    Tcl_IncrRefCount(av[2]);
    for(int i=0; i<ac; i++) {
        if(pd_to_tcl(&at[i], &av[3+i]) == TCL_ERROR) {
            tclpd_interp_error(TCL_ERROR);
            return;
        }
    }
    int result = Tcl_EvalObjv(tcl_for_pd, ac+3, av, 0);
    Tcl_DecrRefCount(av[1]);
    Tcl_DecrRefCount(av[2]);
    if(result != TCL_OK) {
        tclpd_interp_error(TCL_ERROR);
    }
}

/* Tcl glue: */

t_proxyinlet* tclpd_add_proxyinlet(t_tcl* x) {
    t_proxyinlet* proxy = (t_proxyinlet*)pd_new(proxyinlet_class);
    proxyinlet_init(proxy);
    proxy->target = x;
    proxy->ninlet = x->ninlets++;
    inlet_new(&x->o, &proxy->obj.ob_pd, 0, 0);
    return proxy;
}

t_tcl* tclpd_get_instance(const char* objectSequentialId) {
    return (t_tcl*)object_table[objectSequentialId];
}

t_object* tclpd_get_object(const char* objectSequentialId) {
    t_tcl* x = tclpd_get_instance(objectSequentialId);
    return &x->o;
}

t_pd* tclpd_get_object_pd(const char* objectSequentialId) {
    t_object* o = tclpd_get_object(objectSequentialId);
    return &o->ob_pd;
}

void poststring2 (const char *s) {
    post("%s", s);
}

void tclpd_save(t_gobj* z, t_binbuf* b) {
}