/* Calf Box, an open source musical instrument. Copyright (C) 2010-2011 Krzysztof Foltman This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program. If not, see . */ #include "app.h" #include "errors.h" #include "recsrc.h" #include "rt.h" #include "scene.h" #include "stm.h" static void cbox_recorder_destroyfunc(struct cbox_objhdr *objhdr) { struct cbox_recorder *rec = CBOX_H2O(objhdr); if (rec->destroy) rec->destroy(rec); free(rec); } CBOX_CLASS_DEFINITION_ROOT(cbox_recorder) static gboolean cbox_recording_source_process_cmd(struct cbox_command_target *ct, struct cbox_command_target *fb, struct cbox_osc_command *cmd, GError **error); void cbox_recording_source_init(struct cbox_recording_source *src, struct cbox_scene *scene, uint32_t max_numsamples, int channels) { src->scene = scene; src->handlers = NULL; src->handler_count = 0; src->max_numsamples = max_numsamples; src->channels = channels; cbox_command_target_init(&src->cmd_target, cbox_recording_source_process_cmd, src); } gboolean cbox_recording_source_attach(struct cbox_recording_source *src, struct cbox_recorder *rec, GError **error) { if (rec->attach && !rec->attach(rec, src, error)) return FALSE; cbox_rt_array_insert(app.rt, (void ***)&src->handlers, &src->handler_count, 0, rec); return TRUE; } int cbox_recording_source_detach(struct cbox_recording_source *src, struct cbox_recorder *rec, GError **error) { int index = -1; for (uint32_t i = 0; i < src->handler_count; i++) { if (src->handlers[i] == rec) { index = i; break; } } if (index == -1) { if (error) g_set_error(error, CBOX_MODULE_ERROR, CBOX_MODULE_ERROR_FAILED, "Recorder is not attached to this source"); return 0; } cbox_rt_array_remove(app.rt, (void ***)&src->handlers, &src->handler_count, index); // XXXKF: when converting to async API, the array_remove must be done synchronously or // detach needs to be called in the cleanup part of the remove command, otherwise detach // may be called on 'live' recorder, which may cause unpredictable results. return rec->detach ? rec->detach(rec, error) : 1; } void cbox_recording_source_push(struct cbox_recording_source *src, const float **buffers, uint32_t offset, uint32_t numsamples) { for (uint32_t i = 0; i < src->handler_count; i++) src->handlers[i]->record_block(src->handlers[i], buffers, offset, numsamples); } void cbox_recording_source_uninit(struct cbox_recording_source *src) { STM_ARRAY_FREE_OBJS(src->handlers, src->handler_count); src->handlers = NULL; src->handler_count = 0; } gboolean cbox_recording_source_process_cmd(struct cbox_command_target *ct, struct cbox_command_target *fb, struct cbox_osc_command *cmd, GError **error) { struct cbox_recording_source *src = ct->user_data; if (!strcmp(cmd->command, "/status") && !strcmp(cmd->arg_types, "")) { if (!cbox_check_fb_channel(fb, cmd->command, error)) return FALSE; for (uint32_t i = 0; i < src->handler_count; i++) { if (!cbox_execute_on(fb, NULL, "/handler", "o", error, src->handlers[i])) return FALSE; } return TRUE; } else if (!strcmp(cmd->command, "/attach") && !strcmp(cmd->arg_types, "s")) { struct cbox_objhdr *objhdr = CBOX_ARG_O(cmd, 0, src->scene, cbox_recorder, error); if (!objhdr) return FALSE; struct cbox_recorder *rec = CBOX_H2O(objhdr); return cbox_recording_source_attach(src, rec, error); } else if (!strcmp(cmd->command, "/detach") && !strcmp(cmd->arg_types, "s")) { struct cbox_objhdr *objhdr = CBOX_ARG_O(cmd, 0, src->scene, cbox_recorder, error); if (!objhdr) return FALSE; struct cbox_recorder *rec = CBOX_H2O(objhdr); return cbox_recording_source_detach(src, rec, error); } else return cbox_set_command_error(error, cmd); }