Fix more warnings. Use -Wall flag to enable those warnings to show up in first place.
[calfbox.git] / module.c
blob03a8f99f0844a937d12fdafa88aafa0df6f6bd22
1 /*
2 Calf Box, an open source musical instrument.
3 Copyright (C) 2010-2011 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 #include "cmd.h"
20 #include "config-api.h"
21 #include "module.h"
22 #include "rt.h"
24 #include <assert.h>
25 #include <glib.h>
26 #include <stdarg.h>
27 #include <stdio.h>
28 #include <stdlib.h>
29 #include <string.h>
31 extern struct cbox_module_manifest sampler_module;
32 extern struct cbox_module_manifest fluidsynth_module;
33 extern struct cbox_module_manifest tonewheel_organ_module;
34 extern struct cbox_module_manifest stream_player_module;
35 extern struct cbox_module_manifest tone_control_module;
36 extern struct cbox_module_manifest delay_module;
37 extern struct cbox_module_manifest reverb_module;
38 extern struct cbox_module_manifest parametric_eq_module;
39 extern struct cbox_module_manifest phaser_module;
40 extern struct cbox_module_manifest chorus_module;
41 extern struct cbox_module_manifest fxchain_module;
42 extern struct cbox_module_manifest jack_input_module;
43 extern struct cbox_module_manifest feedback_reducer_module;
44 extern struct cbox_module_manifest compressor_module;
45 extern struct cbox_module_manifest gate_module;
46 extern struct cbox_module_manifest distortion_module;
47 extern struct cbox_module_manifest fuzz_module;
49 struct cbox_module_manifest *cbox_module_list[] = {
50 &tonewheel_organ_module,
51 &fluidsynth_module,
52 &stream_player_module,
53 &tone_control_module,
54 &delay_module,
55 &reverb_module,
56 &parametric_eq_module,
57 &phaser_module,
58 &chorus_module,
59 &sampler_module,
60 &fxchain_module,
61 &jack_input_module,
62 &feedback_reducer_module,
63 &compressor_module,
64 &gate_module,
65 &distortion_module,
66 &fuzz_module,
67 NULL
70 CBOX_CLASS_DEFINITION_ROOT(cbox_module)
72 void cbox_module_manifest_dump(struct cbox_module_manifest *manifest)
74 static const char *ctl_classes[] = { "Switch CC#", "Continuous CC#", "Cont. Param", "Discrete Param", "Enum" };
75 int i = 0;
76 printf("Module: %s\n", manifest->name);
77 printf("Audio I/O: min %d inputs, min %d outputs\n", manifest->min_inputs, manifest->min_outputs);
79 printf("Live controllers:\n");
80 printf("Ch# Type Number Name \n");
81 printf("---- --------------- ------ ------------------------------\n");
82 for (i = 0; i < manifest->num_live_controllers; i++)
84 struct cbox_module_livecontroller_metadata *lc = &manifest->live_controllers[i];
85 if (lc->channel == 255)
86 printf("ALL ");
87 else
88 if (!lc->channel)
89 printf("ANY ");
90 else
91 printf("%-4d ", lc->channel);
92 printf("%15s %-6d %-30s\n", ctl_classes[lc->controller_class], lc->controller, lc->name);
96 struct cbox_module_manifest *cbox_module_manifest_get_by_name(const char *name)
98 struct cbox_module_manifest **mptr;
100 for (mptr = cbox_module_list; *mptr; mptr++)
102 if (!strcmp((*mptr)->name, name))
103 return *mptr;
105 return NULL;
108 struct cbox_module *cbox_module_manifest_create_module(struct cbox_module_manifest *manifest, const char *cfg_section, struct cbox_document *doc, struct cbox_rt *rt, const char *instance_name, GError **error)
110 g_clear_error(error);
111 struct cbox_module *module = manifest->create(manifest->user_data, cfg_section, doc, rt, error);
112 if (!module)
113 return NULL;
115 module->instance_name = g_strdup(instance_name);
116 module->input_samples = malloc(sizeof(float) * CBOX_BLOCK_SIZE * module->inputs);
117 module->output_samples = malloc(sizeof(float) * CBOX_BLOCK_SIZE * module->outputs);
118 module->engine_name = manifest->name;
119 cbox_midi_buffer_init(&module->midi_input);
121 return module;
124 void cbox_module_init(struct cbox_module *module, struct cbox_document *doc, struct cbox_rt *rt, void *user_data, int inputs, int outputs, cbox_process_cmd cmd_handler, void (*destroy)(struct cbox_module *module))
126 CBOX_OBJECT_HEADER_INIT(module, cbox_module, doc);
127 module->user_data = user_data;
128 module->rt = rt;
129 module->instance_name = NULL;
130 module->input_samples = NULL;
131 module->output_samples = NULL;
132 module->inputs = inputs;
133 module->outputs = outputs;
134 module->aux_offset = outputs;
135 module->bypass = 0;
136 module->srate = cbox_rt_get_sample_rate(rt);
137 module->srate_inv = 1.0 / module->srate;
139 cbox_command_target_init(&module->cmd_target, cmd_handler, module);
140 module->process_event = NULL;
141 module->process_block = NULL;
142 module->destroy = destroy;
143 CBOX_OBJECT_REGISTER(module);
146 struct cbox_module *cbox_module_new_from_fx_preset(const char *name, struct cbox_document *doc, struct cbox_rt *rt, GError **error)
148 gchar *section = g_strdup_printf("fxpreset:%s", name);
149 const char *engine;
150 struct cbox_module_manifest *mptr;
151 struct cbox_module *effect;
153 if (!cbox_config_has_section(section))
155 g_set_error(error, CBOX_MODULE_ERROR, CBOX_MODULE_ERROR_FAILED, "No FX preset called '%s'", name);
156 goto fxpreset_error;
158 engine = cbox_config_get_string(section, "engine");
159 if (!engine)
161 g_set_error(error, CBOX_MODULE_ERROR, CBOX_MODULE_ERROR_FAILED, "FX engine not specified for preset '%s'", name);
162 goto fxpreset_error;
164 mptr = cbox_module_manifest_get_by_name(engine);
165 if (!mptr)
167 g_set_error(error, CBOX_MODULE_ERROR, CBOX_MODULE_ERROR_FAILED, "FX preset '%s' refers to non-existing engine '%s'", name, engine);
168 goto fxpreset_error;
170 effect = cbox_module_manifest_create_module(mptr, section, doc, rt, name, error);
171 if (!effect)
173 cbox_force_error(error);
174 g_prefix_error(error, "Could not instantiate FX preset '%s': ", name);
175 goto fxpreset_error;
177 g_free(section);
178 return effect;
180 fxpreset_error:
181 g_free(section);
182 return NULL;
185 gboolean cbox_module_slot_process_cmd(struct cbox_module **psm,
186 struct cbox_command_target *fb, struct cbox_osc_command *cmd, const char *subcmd,
187 struct cbox_document *doc, struct cbox_rt *rt, GError **error)
189 struct cbox_module *sm = *psm;
190 if (!strcmp(subcmd, "/status") && !strcmp(cmd->arg_types, ""))
192 if (!cbox_check_fb_channel(fb, cmd->command, error))
193 return FALSE;
194 if (!(cbox_execute_on(fb, NULL, "/insert_engine", "s", error, sm ? sm->engine_name : "") &&
195 cbox_execute_on(fb, NULL, "/insert_preset", "s", error, sm ? sm->instance_name : "") &&
196 cbox_execute_on(fb, NULL, "/bypass", "i", error, sm ? sm->bypass : 0)))
197 return FALSE;
198 return TRUE;
200 if (!strcmp(subcmd, "/insert_preset") && !strcmp(cmd->arg_types, "s"))
202 struct cbox_module *effect = cbox_module_new_from_fx_preset(CBOX_ARG_S(cmd, 0), doc, rt, error);
203 if (!effect)
204 return FALSE;
205 cbox_rt_swap_pointers(rt, (void **)psm, effect);
206 return TRUE;
208 if (!strcmp(subcmd, "/insert_engine") && !strcmp(cmd->arg_types, "s"))
210 struct cbox_module *effect = NULL;
211 if (*CBOX_ARG_S(cmd, 0))
213 struct cbox_module_manifest *manifest = cbox_module_manifest_get_by_name(CBOX_ARG_S(cmd, 0));
214 if (!manifest)
216 g_set_error(error, CBOX_MODULE_ERROR, CBOX_MODULE_ERROR_FAILED, "No effect engine '%s'", CBOX_ARG_S(cmd, 0));
217 return FALSE;
219 effect = cbox_module_manifest_create_module(manifest, NULL, doc, rt, "unnamed", error);
220 if (!effect)
221 return FALSE;
223 cbox_rt_swap_pointers(rt, (void **)psm, effect);
224 return TRUE;
226 if (!strncmp(subcmd, "/engine/", 8))
228 if (!sm)
230 g_set_error(error, CBOX_MODULE_ERROR, CBOX_MODULE_ERROR_FAILED, "No engine on module in path '%s'", cmd->command);
231 return FALSE;
233 if (!sm->cmd_target.process_cmd)
235 g_set_error(error, CBOX_MODULE_ERROR, CBOX_MODULE_ERROR_FAILED, "The engine %s has no command target defined", sm->engine_name);
236 return FALSE;
238 return cbox_execute_sub(&sm->cmd_target, fb, cmd, subcmd + 7, error);
240 if (!strcmp(subcmd, "/set_bypass") && !strcmp(cmd->arg_types, "i"))
242 if (!sm)
244 g_set_error(error, CBOX_MODULE_ERROR, CBOX_MODULE_ERROR_FAILED, "No engine on module in path '%s'", cmd->command);
245 return FALSE;
247 sm->bypass = CBOX_ARG_I(cmd, 0);
248 return TRUE;
250 return cbox_object_default_process_cmd(&sm->cmd_target, fb, cmd, error);
253 void cbox_module_swap_pointers_and_free(struct cbox_module *sm, void **pptr, void *value)
255 free(cbox_rt_swap_pointers(sm->rt, pptr, value));
258 void cbox_module_destroyfunc(struct cbox_objhdr *hdr)
260 struct cbox_module *module = CBOX_H2O(hdr);
261 g_free(module->instance_name);
262 free(module->input_samples);
263 free(module->output_samples);
264 if (module->destroy)
265 module->destroy(module);
266 free(module);