Merge pull request #1 from atsampson/master
[calfbox.git] / rt.h
blob498bd486372900de72e71c735645d01b2b6711dc
1 /*
2 Calf Box, an open source musical instrument.
3 Copyright (C) 2010-2013 Krzysztof Foltman
5 This program is free software: you can redistribute it and/or modify
6 it under the terms of the GNU General Public License as published by
7 the Free Software Foundation, either version 3 of the License, or
8 (at your option) any later version.
10 This program is distributed in the hope that it will be useful,
11 but WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 GNU General Public License for more details.
15 You should have received a copy of the GNU General Public License
16 along with this program. If not, see <http://www.gnu.org/licenses/>.
19 #ifndef CBOX_RT_H
20 #define CBOX_RT_H
22 #include <stdint.h>
24 #include "cmd.h"
25 #include "dom.h"
26 #include "fifo.h"
27 #include "ioenv.h"
28 #include "midi.h"
29 #include "mididest.h"
31 #define RT_CMD_QUEUE_ITEMS 1024
32 #define RT_MAX_COST_PER_CALL 100
34 struct cbox_instruments;
35 struct cbox_scene;
36 struct cbox_io;
37 struct cbox_midi_pattern;
38 struct cbox_song;
39 struct cbox_rt_cmd_instance;
41 struct cbox_rt_cmd_definition
43 int (*prepare)(void *user_data); // non-zero to skip the whole thing
44 int (*execute)(void *user_data); // returns cost
45 void (*cleanup)(void *user_data);
48 CBOX_EXTERN_CLASS(cbox_rt)
50 struct cbox_rt
52 CBOX_OBJECT_HEADER()
54 struct cbox_io *io;
55 struct cbox_io_callbacks *cbs;
57 struct cbox_fifo *rb_execute, *rb_cleanup;
59 struct cbox_command_target cmd_target;
60 int started, disconnected;
61 struct cbox_io_env io_env;
62 struct cbox_engine *engine;
65 extern struct cbox_rt *cbox_rt_new(struct cbox_document *doc);
67 extern void cbox_rt_set_io(struct cbox_rt *rt, struct cbox_io *io);
68 extern void cbox_rt_set_offline(struct cbox_rt *rt, int sample_rate, int buffer_size);
69 extern void cbox_rt_start(struct cbox_rt *rt, struct cbox_command_target *fb);
70 extern void cbox_rt_handle_cmd_queue(struct cbox_rt *rt);
71 // This one should be called from RT thread process function to execute the queued RT commands
72 extern void cbox_rt_handle_rt_commands(struct cbox_rt *rt);
73 extern void cbox_rt_stop(struct cbox_rt *rt);
75 // Those are for calling from the main thread. I will add a RT-thread version later.
76 extern void cbox_rt_execute_cmd_sync(struct cbox_rt *rt, struct cbox_rt_cmd_definition *cmd, void *user_data);
77 extern void cbox_rt_execute_cmd_async(struct cbox_rt *rt, struct cbox_rt_cmd_definition *cmd, void *user_data);
78 extern void *cbox_rt_swap_pointers(struct cbox_rt *rt, void **ptr, void *new_value);
79 extern void *cbox_rt_swap_pointers_and_update_count(struct cbox_rt *rt, void **ptr, void *new_value, int *pcount, int new_count);
81 extern void cbox_rt_array_insert(struct cbox_rt *rt, void ***ptr, int *pcount, int index, void *new_value);
82 extern void *cbox_rt_array_remove(struct cbox_rt *rt, void ***ptr, int *pcount, int index);
83 extern gboolean cbox_rt_array_remove_by_value(struct cbox_rt *rt, void ***ptr, int *pcount, void *value_to_remove);
84 extern struct cbox_midi_merger *cbox_rt_get_midi_output(struct cbox_rt *rt, struct cbox_uuid *uuid);
86 ///////////////////////////////////////////////////////////////////////////////
88 #define GET_RT_FROM_cbox_rt(ptr) (ptr)
89 #define RT_FUNC_ARG_MEMBER(type, name) type name;
90 #define RT_FUNC_ARG_LIST(type, name) , type name
91 #define RT_FUNC_ARG_PASS(type, name) _args.name = name;
92 #define RT_FUNC_ARG_PASS2(type, name) , _args.name
93 #define RT_FUNC_ARG_PASS3(type, name) , _args->name
94 #define RT_FUNC_ARG_PASS4(type, name) , name
95 #define DEFINE_RT_FUNC(restype, objtype, argname, name) \
96 struct rt_function_args_##name { \
97 struct objtype *_obj; \
98 restype _result; \
99 name##_args(RT_FUNC_ARG_MEMBER) \
100 }; \
101 static restype RT_IMPL_##name(struct objtype *_obj, int *_cost name##_args(RT_FUNC_ARG_LIST)); \
102 int exec_##name(void *user_data) { \
103 int cost = 1; \
104 struct rt_function_args_##name *_args = user_data;\
105 _args->_result = RT_IMPL_##name(_args->_obj, &cost name##_args(RT_FUNC_ARG_PASS3)); \
106 return cost; \
108 restype name(struct objtype *_obj name##_args(RT_FUNC_ARG_LIST)) \
110 struct cbox_rt *rt = GET_RT_FROM_##objtype(_obj); \
111 if (rt) { \
112 struct rt_function_args_##name _args; \
113 static struct cbox_rt_cmd_definition _cmd = { .prepare = NULL, .execute = exec_##name, .cleanup = NULL }; \
114 _args._obj = _obj; \
115 name##_args(RT_FUNC_ARG_PASS) \
116 cbox_rt_execute_cmd_sync(rt, &_cmd, &_args); \
117 return _args._result; \
118 } else { \
119 int cost; \
120 restype _result; \
121 do { \
122 cost = 1; \
123 _result = RT_IMPL_##name(_obj, &cost name##_args(RT_FUNC_ARG_PASS4)); \
124 } while(!cost); \
125 return _result; \
128 restype RT_IMPL_##name(struct objtype *argname, int *_cost name##_args(RT_FUNC_ARG_LIST))
130 #define DEFINE_RT_VOID_FUNC(objtype, argname, name) \
131 struct rt_function_args_##name { \
132 struct objtype *_obj; \
133 name##_args(RT_FUNC_ARG_MEMBER) \
134 }; \
135 static void RT_IMPL_##name(struct objtype *_obj, int *_cost name##_args(RT_FUNC_ARG_LIST)); \
136 int exec_##name(void *user_data) { \
137 int cost = 1; \
138 struct rt_function_args_##name *_args = user_data;\
139 RT_IMPL_##name(_args->_obj, &cost name##_args(RT_FUNC_ARG_PASS3)); \
140 return cost; \
142 void name(struct objtype *_obj name##_args(RT_FUNC_ARG_LIST)) \
144 struct cbox_rt *rt = GET_RT_FROM_##objtype(_obj); \
145 if (rt) { \
146 struct rt_function_args_##name _args = { ._obj = _obj }; \
147 static struct cbox_rt_cmd_definition _cmd = { .prepare = NULL, .execute = exec_##name, .cleanup = NULL }; \
148 name##_args(RT_FUNC_ARG_PASS) \
149 cbox_rt_execute_cmd_sync(rt, &_cmd, &_args); \
150 } else { \
151 int cost; \
152 do { \
153 cost = 1; \
154 RT_IMPL_##name(_obj, &cost name##_args(RT_FUNC_ARG_PASS4)); \
155 } while(!cost); \
158 void RT_IMPL_##name(struct objtype *argname, int *_cost name##_args(RT_FUNC_ARG_LIST))
160 #define RT_CALL_AGAIN_LATER() ((*_cost) = 0)
161 #define RT_SET_COST(n) ((*_cost) = (n))
163 #endif