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/>.
20 #include "config-api.h"
32 extern struct cbox_module_manifest sampler_module
;
33 extern struct cbox_module_manifest fluidsynth_module
;
34 extern struct cbox_module_manifest tonewheel_organ_module
;
35 extern struct cbox_module_manifest stream_player_module
;
36 extern struct cbox_module_manifest tone_control_module
;
37 extern struct cbox_module_manifest delay_module
;
38 extern struct cbox_module_manifest reverb_module
;
39 extern struct cbox_module_manifest parametric_eq_module
;
40 extern struct cbox_module_manifest phaser_module
;
41 extern struct cbox_module_manifest chorus_module
;
42 extern struct cbox_module_manifest fxchain_module
;
43 extern struct cbox_module_manifest jack_input_module
;
44 extern struct cbox_module_manifest feedback_reducer_module
;
45 extern struct cbox_module_manifest compressor_module
;
46 extern struct cbox_module_manifest gate_module
;
47 extern struct cbox_module_manifest distortion_module
;
48 extern struct cbox_module_manifest fuzz_module
;
50 struct cbox_module_manifest
*cbox_module_list
[] = {
51 &tonewheel_organ_module
,
53 &stream_player_module
,
57 ¶metric_eq_module
,
63 &feedback_reducer_module
,
71 CBOX_CLASS_DEFINITION_ROOT(cbox_module
)
73 void cbox_module_manifest_dump(struct cbox_module_manifest
*manifest
)
75 static const char *ctl_classes
[] = { "Switch CC#", "Continuous CC#", "Cont. Param", "Discrete Param", "Enum" };
77 printf("Module: %s\n", manifest
->name
);
78 printf("Audio I/O: min %d inputs, min %d outputs\n", manifest
->min_inputs
, manifest
->min_outputs
);
80 printf("Live controllers:\n");
81 printf("Ch# Type Number Name \n");
82 printf("---- --------------- ------ ------------------------------\n");
83 for (i
= 0; i
< manifest
->num_live_controllers
; i
++)
85 struct cbox_module_livecontroller_metadata
*lc
= &manifest
->live_controllers
[i
];
86 if (lc
->channel
== 255)
92 printf("%-4d ", lc
->channel
);
93 printf("%15s %-6d %-30s\n", ctl_classes
[lc
->controller_class
], lc
->controller
, lc
->name
);
97 struct cbox_module_manifest
*cbox_module_manifest_get_by_name(const char *name
)
99 struct cbox_module_manifest
**mptr
;
101 for (mptr
= cbox_module_list
; *mptr
; mptr
++)
103 if (!strcmp((*mptr
)->name
, name
))
109 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
, struct cbox_engine
*engine
, const char *instance_name
, GError
**error
)
111 g_clear_error(error
);
112 struct cbox_module
*module
= manifest
->create(manifest
->user_data
, cfg_section
, doc
, rt
, engine
, error
);
116 module
->instance_name
= g_strdup(instance_name
);
117 module
->input_samples
= malloc(sizeof(float) * CBOX_BLOCK_SIZE
* module
->inputs
);
118 module
->output_samples
= malloc(sizeof(float) * CBOX_BLOCK_SIZE
* module
->outputs
);
119 module
->engine_name
= manifest
->name
;
120 cbox_midi_buffer_init(&module
->midi_input
);
125 void cbox_module_init(struct cbox_module
*module
, struct cbox_document
*doc
, struct cbox_rt
*rt
, struct cbox_engine
*engine
, void *user_data
, int inputs
, int outputs
, cbox_process_cmd cmd_handler
, void (*destroy
)(struct cbox_module
*module
))
127 CBOX_OBJECT_HEADER_INIT(module
, cbox_module
, doc
);
128 module
->user_data
= user_data
;
130 module
->engine
= engine
;
131 module
->instance_name
= NULL
;
132 module
->input_samples
= NULL
;
133 module
->output_samples
= NULL
;
134 module
->inputs
= inputs
;
135 module
->outputs
= outputs
;
136 module
->aux_offset
= outputs
;
138 module
->srate
= engine
->io_env
.srate
;
139 module
->srate_inv
= 1.0 / module
->srate
;
141 cbox_command_target_init(&module
->cmd_target
, cmd_handler
, module
);
142 module
->process_event
= NULL
;
143 module
->process_block
= NULL
;
144 module
->destroy
= destroy
;
145 CBOX_OBJECT_REGISTER(module
);
148 struct cbox_module
*cbox_module_new_from_fx_preset(const char *name
, struct cbox_document
*doc
, struct cbox_rt
*rt
, struct cbox_engine
*engine
, GError
**error
)
150 gchar
*section
= g_strdup_printf("fxpreset:%s", name
);
151 const char *engine_name
;
152 struct cbox_module_manifest
*mptr
;
153 struct cbox_module
*effect
;
155 if (!cbox_config_has_section(section
))
157 g_set_error(error
, CBOX_MODULE_ERROR
, CBOX_MODULE_ERROR_FAILED
, "No FX preset called '%s'", name
);
160 engine_name
= cbox_config_get_string(section
, "engine");
163 g_set_error(error
, CBOX_MODULE_ERROR
, CBOX_MODULE_ERROR_FAILED
, "FX engine not specified for preset '%s'", name
);
166 mptr
= cbox_module_manifest_get_by_name(engine_name
);
169 g_set_error(error
, CBOX_MODULE_ERROR
, CBOX_MODULE_ERROR_FAILED
, "FX preset '%s' refers to non-existing engine '%s'", name
, engine_name
);
172 effect
= cbox_module_manifest_create_module(mptr
, section
, doc
, rt
, engine
, name
, error
);
175 cbox_force_error(error
);
176 g_prefix_error(error
, "Could not instantiate FX preset '%s': ", name
);
187 gboolean
cbox_module_slot_process_cmd(struct cbox_module
**psm
,
188 struct cbox_command_target
*fb
, struct cbox_osc_command
*cmd
, const char *subcmd
,
189 struct cbox_document
*doc
, struct cbox_rt
*rt
, struct cbox_engine
*engine
, GError
**error
)
191 struct cbox_module
*sm
= *psm
;
192 if (!strcmp(subcmd
, "/status") && !strcmp(cmd
->arg_types
, ""))
194 if (!cbox_check_fb_channel(fb
, cmd
->command
, error
))
196 if (!(cbox_execute_on(fb
, NULL
, "/insert_engine", "s", error
, sm
? sm
->engine_name
: "") &&
197 cbox_execute_on(fb
, NULL
, "/insert_preset", "s", error
, sm
? sm
->instance_name
: "") &&
198 cbox_execute_on(fb
, NULL
, "/bypass", "i", error
, sm
? sm
->bypass
: 0)))
202 if (!strcmp(subcmd
, "/insert_preset") && !strcmp(cmd
->arg_types
, "s"))
204 struct cbox_module
*effect
= cbox_module_new_from_fx_preset(CBOX_ARG_S(cmd
, 0), doc
, rt
, engine
, error
);
207 cbox_rt_swap_pointers(rt
, (void **)psm
, effect
);
210 if (!strcmp(subcmd
, "/insert_engine") && !strcmp(cmd
->arg_types
, "s"))
212 struct cbox_module
*effect
= NULL
;
213 if (*CBOX_ARG_S(cmd
, 0))
215 struct cbox_module_manifest
*manifest
= cbox_module_manifest_get_by_name(CBOX_ARG_S(cmd
, 0));
218 g_set_error(error
, CBOX_MODULE_ERROR
, CBOX_MODULE_ERROR_FAILED
, "No effect engine '%s'", CBOX_ARG_S(cmd
, 0));
221 effect
= cbox_module_manifest_create_module(manifest
, NULL
, doc
, rt
, engine
, "unnamed", error
);
225 cbox_rt_swap_pointers(rt
, (void **)psm
, effect
);
228 if (!strncmp(subcmd
, "/engine/", 8))
232 g_set_error(error
, CBOX_MODULE_ERROR
, CBOX_MODULE_ERROR_FAILED
, "No engine on module in path '%s'", cmd
->command
);
235 if (!sm
->cmd_target
.process_cmd
)
237 g_set_error(error
, CBOX_MODULE_ERROR
, CBOX_MODULE_ERROR_FAILED
, "The engine %s has no command target defined", sm
->engine_name
);
240 return cbox_execute_sub(&sm
->cmd_target
, fb
, cmd
, subcmd
+ 7, error
);
242 if (!strcmp(subcmd
, "/set_bypass") && !strcmp(cmd
->arg_types
, "i"))
246 g_set_error(error
, CBOX_MODULE_ERROR
, CBOX_MODULE_ERROR_FAILED
, "No engine on module in path '%s'", cmd
->command
);
249 sm
->bypass
= CBOX_ARG_I(cmd
, 0);
252 return cbox_object_default_process_cmd(&sm
->cmd_target
, fb
, cmd
, error
);
255 void cbox_module_swap_pointers_and_free(struct cbox_module
*sm
, void **pptr
, void *value
)
257 free(cbox_rt_swap_pointers(sm
->rt
, pptr
, value
));
260 void cbox_module_destroyfunc(struct cbox_objhdr
*hdr
)
262 struct cbox_module
*module
= CBOX_H2O(hdr
);
263 g_free(module
->instance_name
);
264 free(module
->input_samples
);
265 free(module
->output_samples
);
267 module
->destroy(module
);