aboutsummaryrefslogtreecommitdiff
path: root/Gem/develop/include/Gem/RTE/MessageCallbacks.h
blob: 9fa57cdd424c425d100fc01f26d0eb1a3582dc08 (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
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
/*-----------------------------------------------------------------
  LOG
  GEM - Graphics Environment for Multimedia

  helper-functions&macros for message callbacks to objects

  Copyright (c) 2010-2011 IOhannes m zmölnig. forum::für::umläute. IEM. zmoelnig@iem.at
  For information on usage and redistribution, and for a DISCLAIMER OF ALL
  WARRANTIES, see the file, "GEM.LICENSE.TERMS" in this distribution.

  -----------------------------------------------------------------*/

// these utility macros warp the callback functions from the RTE, no need add them to your headers!

// NOTE: this is very experimental; you should not include this header unless you know what you are doing
// once this has proven to work (test on M$VC!), it is likely to be included automatically

/* usage:
 *    void myclass::obj_setupCallback(t_class*classPtr) {
 *      CPPEXTERN_MSG (classPtr, "foo", gimmeMess); // A_GIMME
 *      CPPEXTERN_MSG0(classPtr, "doit", bangMess); // no args
 *      CPPEXTERN_MSG1(classPtr, "name", nameMess, t_symbol*);  // 1 arg (A_SYMBOL)
 *      CPPEXTERN_MSG1(classPtr, "title", titleMess, const std::string&); // 1 arg (A_SYMBOL)
 *      CPPEXTERN_MSG3(classPtr, "values", tripletMess, t_float, t_float, t_float);  // 3 args (A_FLOAT)
 *    }
 *    void myclass::gimmeMess  (t_symbol*s, int argc, t_atom*argv) {;}
 *    void myclass::bangMess   (void)                              {;}
 *    void myclass::nameMess   (t_symbol*s)                        {;}
 *    void myclass::titleMess  (const std::string&s)               {;}
 *    void myclass::tripletMess(t_float a, t_float b, t_float c)   {;}
 */
#ifndef _INCLUDE__GEM_RTE_MESSAGECALLBACKS_H_
#define _INCLUDE__GEM_RTE_MESSAGECALLBACKS_H_

namespace gem
{
namespace RteMess
{
class NoneType {}; // just a dummy class
template<class T=NoneType, class T1=T>
struct TypeTemplateCore {
  static t_atomtype atomtype_id(void)
  {
    return A_NULL;
  }
  static T1 cast(T value)
  {
    return static_cast<T1>(value);
  }
  typedef T proxyType;
  virtual ~TypeTemplateCore(void) { }
};
template<class T>
struct TypeTemplate : TypeTemplateCore<T, T> {
};
template<>
struct TypeTemplate<float> : TypeTemplateCore<t_float, float> {
  static t_atomtype atomtype_id(void)
  {
    return A_FLOAT;
  }
};
template<>
struct TypeTemplate<double> : TypeTemplateCore<t_float, double> {
  static t_atomtype atomtype_id(void)
  {
    return A_FLOAT;
  }
};
template<>
struct TypeTemplate<t_int> : TypeTemplateCore<t_float, t_int> {
  static t_atomtype atomtype_id(void)
  {
    return A_FLOAT;
  }
};
template<>
struct TypeTemplate<int> : TypeTemplateCore<t_float, int> {
  static t_atomtype atomtype_id(void)
  {
    return A_FLOAT;
  }
};
template<>
struct TypeTemplate<unsigned int> : TypeTemplateCore<t_float, unsigned int> {
  static t_atomtype atomtype_id(void)
  {
    return A_FLOAT;
  }
  static unsigned int cast(t_float f)
  {
    return (f>0.)?static_cast<unsigned int>(f):0;
  }
};
template<>
struct TypeTemplate<bool> : TypeTemplateCore<t_float, bool> {
  static t_atomtype atomtype_id(void)
  {
    return A_FLOAT;
  }
  static bool cast(t_float f)
  {
    return (f>0.5);
  }
};
template<>
struct TypeTemplate<t_symbol*> : TypeTemplateCore<t_symbol*> {
  static t_atomtype atomtype_id(void)
  {
    return A_DEFSYMBOL;
  }
};
template<>
struct TypeTemplate<std::string> : TypeTemplateCore<t_symbol*, std::string> {
  static t_atomtype atomtype_id(void)
  {
    return A_DEFSYMBOL;
  }
  static std::string cast(t_symbol*s)
  {
    return std::string(s->s_name);
  }
};
};
};
#define MSG_CONCAT3(a, b, c) _##a##_##b##_##c




#define CPPEXTERN_MSG_(line, cp, selector, fun)                 \
  struct MSG_CONCAT3(CallbackClass, fun, line) {                \
    static void callback(void*data, t_symbol*s, int argc, t_atom*argv) { GetMyClass(data)->fun(s, argc, argv); } \
    MSG_CONCAT3(CallbackClass, fun, line) (t_class*c, std::string s) { class_addmethod(c, reinterpret_cast<t_method>(callback), gensym(s.c_str()), A_GIMME, A_NULL); } \
  };                                                                    \
  MSG_CONCAT3(CallbackClass, fun, line)  MSG_CONCAT3(CallbackClassInstance, fun, line) (cp, selector)
#define CPPEXTERN_MSG0_(line, cp, selector, fun)                \
  struct MSG_CONCAT3(CallbackClass, fun, line) {                \
    static void callback(void*data) { GetMyClass(data)->fun(); }        \
    MSG_CONCAT3(CallbackClass, fun, line) (t_class*c, std::string s) { class_addmethod(c, reinterpret_cast<t_method>(callback), gensym(s.c_str()), A_NULL); } \
  };                                                                    \
  MSG_CONCAT3(CallbackClass, fun, line)  MSG_CONCAT3(CallbackClassInstance, fun, line) (cp, selector)
#define CPPEXTERN_MSG1_(line, cp, selector, fun, typ0)          \
  struct MSG_CONCAT3(CallbackClass, fun, line) {                \
    static void callback(void*data, gem::RteMess::TypeTemplate<typ0>::proxyType v0) \
      { GetMyClass(data)->fun(gem::RteMess::TypeTemplate<typ0>::cast(v0)); } \
    MSG_CONCAT3(CallbackClass, fun, line) (t_class*c, std::string s) { class_addmethod(c, reinterpret_cast<t_method>(callback), gensym(s.c_str()), ("symbol"==s)?A_SYMBOL:(gem::RteMess::TypeTemplate<typ0>::atomtype_id()),  A_NULL); } \
  };                                                                    \
  MSG_CONCAT3(CallbackClass, fun, line)  MSG_CONCAT3(CallbackClassInstance, fun, line) (cp, selector)
#define CPPEXTERN_MSG2_(line, cp, selector, fun, typ0, typ1)    \
  struct MSG_CONCAT3(CallbackClass, fun, line) {                \
    static void callback(void*data, gem::RteMess::TypeTemplate<typ0>::proxyType v0, gem::RteMess::TypeTemplate<typ1>::proxyType v1) \
      { GetMyClass(data)->fun(gem::RteMess::TypeTemplate<typ0>::cast(v0),  gem::RteMess::TypeTemplate<typ1>::cast(v1)); } \
    MSG_CONCAT3(CallbackClass, fun, line) (t_class*c, std::string s) { class_addmethod(c, reinterpret_cast<t_method>(callback), gensym(s.c_str()), gem::RteMess::TypeTemplate<typ0>::atomtype_id(),  gem::RteMess::TypeTemplate<typ1>::atomtype_id(),  A_NULL); } \
  };                                                                    \
  MSG_CONCAT3(CallbackClass, fun, line)  MSG_CONCAT3(CallbackClassInstance, fun, line) (cp, selector)

#define CPPEXTERN_MSG3_(line, cp, selector, fun, typ0, typ1, typ2) \
  struct MSG_CONCAT3(CallbackClass, fun, line) {                \
    static void callback(void*data, gem::RteMess::TypeTemplate<typ0>::proxyType v0, gem::RteMess::TypeTemplate<typ1>::proxyType v1, gem::RteMess::TypeTemplate<typ2>::proxyType v2) \
      { GetMyClass(data)->fun(gem::RteMess::TypeTemplate<typ0>::cast(v0),  gem::RteMess::TypeTemplate<typ1>::cast(v1),  gem::RteMess::TypeTemplate<typ2>::cast(v2)); } \
    MSG_CONCAT3(CallbackClass, fun, line) (t_class*c, std::string s) { class_addmethod(c, reinterpret_cast<t_method>(callback), gensym(s.c_str()), gem::RteMess::TypeTemplate<typ0>::atomtype_id(),  gem::RteMess::TypeTemplate<typ1>::atomtype_id(),  gem::RteMess::TypeTemplate<typ2>::atomtype_id(), A_NULL); } \
  };                                                                    \
  MSG_CONCAT3(CallbackClass, fun, line)  MSG_CONCAT3(CallbackClassInstance, fun, line) (cp, selector)

#define CPPEXTERN_MSG4_(line, cp, selector, fun, typ0, typ1, typ2, typ3) \
  struct MSG_CONCAT3(CallbackClass, fun, line) {                \
    static void callback(void*data, gem::RteMess::TypeTemplate<typ0>::proxyType v0, gem::RteMess::TypeTemplate<typ1>::proxyType v1, gem::RteMess::TypeTemplate<typ2>::proxyType v2, gem::RteMess::TypeTemplate<typ3>::proxyType v3) \
      { GetMyClass(data)->fun(gem::RteMess::TypeTemplate<typ0>::cast(v0),  gem::RteMess::TypeTemplate<typ1>::cast(v1),  gem::RteMess::TypeTemplate<typ2>::cast(v2),  gem::RteMess::TypeTemplate<typ3>::cast(v3)); } \
    MSG_CONCAT3(CallbackClass, fun, line) (t_class*c, std::string s) { class_addmethod(c, reinterpret_cast<t_method>(callback), gensym(s.c_str()), gem::RteMess::TypeTemplate<typ0>::atomtype_id(),  gem::RteMess::TypeTemplate<typ1>::atomtype_id(),  gem::RteMess::TypeTemplate<typ2>::atomtype_id(),  gem::RteMess::TypeTemplate<typ3>::atomtype_id(), A_NULL); } \
  };                                                                    \
  MSG_CONCAT3(CallbackClass, fun, line)  MSG_CONCAT3(CallbackClassInstance, fun, line) (cp, selector)
#define CPPEXTERN_MSG5_(line, cp, selector, fun, typ0, typ1, typ2, typ3, typ4) \
  struct MSG_CONCAT3(CallbackClass, fun, line) {                \
    static void callback(void*data, gem::RteMess::TypeTemplate<typ0>::proxyType v0, gem::RteMess::TypeTemplate<typ1>::proxyType v1, gem::RteMess::TypeTemplate<typ2>::proxyType v2, gem::RteMess::TypeTemplate<typ3>::proxyType v3, gem::RteMess::TypeTemplate<typ4>::proxyType v4) \
      { GetMyClass(data)->fun(gem::RteMess::TypeTemplate<typ0>::cast(v0),  gem::RteMess::TypeTemplate<typ1>::cast(v1),  gem::RteMess::TypeTemplate<typ2>::cast(v2),  gem::RteMess::TypeTemplate<typ3>::cast(v3),  gem::RteMess::TypeTemplate<typ4>::cast(v4)); } \
    MSG_CONCAT3(CallbackClass, fun, line) (t_class*c, std::string s) { class_addmethod(c, reinterpret_cast<t_method>(callback), gensym(s.c_str()), gem::RteMess::TypeTemplate<typ0>::atomtype_id(),  gem::RteMess::TypeTemplate<typ1>::atomtype_id(),  gem::RteMess::TypeTemplate<typ2>::atomtype_id(),  gem::RteMess::TypeTemplate<typ3>::atomtype_id(),  gem::RteMess::TypeTemplate<typ4>::atomtype_id(), A_NULL); } \
  };                                                                    \
  MSG_CONCAT3(CallbackClass, fun, line)  MSG_CONCAT3(CallbackClassInstance, fun, line) (cp, selector)


#define CPPEXTERN_MSG(cp, selector, fun)                                CPPEXTERN_MSG_  ( __LINE__ , cp, selector, fun)
#define CPPEXTERN_MSG0(cp, selector, fun)                               CPPEXTERN_MSG0_ ( __LINE__ , cp, selector, fun)
#define CPPEXTERN_MSG1(cp, selector, fun, typ)                          CPPEXTERN_MSG1_ ( __LINE__ , cp, selector, fun, typ)
#define CPPEXTERN_MSG2(cp, selector, fun, typ0, typ1)                   CPPEXTERN_MSG2_ ( __LINE__ , cp, selector, fun, typ0, typ1)
#define CPPEXTERN_MSG3(cp, selector, fun, typ0, typ1, typ2)             CPPEXTERN_MSG3_ ( __LINE__ , cp, selector, fun, typ0, typ1, typ2)
#define CPPEXTERN_MSG4(cp, selector, fun, typ0, typ1, typ2, typ3)       CPPEXTERN_MSG4_ ( __LINE__ , cp, selector, fun, typ0, typ1, typ2, typ3)
#define CPPEXTERN_MSG5(cp, selector, fun, typ0, typ1, typ2, typ3, typ4) CPPEXTERN_MSG5_ ( __LINE__ , cp, selector, fun, typ0, typ1, typ2, typ3, typ4)




#endif /* _INCLUDE__GEM_RTE_MESSAGECALLBACKS_H_ */