aboutsummaryrefslogtreecommitdiff
path: root/externals/grill/prepend/main.cpp
blob: 91a9a5ff70e1be7edb42ad5367191a1bb183f5ed (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
/* 

prepend - just like in MaxMSP

Copyright (c) 2002 Thomas Grill (xovo@gmx.net)
For information on usage and redistribution, and for a DISCLAIMER OF ALL
WARRANTIES, see the file, "license.txt," in this distribution.  

*/

#include <flext.h>

#if !defined(FLEXT_VERSION) || (FLEXT_VERSION < 401)
#error You need at least flext version 0.4.1
#endif

#define PREPEND_VERSION "0.0.3"

class prepend: 
	public flext_base
{
	FLEXT_HEADER_S(prepend, flext_base, Setup)

public:
	prepend(int argc,t_atom *argv);

protected:
	void m_bang();
	void m_set(int argc,t_atom *argv) { reg[0].Store(NULL,argc,argv); }
	void m_any0(const t_symbol *s,int argc,t_atom *argv) { reg[1].Store(s,argc,argv); m_bang(); }
	void m_any1(const t_symbol *s,int argc,t_atom *argv) { reg[0].Store(s,argc,argv); }

	virtual void m_help();

private:	

	static void Setup(t_class *c);

	class reg_t 
	{ 
	public:
		reg_t(): cnt(0),lst(NULL) {}
		~reg_t() { if(lst) delete[] lst; }

		bool Is() const { return cnt && lst; }
		bool IsSimple() const { return !IsSymbol(lst[0]); }
		bool IsList() const { return IsSymbol(lst[0]) && GetSymbol(lst[0]) == &s_list; }

		void Store(const t_symbol *s,int argc,t_atom *argv);
		int cnt; t_atom *lst; 
	} reg[2];

	FLEXT_CALLBACK(m_bang)
	FLEXT_CALLBACK_V(m_set)
	FLEXT_CALLBACK_A(m_any0)
	FLEXT_CALLBACK_A(m_any1)
};

FLEXT_NEW_V("prepend",prepend)



prepend::prepend(int argc,t_atom *argv)
{
	AddInAnything(2);  
	AddOutAnything();   

	m_set(argc,argv);
}

void prepend::Setup(t_class *c)
{
	FLEXT_CADDMETHOD_(c,0,"bang",m_bang);
//	FLEXT_CADDMETHOD_(c,0,"set",m_set);
	FLEXT_CADDMETHOD(c,0,m_any0);
	FLEXT_CADDMETHOD(c,1,m_any1);
}

void prepend::reg_t::Store(const t_symbol *s,int argc,t_atom *argv)
{
	if(lst) delete[] lst; cnt = 0;
	lst = new t_atom[argc+1];

	if(s && s != &s_float) SetSymbol(lst[cnt++],s);
	else if(argc > 0 && !IsSymbol(argv[0])) SetSymbol(lst[cnt++],&s_list);

	for(int i = 0; i < argc; ++i,++cnt) lst[cnt] = argv[i];
}

void prepend::m_bang()
{
	t_atom *ret = new t_atom[reg[0].cnt+reg[1].cnt+1];
	int i,rcnt = 0;

	if(reg[0].Is()) {
		if(reg[0].IsSimple()) SetSymbol(ret[rcnt++],&s_list);
		for(i = reg[0].IsList()?1:0; i < reg[0].cnt; ++i) ret[rcnt++] = reg[0].lst[i];
	}
	else
		SetSymbol(ret[rcnt++],&s_list);

	if(reg[1].Is()) {
		for(i = reg[1].IsList()?1:0; i < reg[1].cnt; ++i) ret[rcnt++] = reg[1].lst[i];
	}

	if(IsSymbol(ret[0]))
		ToOutAnything(0,GetSymbol(ret[0]),rcnt-1,ret+1);
	else
		ToOutList(0,rcnt,ret);
	delete[] ret;
}

void prepend::m_help()
{
	post("%s - just like in Max/MSP, version " PREPEND_VERSION,thisName());
#ifdef _DEBUG
	post("compiled on " __DATE__ " " __TIME__);
#endif
	post("(C) Thomas Grill, 2002");
	post("");
	post("Arguments: %s [atoms to prepend]",thisName());
	post("Inlets: 1:triggering atoms");
	post("Inlets: 2:atoms to prepend");
	post("Outlets: 1:sum of prepend");	
	post("Methods:");
	post("\thelp: shows this help");
//	post("\tset [atoms]: set atoms to prepend");
	post("");
}