Пример #1
0
struct cbox_engine *cbox_engine_new(struct cbox_document *doc, struct cbox_rt *rt)
{
    struct cbox_engine *engine = malloc(sizeof(struct cbox_engine));
    CBOX_OBJECT_HEADER_INIT(engine, cbox_engine, doc);
    
    engine->rt = rt;
    engine->scenes = NULL;
    engine->scene_count = 0;
    engine->effect = NULL;
    engine->master = cbox_master_new(engine);
    engine->master->song = cbox_song_new(doc);
    engine->spb = NULL;
    
    if (rt)
        cbox_io_env_copy(&engine->io_env, &rt->io_env);
    else
    {
        engine->io_env.srate = 0; // must be overridden
        engine->io_env.buffer_size = 256;
        engine->io_env.input_count = 0;
        engine->io_env.output_count = 2;
    }

    cbox_midi_buffer_init(&engine->midibuf_aux);
    cbox_midi_buffer_init(&engine->midibuf_jack);
    cbox_midi_buffer_init(&engine->midibuf_song);
    cbox_midi_appsink_init(&engine->appsink, rt);

    cbox_command_target_init(&engine->cmd_target, cbox_engine_process_cmd, engine);
    CBOX_OBJECT_REGISTER(engine);
    
    return engine;
}
Пример #2
0
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, struct cbox_engine *engine, const char *instance_name, GError **error)
{
    g_clear_error(error);
    struct cbox_module *module = manifest->create(manifest->user_data, cfg_section, doc, rt, engine, error);
    if (!module)
        return NULL;

    module->instance_name = g_strdup(instance_name);
    module->input_samples = malloc(sizeof(float) * CBOX_BLOCK_SIZE * module->inputs);
    module->output_samples = malloc(sizeof(float) * CBOX_BLOCK_SIZE * module->outputs);
    module->engine_name = manifest->name;
    cbox_midi_buffer_init(&module->midi_input);
    
    return module;
}
Пример #3
0
struct cbox_adhoc_pattern *cbox_adhoc_pattern_new(struct cbox_engine *engine, int id, struct cbox_midi_pattern *pattern)
{
    struct cbox_adhoc_pattern *ap = calloc(1, sizeof(struct cbox_adhoc_pattern));
    ap->next = NULL;
    ap->pattern = pattern;
    ap->pattern_playback = cbox_midi_pattern_playback_new(pattern);
    ap->master = cbox_master_new(engine);
    cbox_midi_playback_active_notes_init(&ap->active_notes);
    cbox_midi_clip_playback_init(&ap->playback, &ap->active_notes, ap->master);
    cbox_midi_buffer_init(&ap->output_buffer);
    ap->id = id;
    ap->completed = FALSE;
    
    return ap;
}
Пример #4
0
struct cbox_midi_input *cbox_jackio_create_midi_in(struct cbox_io_impl *impl, const char *name, GError **error)
{
    struct cbox_jack_io_impl *jii = (struct cbox_jack_io_impl *)impl;
    jack_port_t *port = jack_port_register(jii->client, name, JACK_DEFAULT_MIDI_TYPE, JackPortIsInput, 0);
    if (!port)
    {
        g_set_error(error, CBOX_MODULE_ERROR, CBOX_MODULE_ERROR_FAILED, "Cannot create input MIDI port '%s'", name);
        return FALSE;
    }
    struct cbox_jack_midi_input *input = calloc(1, sizeof(struct cbox_jack_midi_input));
    input->hdr.name = g_strdup(name);
    input->hdr.removing = FALSE;
    input->port = port;
    input->jii = jii;
    cbox_uuid_generate(&input->hdr.uuid);
    cbox_midi_buffer_init(&input->hdr.buffer);

    return (struct cbox_midi_input *)input;
}
Пример #5
0
static gboolean cbox_engine_process_cmd(struct cbox_command_target *ct, struct cbox_command_target *fb, struct cbox_osc_command *cmd, GError **error)
{
    struct cbox_engine *engine = ct->user_data;
    if (!strcmp(cmd->command, "/status") && !strcmp(cmd->arg_types, ""))
    {
        for (int i = 0; i < engine->scene_count; i++)
        {
            if (!cbox_execute_on(fb, NULL, "/scene", "o", error, engine->scenes[i]))
                return FALSE;
        }
        return CBOX_OBJECT_DEFAULT_STATUS(engine, fb, error);
    }
    else if (!strcmp(cmd->command, "/render_stereo") && !strcmp(cmd->arg_types, "i"))
    {
        if (!cbox_check_fb_channel(fb, cmd->command, error))
            return FALSE;
        if (engine->rt && engine->rt->io)
        {
            g_set_error(error, CBOX_MODULE_ERROR, CBOX_MODULE_ERROR_FAILED, "Cannot use render function in real-time mode.");
            return FALSE;
        }
        struct cbox_midi_buffer midibuf_song;
        cbox_midi_buffer_init(&midibuf_song);
        int nframes = CBOX_ARG_I(cmd, 0);
        float *data = malloc(2 * nframes * sizeof(float));
        float *data_i = malloc(2 * nframes * sizeof(float));
        float *buffers[2] = { data, data + nframes };
        for (int i = 0; i < nframes; i++)
        {
            buffers[0][i] = 0.f;
            buffers[1][i] = 0.f;
        }
        cbox_engine_process(engine, NULL, nframes, buffers);
        for (int i = 0; i < nframes; i++)
        {
            data_i[i * 2] = buffers[0][i];
            data_i[i * 2 + 1] = buffers[1][i];
        }
        free(data);

        if (!cbox_execute_on(fb, NULL, "/data", "b", error, cbox_blob_new_acquire_data(data_i, nframes * 2 * sizeof(float))))
            return FALSE;
        return TRUE;
    }
    else if (!strncmp(cmd->command, "/master_effect/",15))
    {
        return cbox_module_slot_process_cmd(&engine->effect, fb, cmd, cmd->command + 14, CBOX_GET_DOCUMENT(engine), engine->rt, engine, error);
    }
    else if (!strcmp(cmd->command, "/new_scene") && !strcmp(cmd->arg_types, ""))
    {
        if (!cbox_check_fb_channel(fb, cmd->command, error))
            return FALSE;

        struct cbox_scene *s = cbox_scene_new(CBOX_GET_DOCUMENT(engine), engine);

        return s ? cbox_execute_on(fb, NULL, "/uuid", "o", error, s) : FALSE;
    }
    else if (!strcmp(cmd->command, "/new_recorder") && !strcmp(cmd->arg_types, "s"))
    {
        if (!cbox_check_fb_channel(fb, cmd->command, error))
            return FALSE;

        struct cbox_recorder *rec = cbox_recorder_new_stream(engine, engine->rt, CBOX_ARG_S(cmd, 0));

        return rec ? cbox_execute_on(fb, NULL, "/uuid", "o", error, rec) : FALSE;
    }
    else
        return cbox_object_default_process_cmd(ct, fb, cmd, error);
}
Пример #6
0
static void run_audio_loop(struct cbox_usb_io_impl *uii)
{
    while(!uii->stop_engine && !uii->device_removed) {
        struct cbox_io *io = uii->ioi.pio;
        struct timeval tv = {
            .tv_sec = 0,
            .tv_usec = 1000
        };
        libusb_handle_events_timeout(uii->usbctx, &tv);
        for (GSList *p = io->midi_outputs; p; p = p->next)
        {
            struct cbox_usb_midi_output *umo = p->data;
            usbio_send_midi_to_output(umo);
        }
    }
}

void usbio_run_idle_loop(struct cbox_usb_io_impl *uii)
{
    while(!uii->stop_engine)
    {
        struct cbox_io *io = uii->ioi.pio;
        for (int b = 0; b < uii->output_channels; b++)
            memset(io->output_buffers[b], 0, io->io_env.buffer_size * sizeof(float));
        io->cb->process(io->cb->user_data, io, io->io_env.buffer_size);
        for (GList *p = uii->rt_midi_ports; p; p = p->next)
        {
            struct cbox_usb_midi_interface *umi = p->data;
            cbox_midi_buffer_clear(&umi->input_port->hdr.buffer);
        }
        for (GSList *p = io->midi_outputs; p; p = p->next)
        {
            struct cbox_usb_midi_output *umo = p->data;
            usbio_send_midi_to_output(umo);
        }
        
        struct timeval tv = {
            .tv_sec = 0,
            .tv_usec = 1
        };
        libusb_handle_events_timeout(uii->usbctx, &tv);
        usleep((int)(io->io_env.buffer_size * 1000000.0 / uii->sample_rate));
    }
}

static void *engine_thread(void *user_data)
{
    struct cbox_usb_io_impl *uii = user_data;
    
    usbio_start_midi_capture(uii);

    if (uii->handle_audiodev)
    {
        uii->no_resubmit = FALSE;
        struct sched_param p;
        memset(&p, 0, sizeof(p));
        p.sched_priority = cbox_config_get_int("io", "rtpriority", 10);
        pid_t tid = syscall(SYS_gettid);
        if (0 != sched_setscheduler(tid, SCHED_FIFO, &p))
            g_warning("Cannot set realtime priority for the processing thread: %s.", strerror(errno));
        
        usbio_start_audio_playback(uii);
        if (!uii->setup_error)
        {
            run_audio_loop(uii);
        }
        uii->no_resubmit = TRUE;
        memset(&p, 0, sizeof(p));
        p.sched_priority = 0;
        if (0 != sched_setscheduler(tid, SCHED_OTHER, &p))
            g_warning("Cannot unset realtime priority for the processing thread: %s.", strerror(errno));
        usbio_stop_audio_playback(uii);
    }
    else
    {
        uii->no_resubmit = TRUE;
        g_message("No audio device found - running idle loop.");
        // notify the UI thread that the (fake) audio loop is running
        uii->playback_counter = uii->playback_buffers;
        usbio_run_idle_loop(uii);
    }
    
    usbio_stop_midi_capture(uii);
    return NULL;
}

static void cbox_usbio_destroy_midi_out(struct cbox_io_impl *ioi, struct cbox_midi_output *midiout)
{
    g_free(midiout->name);
    free(midiout);
}

static struct cbox_usb_midi_interface *cur_midi_interface = NULL;

struct cbox_midi_input *cbox_usbio_create_midi_in(struct cbox_io_impl *impl, const char *name, GError **error)
{
    // struct cbox_usb_io_impl *uii = (struct cbox_usb_io_impl *)impl;
    struct cbox_usb_midi_input *input = calloc(1, sizeof(struct cbox_usb_midi_input));
    input->hdr.name = g_strdup(name);
    input->hdr.removing = FALSE;
    cbox_uuid_generate(&input->hdr.uuid);
    cbox_midi_buffer_init(&input->hdr.buffer);
    input->ifptr = cur_midi_interface;
    cbox_midi_appsink_init(&input->hdr.appsink, NULL);
    input->hdr.enable_appsink = FALSE;

    return (struct cbox_midi_input *)input;
}

struct cbox_midi_output *cbox_usbio_create_midi_out(struct cbox_io_impl *impl, const char *name, GError **error)
{
    // struct cbox_usb_io_impl *uii = (struct cbox_usb_io_impl *)impl;
    struct cbox_usb_midi_output *output = calloc(1, sizeof(struct cbox_usb_midi_output));
    output->hdr.name = g_strdup(name);
    output->hdr.removing = FALSE;
    cbox_uuid_generate(&output->hdr.uuid);
    cbox_midi_buffer_init(&output->hdr.buffer);
    cbox_midi_merger_init(&output->hdr.merger, &output->hdr.buffer);
    output->ifptr = cur_midi_interface;

    return (struct cbox_midi_output *)output;
}

static void create_midi_ports(struct cbox_usb_io_impl *uii)
{
    uii->ioi.createmidiinfunc = cbox_usbio_create_midi_in;
    uii->ioi.createmidioutfunc = cbox_usbio_create_midi_out;
    for (GList *p = uii->midi_ports; p; p = p->next)
    {
        struct cbox_usb_midi_interface *umi = p->data;
        char buf[80];
        sprintf(buf, "usb:%03d:%03d", umi->devinfo->bus, umi->devinfo->devadr);
        cur_midi_interface = umi;
        if (umi->epdesc_in.found)
            umi->input_port = (struct cbox_usb_midi_input *)cbox_io_create_midi_input(uii->ioi.pio, buf, NULL);
        else
            umi->input_port = NULL;
        if (umi->epdesc_out.found)
            umi->output_port = (struct cbox_usb_midi_output *)cbox_io_create_midi_output(uii->ioi.pio, buf, NULL);
        else
            umi->output_port = NULL;
    }
    uii->ioi.createmidiinfunc = NULL;
    uii->ioi.createmidioutfunc = NULL;
    cur_midi_interface = NULL;
}