You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
131 lines
4.5 KiB
131 lines
4.5 KiB
3 years ago
|
/*
|
||
|
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 <http://www.gnu.org/licenses/>.
|
||
|
*/
|
||
|
|
||
|
#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);
|
||
|
}
|
||
|
|