aboutsummaryrefslogtreecommitdiff
path: root/cyclone/shadow/cyclone.c
blob: cb051b6d890e10e8646cc338eb3a96cdf513ef41 (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
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
/* Copyright (c) 2003-2005 krzYszcz and others.
 * For information on usage and redistribution, and for a DISCLAIMER OF ALL
 * WARRANTIES, see the file, "LICENSE.txt," in this distribution.  */

/* Never use forked calls in shadow code... */

/* LATER support multi-atom dir ('cd' message), and fn ('import' message)
   (same in maxmode, hammer and sickle) */

#include "m_pd.h"
#include "common/loud.h"
#include "common/port.h"
#include "hammer/file.h"
#include "unstable/fragile.h"
#include "unstable/loader.h"
#include "shadow.h"
#include "../build_counter"

typedef struct _cyclone
{
    t_object       x_ob;
    t_hammerfile  *x_filehandle;
} t_cyclone;

static t_class *cyclone_class;
static int cyclone_hammerndx;
static int cyclone_sicklendx;
static int cyclone_nettlesndx;
static int cyclone_lastndx;

static void cyclone_readhook(t_pd *z, t_symbol *fn, int ac, t_atom *av)
{
    int result = import_max(fn->s_name, "");
    outlet_float(((t_object *)z)->ob_outlet, (t_float)result);
}

static void cyclone_doimport(t_cyclone *x, t_symbol *fn)
{
    if (fn && fn != &s_)
    {
	t_symbol *dir = hammerpanel_getopendir(x->x_filehandle);
	int result =
	    import_max(fn->s_name, (dir && dir != &s_ ? dir->s_name : ""));
	outlet_float(((t_object *)x)->ob_outlet, (t_float)result);
    }
    else hammerpanel_open(x->x_filehandle, 0);
}

static void cyclone_click(t_cyclone *x, t_floatarg xpos, t_floatarg ypos,
			  t_floatarg shift, t_floatarg ctrl, t_floatarg alt)
{
    cyclone_doimport(x, 0);
}

static void cyclone_import(t_cyclone *x, t_symbol *fn)
{
    cyclone_doimport(x, fn);
}

static void cyclone_cd(t_cyclone *x, t_symbol *dir)
{
    hammerpanel_setopendir(x->x_filehandle, dir);
}

static void cyclone_pwd(t_cyclone *x, t_symbol *s)
{
    t_symbol *dir;
    if (s && s->s_thing && (dir = hammerpanel_getopendir(x->x_filehandle)))
	pd_symbol(s->s_thing, dir);
}

static void cyclone_bang(t_cyclone *x)
{
    if (cyclone_hammerndx && cyclone_sicklendx)
    {
	fragile_class_printnames("hammer classes are: ",
				 cyclone_hammerndx, cyclone_sicklendx - 1);
	fragile_class_printnames("sickle classes are: ",
				 cyclone_sicklendx, cyclone_nettlesndx - 1);
    }
    fragile_class_printnames("nettles are: ",
			     cyclone_nettlesndx, cyclone_lastndx - 1);
}

static void cyclone_free(t_cyclone *x)
{
    hammerfile_free(x->x_filehandle);
}

static void *cyclone_new(void)
{
    t_cyclone *x = (t_cyclone *)pd_new(cyclone_class);
    x->x_filehandle = hammerfile_new((t_pd *)x, 0, cyclone_readhook, 0, 0);
    outlet_new((t_object *)x, &s_float);
    return (x);
}

void cyclone_setup(void)
{
    int hresult, sresult;
    hresult = sresult = LOADER_OK;
    if (zgetfn(&pd_objectmaker, gensym("cyclone")))
    {
	loud_error(0, "cyclone is already loaded");
	return;
    }
    post("this is cyclone %s, %s %s build",
	 CYCLONE_VERSION, loud_ordinal(CYCLONE_BUILD), CYCLONE_RELEASE);
    cyclone_class = class_new(gensym("cyclone"),
			      (t_newmethod)cyclone_new,
			      (t_method)cyclone_free,
			      sizeof(t_cyclone), 0, 0);
    class_addbang(cyclone_class, cyclone_bang);
    class_addmethod(cyclone_class, (t_method)cyclone_cd,
		    gensym("cd"), A_DEFSYM, 0);
    class_addmethod(cyclone_class, (t_method)cyclone_pwd,
		    gensym("pwd"), A_SYMBOL, 0);
    class_addmethod(cyclone_class, (t_method)cyclone_import,
		    gensym("import"), A_DEFSYM, 0);
    class_addmethod(cyclone_class, (t_method)cyclone_click,
		    gensym("click"),
		    A_FLOAT, A_FLOAT, A_FLOAT, A_FLOAT, A_FLOAT, 0);
    hammerfile_setup(cyclone_class, 0);

    if (canvas_getcurrent())
    {
	/* Loading hammer and sickle by cyclone object creation is banned,
	   because of a danger of having some of the classes already loaded. */
	loud_warning(0, "cyclone",
 "creating cyclone object without loading cyclone components");
	cyclone_hammerndx = cyclone_sicklendx = 0;
    }
    else
    {
	cyclone_hammerndx = fragile_class_count();
	if (zgetfn(&pd_objectmaker, gensym("hammer")))
	    loud_warning(0, "cyclone", "hammer is already loaded");
	else
	    hresult = unstable_load_lib("", "hammer");

	cyclone_sicklendx = fragile_class_count();
	if (zgetfn(&pd_objectmaker, gensym("sickle")))
	    loud_warning(0, "cyclone", "sickle is already loaded");
	else
	    sresult = unstable_load_lib("", "sickle");
    }
    cyclone_nettlesndx = fragile_class_count();
    allnettles_setup();
    cyclone_lastndx = fragile_class_count() - 1;

    if (hresult == LOADER_NOFILE)
	loud_error(0, "hammer library is missing");
    else if (sresult == LOADER_NOFILE)
	loud_error(0, "sickle library is missing");
    else if (cyclone_hammerndx &&
	     (!zgetfn(&pd_objectmaker, gensym("hammer")) ||
	      !zgetfn(&pd_objectmaker, gensym("sickle"))))
    {
	loud_error(0, "version mismatch");
	loud_errand(0,
		    "use a more recent Pd release (or recompile the cyclone).");
    }
}