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"
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
,
52 &stream_player_module
,
56 ¶metric_eq_module
,
62 &feedback_reducer_module
,
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" };
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)
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
))
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
);
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
);
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
;
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
;
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
);
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
);
158 engine
= cbox_config_get_string(section
, "engine");
161 g_set_error(error
, CBOX_MODULE_ERROR
, CBOX_MODULE_ERROR_FAILED
, "FX engine not specified for preset '%s'", name
);
164 mptr
= cbox_module_manifest_get_by_name(engine
);
167 g_set_error(error
, CBOX_MODULE_ERROR
, CBOX_MODULE_ERROR_FAILED
, "FX preset '%s' refers to non-existing engine '%s'", name
, engine
);
170 effect
= cbox_module_manifest_create_module(mptr
, section
, doc
, rt
, name
, error
);
173 cbox_force_error(error
);
174 g_prefix_error(error
, "Could not instantiate FX preset '%s': ", name
);
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
))
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)))
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
);
205 cbox_rt_swap_pointers(rt
, (void **)psm
, effect
);
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));
216 g_set_error(error
, CBOX_MODULE_ERROR
, CBOX_MODULE_ERROR_FAILED
, "No effect engine '%s'", CBOX_ARG_S(cmd
, 0));
219 effect
= cbox_module_manifest_create_module(manifest
, NULL
, doc
, rt
, "unnamed", error
);
223 cbox_rt_swap_pointers(rt
, (void **)psm
, effect
);
226 if (!strncmp(subcmd
, "/engine/", 8))
230 g_set_error(error
, CBOX_MODULE_ERROR
, CBOX_MODULE_ERROR_FAILED
, "No engine on module in path '%s'", cmd
->command
);
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
);
238 return cbox_execute_sub(&sm
->cmd_target
, fb
, cmd
, subcmd
+ 7, error
);
240 if (!strcmp(subcmd
, "/set_bypass") && !strcmp(cmd
->arg_types
, "i"))
244 g_set_error(error
, CBOX_MODULE_ERROR
, CBOX_MODULE_ERROR_FAILED
, "No engine on module in path '%s'", cmd
->command
);
247 sm
->bypass
= CBOX_ARG_I(cmd
, 0);
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
);
265 module
->destroy(module
);