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"
28 CBOX_CLASS_DEFINITION_ROOT(cbox_instrument
)
30 static gboolean
cbox_instrument_output_process_cmd(struct cbox_instrument
*instr
, struct cbox_instrument_output
*output
, struct cbox_command_target
*fb
, struct cbox_osc_command
*cmd
, const char *subcmd
, GError
**error
)
32 if (!strcmp(subcmd
, "/status") && !strcmp(cmd
->arg_types
, ""))
34 if (!(cbox_execute_on(fb
, NULL
, "/gain_linear", "f", error
, output
->gain
) &&
35 cbox_execute_on(fb
, NULL
, "/gain", "f", error
, gain2dB_simple(output
->gain
)) &&
36 cbox_execute_on(fb
, NULL
, "/output", "i", error
, output
->output_bus
+ 1)))
38 return cbox_module_slot_process_cmd(&output
->insert
, fb
, cmd
, subcmd
, CBOX_GET_DOCUMENT(instr
->scene
), instr
->scene
->rt
, instr
->scene
->engine
, error
);
40 if (!strcmp(subcmd
, "/gain") && !strcmp(cmd
->arg_types
, "f"))
42 output
->gain
= dB2gain_simple(CBOX_ARG_F(cmd
, 0));
45 if (!strcmp(subcmd
, "/output") && !strcmp(cmd
->arg_types
, "i"))
47 int obus
= CBOX_ARG_I(cmd
, 0);
48 // XXXKF add error checking
49 output
->output_bus
= obus
- 1;
52 if (!strncmp(subcmd
, "/rec_dry/", 9))
53 return cbox_execute_sub(&output
->rec_dry
.cmd_target
, fb
, cmd
, subcmd
+ 8, error
);
54 if (!strncmp(subcmd
, "/rec_wet/", 9))
55 return cbox_execute_sub(&output
->rec_wet
.cmd_target
, fb
, cmd
, subcmd
+ 8, error
);
56 return cbox_module_slot_process_cmd(&output
->insert
, fb
, cmd
, subcmd
, CBOX_GET_DOCUMENT(instr
->scene
), instr
->scene
->rt
, instr
->scene
->engine
, error
);
59 static gboolean
cbox_instrument_aux_process_cmd(struct cbox_instrument
*instr
, struct cbox_instrument_output
*output
, int id
, struct cbox_command_target
*fb
, struct cbox_osc_command
*cmd
, const char *subcmd
, GError
**error
)
61 if (!strcmp(subcmd
, "/status") && !strcmp(cmd
->arg_types
, ""))
63 if (!cbox_check_fb_channel(fb
, cmd
->command
, error
))
65 if (!(cbox_execute_on(fb
, NULL
, "/gain_linear", "f", error
, output
->gain
) &&
66 cbox_execute_on(fb
, NULL
, "/gain", "f", error
, gain2dB_simple(output
->gain
)) &&
67 cbox_execute_on(fb
, NULL
, "/bus", "s", error
, instr
->aux_output_names
[id
] ? instr
->aux_output_names
[id
] : "")))
69 return cbox_module_slot_process_cmd(&output
->insert
, fb
, cmd
, subcmd
, CBOX_GET_DOCUMENT(instr
->scene
), instr
->scene
->rt
, instr
->scene
->engine
, error
);
71 else if (!strcmp(subcmd
, "/bus") && !strcmp(cmd
->arg_types
, "s"))
73 struct cbox_scene
*scene
= instr
->scene
;
74 if (!CBOX_ARG_S(cmd
, 0))
76 struct cbox_aux_bus
*old_bus
= cbox_rt_swap_pointers(instr
->module
->rt
, (void **)&instr
->aux_outputs
[id
], NULL
);
78 cbox_aux_bus_unref(old_bus
);
81 for (int i
= 0; i
< scene
->aux_bus_count
; i
++)
83 if (!scene
->aux_buses
[i
])
85 if (!strcmp(scene
->aux_buses
[i
]->name
, CBOX_ARG_S(cmd
, 0)))
87 g_free(instr
->aux_output_names
[id
]);
88 instr
->aux_output_names
[id
] = g_strdup(scene
->aux_buses
[i
]->name
);
89 cbox_aux_bus_ref(scene
->aux_buses
[i
]);
90 struct cbox_aux_bus
*old_bus
= cbox_rt_swap_pointers(instr
->module
->rt
, (void **)&instr
->aux_outputs
[id
], scene
->aux_buses
[i
]);
92 cbox_aux_bus_unref(old_bus
);
96 g_set_error(error
, CBOX_MODULE_ERROR
, CBOX_MODULE_ERROR_FAILED
, "Unknown aux bus: %s", CBOX_ARG_S(cmd
, 0));
99 else if (!strcmp(subcmd
, "/output") && !strcmp(cmd
->arg_types
, "i")) // not supported
101 cbox_set_command_error(error
, cmd
);
104 else // otherwise, treat just like an command on normal (non-aux) output
105 return cbox_instrument_output_process_cmd(instr
, output
, fb
, cmd
, subcmd
, error
);
108 gboolean
cbox_instrument_process_cmd(struct cbox_command_target
*ct
, struct cbox_command_target
*fb
, struct cbox_osc_command
*cmd
, GError
**error
)
110 struct cbox_instrument
*instr
= ct
->user_data
;
111 const char *subcommand
= NULL
;
113 int aux_offset
= instr
->module
->aux_offset
/ 2;
114 if (!strcmp(cmd
->command
, "/status") && !strcmp(cmd
->arg_types
, ""))
116 if (!cbox_check_fb_channel(fb
, cmd
->command
, error
))
118 if (!cbox_execute_on(fb
, NULL
, "/engine", "s", error
, instr
->module
->engine_name
))
120 if (!cbox_execute_on(fb
, NULL
, "/aux_offset", "i", error
, instr
->module
->aux_offset
/ 2 + 1))
122 if (!cbox_execute_on(fb
, NULL
, "/outputs", "i", error
, instr
->module
->outputs
/ 2))
124 return CBOX_OBJECT_DEFAULT_STATUS(instr
, fb
, error
);
126 else if (cbox_parse_path_part_int(cmd
, "/output/", &subcommand
, &index
, 1, aux_offset
, error
))
130 if (index
< 1 || index
> 1 + instr
->module
->aux_offset
)
132 g_set_error(error
, CBOX_MODULE_ERROR
, CBOX_MODULE_ERROR_FAILED
, "Invalid position %d (valid are 1..%d)", index
, instr
->module
->aux_offset
);
135 return cbox_instrument_output_process_cmd(instr
, &instr
->outputs
[index
- 1], fb
, cmd
, subcommand
, error
);
137 else if (cbox_parse_path_part_int(cmd
, "/aux/", &subcommand
, &index
, 1, instr
->aux_output_count
, error
))
141 int acount
= 1 + instr
->module
->outputs
- instr
->module
->aux_offset
;
142 if (index
< 1 || index
> acount
)
144 g_set_error(error
, CBOX_MODULE_ERROR
, CBOX_MODULE_ERROR_FAILED
, "Invalid position %d (valid are 1..%d)", index
, acount
);
147 return cbox_instrument_aux_process_cmd(instr
, &instr
->outputs
[aux_offset
+ index
- 1], index
- 1, fb
, cmd
, subcommand
, error
);
150 if (!strncmp(cmd
->command
, "/engine/",8))
152 if (!instr
->module
->cmd_target
.process_cmd
)
154 g_set_error(error
, CBOX_MODULE_ERROR
, CBOX_MODULE_ERROR_FAILED
, "The engine %s has no command target defined", instr
->module
->engine_name
);
157 return cbox_execute_sub(&instr
->module
->cmd_target
, fb
, cmd
, cmd
->command
+ 7, error
);
159 else if (!strcmp(cmd
->command
, "/move_to") && !strcmp(cmd
->arg_types
, "si"))
161 struct cbox_scene
*new_scene
= (struct cbox_scene
*)CBOX_ARG_O(cmd
, 0, instr
->scene
, cbox_scene
, error
);
164 int dstpos
= CBOX_ARG_I(cmd
, 1) - 1;
166 if (dstpos
< 0 || dstpos
> new_scene
->layer_count
)
168 g_set_error(error
, CBOX_MODULE_ERROR
, CBOX_MODULE_ERROR_FAILED
, "Invalid position %d (valid are 1..%d or 0 for append)", dstpos
+ 1, 1 + new_scene
->layer_count
);
172 return cbox_scene_move_instrument_to(instr
->scene
, instr
, new_scene
, dstpos
, error
);
175 return cbox_object_default_process_cmd(ct
, fb
, cmd
, error
);
178 void cbox_instrument_destroy_if_unused(struct cbox_instrument
*instrument
)
180 if (instrument
->refcount
== 0)
181 CBOX_DELETE(instrument
);
184 void cbox_instrument_destroyfunc(struct cbox_objhdr
*objhdr
)
186 struct cbox_instrument
*instrument
= CBOX_H2O(objhdr
);
187 assert(instrument
->refcount
== 0);
188 for (int i
= 0; i
< instrument
->module
->outputs
/ 2; i
++)
190 cbox_instrument_output_uninit(&instrument
->outputs
[i
]);
192 free(instrument
->outputs
);
193 for (int i
= 0; i
< instrument
->aux_output_count
; i
++)
195 g_free(instrument
->aux_output_names
[i
]);
197 free(instrument
->aux_output_names
);
198 free(instrument
->aux_outputs
);
199 CBOX_DELETE(instrument
->module
);
203 void cbox_instrument_unref_aux_buses(struct cbox_instrument
*instrument
)
205 for (int j
= 0; j
< instrument
->aux_output_count
; j
++)
207 if (instrument
->aux_outputs
[j
])
208 cbox_aux_bus_unref(instrument
->aux_outputs
[j
]);
212 void cbox_instrument_disconnect_aux_bus(struct cbox_instrument
*instrument
, struct cbox_aux_bus
*bus
)
214 for (int j
= 0; j
< instrument
->aux_output_count
; j
++)
216 if (instrument
->aux_outputs
[j
] == bus
)
218 cbox_aux_bus_unref(instrument
->aux_outputs
[j
]);
219 instrument
->aux_outputs
[j
] = NULL
;
224 void cbox_instrument_output_init(struct cbox_instrument_output
*output
, struct cbox_scene
*scene
, uint32_t max_numsamples
)
226 cbox_recording_source_init(&output
->rec_dry
, scene
, max_numsamples
, 2);
227 cbox_recording_source_init(&output
->rec_wet
, scene
, max_numsamples
, 2);
228 output
->insert
= NULL
;
229 output
->output_bus
= 0;
234 void cbox_instrument_output_uninit(struct cbox_instrument_output
*output
)
236 cbox_recording_source_uninit(&output
->rec_dry
);
237 cbox_recording_source_uninit(&output
->rec_wet
);
240 CBOX_DELETE(output
->insert
);
241 output
->insert
= NULL
;