Sampled Instrument Player with static and monolithic design. All instruments are built-in.
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.
 
 

130 lines
4.5 KiB

/*
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);
}