Exemple #1
0
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)
{
    if (!strcmp(subcmd, "/status") && !strcmp(cmd->arg_types, ""))
    {
        if (!cbox_check_fb_channel(fb, cmd->command, error))
            return FALSE;
        if (!(cbox_execute_on(fb, NULL, "/gain_linear", "f", error, output->gain) &&
            cbox_execute_on(fb, NULL, "/gain", "f", error, gain2dB_simple(output->gain)) &&
            cbox_execute_on(fb, NULL, "/bus", "s", error, instr->aux_output_names[id] ? instr->aux_output_names[id] : "")))
            return FALSE;
        return cbox_module_slot_process_cmd(&output->insert, fb, cmd, subcmd, CBOX_GET_DOCUMENT(instr->scene), instr->scene->rt, instr->scene->engine, error);
    }
    else if (!strcmp(subcmd, "/bus") && !strcmp(cmd->arg_types, "s"))
    {
        struct cbox_scene *scene = instr->scene;
        if (!CBOX_ARG_S(cmd, 0))
        {
            struct cbox_aux_bus *old_bus = cbox_rt_swap_pointers(instr->module->rt, (void **)&instr->aux_outputs[id], NULL);
            if (old_bus)
                cbox_aux_bus_unref(old_bus);
            return TRUE;            
        }
        for (int i = 0; i < scene->aux_bus_count; i++)
        {
            if (!scene->aux_buses[i])
                continue;
            if (!strcmp(scene->aux_buses[i]->name, CBOX_ARG_S(cmd, 0)))
            {
                g_free(instr->aux_output_names[id]);
                instr->aux_output_names[id] = g_strdup(scene->aux_buses[i]->name);
                cbox_aux_bus_ref(scene->aux_buses[i]);
                struct cbox_aux_bus *old_bus = cbox_rt_swap_pointers(instr->module->rt, (void **)&instr->aux_outputs[id], scene->aux_buses[i]);
                if (old_bus)
                    cbox_aux_bus_unref(old_bus);
                return TRUE;
            }
        }
        g_set_error(error, CBOX_MODULE_ERROR, CBOX_MODULE_ERROR_FAILED, "Unknown aux bus: %s", CBOX_ARG_S(cmd, 0));
        return FALSE;
    }
    else if (!strcmp(subcmd, "/output") && !strcmp(cmd->arg_types, "i")) // not supported
    {
        cbox_set_command_error(error, cmd);
        return FALSE;
    }
    else // otherwise, treat just like an command on normal (non-aux) output
        return cbox_instrument_output_process_cmd(instr, output, fb, cmd, subcmd, error);
}
Exemple #2
0
static gboolean cbox_jack_io_process_cmd(struct cbox_command_target *ct, struct cbox_command_target *fb, struct cbox_osc_command *cmd, GError **error)
{
    struct cbox_jack_io_impl *jii = (struct cbox_jack_io_impl *)ct->user_data;
    struct cbox_io *io = jii->ioi.pio;
    gboolean handled = FALSE;
    if (!strcmp(cmd->command, "/status") && !strcmp(cmd->arg_types, ""))
    {
        if (!cbox_check_fb_channel(fb, cmd->command, error))
            return FALSE;
        return cbox_execute_on(fb, NULL, "/client_type", "s", error, "JACK") &&
            cbox_execute_on(fb, NULL, "/client_name", "s", error, jii->client_name) &&
            cbox_io_process_cmd(io, fb, cmd, error, &handled);
    }
    else if (!strcmp(cmd->command, "/rename_midi_port") && !strcmp(cmd->arg_types, "ss"))
    {
        const char *uuidstr = CBOX_ARG_S(cmd, 0);
        const char *new_name = CBOX_ARG_S(cmd, 1);
        struct cbox_uuid uuid;
        if (!cbox_uuid_fromstring(&uuid, uuidstr, error))
            return FALSE;
        struct cbox_midi_input *midiin = cbox_io_get_midi_input(io, NULL, &uuid);
        struct cbox_midi_output *midiout = cbox_io_get_midi_output(io, NULL, &uuid);
        if (!midiout && !midiin)
        {
            g_set_error(error, CBOX_MODULE_ERROR, CBOX_MODULE_ERROR_FAILED, "Port '%s' not found", uuidstr);
            return FALSE;
        }
        jack_port_t *port = midiout ? ((struct cbox_jack_midi_output *)midiout)->port 
            : ((struct cbox_jack_midi_input *)midiin)->port;
        char **pname = midiout ? &midiout->name : &midiin->name;
        if (0 != jack_port_set_name(port, new_name))
        {
            g_set_error(error, CBOX_MODULE_ERROR, CBOX_MODULE_ERROR_FAILED, "Cannot set port name to '%s'", new_name);
            return FALSE;
        }
        g_free(*pname);
        *pname = g_strdup(new_name);
        return TRUE;
    }
    else if (!strcmp(cmd->command, "/autoconnect") && !strcmp(cmd->arg_types, "ss"))
    {
        const char *uuidstr = CBOX_ARG_S(cmd, 0);
        const char *spec = CBOX_ARG_S(cmd, 1);
        struct cbox_uuid uuid;
        if (!cbox_uuid_fromstring(&uuid, uuidstr, error))
            return FALSE;
        struct cbox_midi_output *midiout = cbox_io_get_midi_output(io, NULL, &uuid);
        if (midiout)
        {
            cbox_jack_midi_output_set_autoconnect((struct cbox_jack_midi_output *)midiout, spec);
            return TRUE;
        }
        struct cbox_midi_input *midiin = cbox_io_get_midi_input(io, NULL, &uuid);
        if (midiin)
        {
            cbox_jack_midi_input_set_autoconnect((struct cbox_jack_midi_input *)midiin, spec);
            return TRUE;
        }
        g_set_error(error, CBOX_MODULE_ERROR, CBOX_MODULE_ERROR_FAILED, "Port '%s' not found", uuidstr);
        return FALSE;
    }
    else if (!strcmp(cmd->command, "/disconnect_midi_port") && !strcmp(cmd->arg_types, "s"))
    {
        const char *uuidstr = CBOX_ARG_S(cmd, 0);
        struct cbox_uuid uuid;
        if (!cbox_uuid_fromstring(&uuid, uuidstr, error))
            return FALSE;
        struct cbox_midi_input *midiin = cbox_io_get_midi_input(io, NULL, &uuid);
        struct cbox_midi_output *midiout = cbox_io_get_midi_output(io, NULL, &uuid);
        if (!midiout && !midiin)
        {
            g_set_error(error, CBOX_MODULE_ERROR, CBOX_MODULE_ERROR_FAILED, "Port '%s' not found", uuidstr);
            return FALSE;
        }
        jack_port_t *port = midiout ? ((struct cbox_jack_midi_output *)midiout)->port 
            : ((struct cbox_jack_midi_input *)midiin)->port; 
        jack_port_disconnect(jii->client, port);
        return TRUE;
    }
    else if (!strcmp(cmd->command, "/port_connect") && !strcmp(cmd->arg_types, "ss"))
    {
        const char *port_from = CBOX_ARG_S(cmd, 0);
        const char *port_to = CBOX_ARG_S(cmd, 1);
        int res = jack_connect(jii->client, port_from, port_to);
        if (res == EEXIST)
            res = 0;
        if (res)
            g_set_error(error, CBOX_MODULE_ERROR, CBOX_MODULE_ERROR_FAILED, "Cannot connect port '%s' to '%s'", port_from, port_to);
        return res == 0;
    }
    else if (!strcmp(cmd->command, "/port_disconnect") && !strcmp(cmd->arg_types, "ss"))
    {
        const char *port_from = CBOX_ARG_S(cmd, 0);
        const char *port_to = CBOX_ARG_S(cmd, 1);
        int res = jack_disconnect(jii->client, port_from, port_to);
        if (res)
            g_set_error(error, CBOX_MODULE_ERROR, CBOX_MODULE_ERROR_FAILED, "Cannot disconnect port '%s' from '%s'", port_from, port_to);
        return res == 0;
    }
    else if (!strcmp(cmd->command, "/get_connected_ports") && !strcmp(cmd->arg_types, "s"))
    {
        if (!cbox_check_fb_channel(fb, cmd->command, error))
            return FALSE;
        const char *name = CBOX_ARG_S(cmd, 0);
        jack_port_t *port = jack_port_by_name(jii->client, name);
        if (!port)
        {
            g_set_error(error, CBOX_MODULE_ERROR, CBOX_MODULE_ERROR_FAILED, "Port '%s' not found", name);
            return FALSE;
        }
        const char** ports = jack_port_get_all_connections(jii->client, port);
        for (int i = 0; ports && ports[i]; i++)
        {
            if (!cbox_execute_on(fb, NULL, "/port", "s", error, ports[i]))
                return FALSE;
        }
        jack_free(ports);
        return TRUE;
    }
    else if (!strcmp(cmd->command, "/get_ports") && !strcmp(cmd->arg_types, "ssi"))
    {
        if (!cbox_check_fb_channel(fb, cmd->command, error))
            return FALSE;
        const char *mask = CBOX_ARG_S(cmd, 0);
        const char *type = CBOX_ARG_S(cmd, 1);
        uint32_t flags = CBOX_ARG_I(cmd, 2);
        const char** ports = jack_get_ports(jii->client, mask, type, flags);
        for (int i = 0; ports && ports[i]; i++)
        {
            if (!cbox_execute_on(fb, NULL, "/port", "s", error, ports[i]))
                return FALSE;
        }
        jack_free(ports);
        return TRUE;
    }
    else
    {
        gboolean result = cbox_io_process_cmd(io, fb, cmd, error, &handled);
        if (!handled)
            g_set_error(error, CBOX_MODULE_ERROR, CBOX_MODULE_ERROR_FAILED, "Unknown combination of target path and argument: '%s', '%s'", cmd->command, cmd->arg_types);
        return result;
    }
}
Exemple #3
0
gboolean cbox_module_slot_process_cmd(struct cbox_module **psm, 
        struct cbox_command_target *fb, struct cbox_osc_command *cmd, const char *subcmd,
        struct cbox_document *doc, struct cbox_rt *rt, struct cbox_engine *engine, GError **error)
{
    struct cbox_module *sm = *psm;
    if (!strcmp(subcmd, "/status") && !strcmp(cmd->arg_types, ""))
    {
        if (!cbox_check_fb_channel(fb, cmd->command, error))
            return FALSE;
        if (!(cbox_execute_on(fb, NULL, "/insert_engine", "s", error, sm ? sm->engine_name : "") &&
            cbox_execute_on(fb, NULL, "/insert_preset", "s", error, sm ? sm->instance_name : "") &&
            cbox_execute_on(fb, NULL, "/bypass", "i", error, sm ? sm->bypass : 0)))
            return FALSE;
        return TRUE;
    }
    if (!strcmp(subcmd, "/insert_preset") && !strcmp(cmd->arg_types, "s"))
    {
        struct cbox_module *effect = cbox_module_new_from_fx_preset(CBOX_ARG_S(cmd, 0), doc, rt, engine, error);
        if (!effect)
            return FALSE;
        cbox_rt_swap_pointers(rt, (void **)psm, effect);
        return TRUE;
    }
    if (!strcmp(subcmd, "/insert_engine") && !strcmp(cmd->arg_types, "s"))
    {
        struct cbox_module *effect = NULL;
        if (*CBOX_ARG_S(cmd, 0))
        {
            struct cbox_module_manifest *manifest = cbox_module_manifest_get_by_name(CBOX_ARG_S(cmd, 0));
            if (!manifest)
            {
                g_set_error(error, CBOX_MODULE_ERROR, CBOX_MODULE_ERROR_FAILED, "No effect engine '%s'", CBOX_ARG_S(cmd, 0));
                return FALSE;
            }
            effect = cbox_module_manifest_create_module(manifest, NULL, doc, rt, engine, "unnamed", error);
            if (!effect)
                return FALSE;
        }
        cbox_rt_swap_pointers(rt, (void **)psm, effect);
        return TRUE;
    }
    if (!sm)
    {
        g_set_error(error, CBOX_MODULE_ERROR, CBOX_MODULE_ERROR_FAILED, "No engine on module in path '%s'", cmd->command);
        return FALSE;
    }
    if (!strncmp(subcmd, "/engine/", 8))
    {
        if (!sm->cmd_target.process_cmd)
        {
            g_set_error(error, CBOX_MODULE_ERROR, CBOX_MODULE_ERROR_FAILED, "The engine %s has no command target defined", sm->engine_name);
            return FALSE;
        }
        return cbox_execute_sub(&sm->cmd_target, fb, cmd, subcmd + 7, error);
    }
    if (!strcmp(subcmd, "/set_bypass") && !strcmp(cmd->arg_types, "i"))
    {
        sm->bypass = CBOX_ARG_I(cmd, 0);
        return TRUE;
    }
    return cbox_object_default_process_cmd(&sm->cmd_target, fb, cmd, error);
}
Exemple #4
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);
}
Exemple #5
0
gboolean cbox_song_process_cmd(struct cbox_command_target *ct, struct cbox_command_target *fb, struct cbox_osc_command *cmd, GError **error)
{
    struct cbox_song *song = ct->user_data;
    if (!strcmp(cmd->command, "/status") && !strcmp(cmd->arg_types, ""))
    {
        if (!cbox_check_fb_channel(fb, cmd->command, error))
            return FALSE;
        
        for(GList *p = song->tracks; p; p = g_list_next(p))
        {
            struct cbox_track *trk = p->data;
            if (!cbox_execute_on(fb, NULL, "/track", "sio", error, trk->name, g_list_length(trk->items), trk))
                return FALSE;
        }
        for(GList *p = song->patterns; p; p = g_list_next(p))
        {
            struct cbox_midi_pattern *pat = p->data;
            if (!cbox_execute_on(fb, NULL, "/pattern", "sio", error, pat->name, pat->loop_end, pat))
                return FALSE;
        }
        uint32_t pos = 0;
        for(GList *p = song->master_track_items; p; p = g_list_next(p))
        {
            struct cbox_master_track_item *mti = p->data;
            // Omit dummy item at 0 position.
            if (pos || (mti->timesig_num && mti->timesig_denom) || mti->tempo)
            {
                if (!cbox_execute_on(fb, NULL, "/mti", "ifii", error, pos, mti->tempo, mti->timesig_num, mti->timesig_denom))
                    return FALSE;
            }
            pos += mti->duration_ppqn;
        }
        return cbox_execute_on(fb, NULL, "/loop_start", "i", error, (int)song->loop_start_ppqn) &&
            cbox_execute_on(fb, NULL, "/loop_end", "i", error, (int)song->loop_end_ppqn) &&
            CBOX_OBJECT_DEFAULT_STATUS(song, fb, error);
    }
    else
    if (!strcmp(cmd->command, "/set_loop") && !strcmp(cmd->arg_types, "ii"))
    {
        song->loop_start_ppqn = CBOX_ARG_I(cmd, 0);
        song->loop_end_ppqn = CBOX_ARG_I(cmd, 1);
        return TRUE;
    }
    else
    if (!strcmp(cmd->command, "/set_mti") && !strcmp(cmd->arg_types, "ifii"))
    {
        cbox_song_set_mti(song, CBOX_ARG_I(cmd, 0), CBOX_ARG_F(cmd, 1), CBOX_ARG_I(cmd, 2), CBOX_ARG_I(cmd, 3));
        return TRUE;
    }
    else
    if (!strcmp(cmd->command, "/clear") && !strcmp(cmd->arg_types, ""))
    {
        cbox_song_clear(song);
        return TRUE;
    }
    else
    if (!strcmp(cmd->command, "/add_track") && !strcmp(cmd->arg_types, ""))
    {
        if (!cbox_check_fb_channel(fb, cmd->command, error))
            return FALSE;
        
        struct cbox_track *track = cbox_track_new(CBOX_GET_DOCUMENT(song));
        cbox_song_add_track(song, track);
        if (!cbox_execute_on(fb, NULL, "/uuid", "o", error, track))
        {
            CBOX_DELETE(track);
            return FALSE;
        }
        
        return TRUE;
    }
    else
    if (!strcmp(cmd->command, "/load_pattern") && !strcmp(cmd->arg_types, "si"))
    {
        if (!cbox_check_fb_channel(fb, cmd->command, error))
            return FALSE;
        
        struct cbox_midi_pattern *pattern = cbox_midi_pattern_load(song, CBOX_ARG_S(cmd, 0), CBOX_ARG_I(cmd, 1), app.engine->master->ppqn_factor);
        if (!cbox_execute_on(fb, NULL, "/uuid", "o", error, pattern))
        {
            CBOX_DELETE(pattern);
            return FALSE;
        }
        
        return TRUE;
    }
    else
    if (!strcmp(cmd->command, "/load_track") && !strcmp(cmd->arg_types, "si"))
    {
        if (!cbox_check_fb_channel(fb, cmd->command, error))
            return FALSE;
        
        struct cbox_midi_pattern *pattern = cbox_midi_pattern_load_track(song, CBOX_ARG_S(cmd, 0), CBOX_ARG_I(cmd, 1), app.engine->master->ppqn_factor);
        if (!cbox_execute_on(fb, NULL, "/uuid", "o", error, pattern))
        {
            CBOX_DELETE(pattern);
            return FALSE;
        }
        
        return TRUE;
    }
    else
    if (!strcmp(cmd->command, "/load_metronome") && !strcmp(cmd->arg_types, "i"))
    {
        if (!cbox_check_fb_channel(fb, cmd->command, error))
            return FALSE;
        
        struct cbox_midi_pattern *pattern = cbox_midi_pattern_new_metronome(song, CBOX_ARG_I(cmd, 0), app.engine->master->ppqn_factor);
        if (!cbox_execute_on(fb, NULL, "/uuid", "o", error, pattern))
        {
            CBOX_DELETE(pattern);
            return FALSE;
        }
        
        return TRUE;
    }
    else
    if (!strcmp(cmd->command, "/load_blob") && !strcmp(cmd->arg_types, "bi"))
    {
        if (!cbox_check_fb_channel(fb, cmd->command, error))
            return FALSE;
        
        struct cbox_midi_pattern *pattern = cbox_midi_pattern_new_from_blob(song, CBOX_ARG_B(cmd, 0), CBOX_ARG_I(cmd, 1), app.engine->master->ppqn_factor);
        if (!cbox_execute_on(fb, NULL, "/uuid", "o", error, pattern))
        {
            CBOX_DELETE(pattern);
            return FALSE;
        }
        
        return TRUE;
    }
    else
        return cbox_object_default_process_cmd(ct, fb, cmd, error);
    return TRUE;
}
Exemple #6
0
static gboolean cbox_jack_io_process_cmd(struct cbox_command_target *ct, struct cbox_command_target *fb, struct cbox_osc_command *cmd, GError **error)
{
    struct cbox_jack_io_impl *jii = (struct cbox_jack_io_impl *)ct->user_data;
    struct cbox_io *io = jii->ioi.pio;
    gboolean handled = FALSE;
    if (!strcmp(cmd->command, "/status") && !strcmp(cmd->arg_types, ""))
    {
        if (!cbox_check_fb_channel(fb, cmd->command, error))
            return FALSE;
        return cbox_execute_on(fb, NULL, "/client_type", "s", error, "JACK") &&
            cbox_execute_on(fb, NULL, "/client_name", "s", error, jii->client_name) &&
            cbox_execute_on(fb, NULL, "/external_tempo", "i", error, jii->external_tempo) &&
            cbox_io_process_cmd(io, fb, cmd, error, &handled);
    }
    else if (!strcmp(cmd->command, "/rename_midi_port") && !strcmp(cmd->arg_types, "ss"))
    {
        const char *uuidstr = CBOX_ARG_S(cmd, 0);
        const char *new_name = CBOX_ARG_S(cmd, 1);
        struct cbox_uuid uuid;
        if (!cbox_uuid_fromstring(&uuid, uuidstr, error))
            return FALSE;
        struct cbox_midi_input *midiin = cbox_io_get_midi_input(io, NULL, &uuid);
        struct cbox_midi_output *midiout = cbox_io_get_midi_output(io, NULL, &uuid);
        if (!midiout && !midiin)
        {
            g_set_error(error, CBOX_MODULE_ERROR, CBOX_MODULE_ERROR_FAILED, "Port '%s' not found", uuidstr);
            return FALSE;
        }
        jack_port_t *port = midiout ? ((struct cbox_jack_midi_output *)midiout)->port
            : ((struct cbox_jack_midi_input *)midiin)->port;
        char **pname = midiout ? &midiout->name : &midiin->name;
        if (0 != jack_port_rename_fn(jii->client, port, new_name))
        {
            g_set_error(error, CBOX_MODULE_ERROR, CBOX_MODULE_ERROR_FAILED, "Cannot set port name to '%s'", new_name);
            return FALSE;
        }
        g_free(*pname);
        *pname = g_strdup(new_name);
        return TRUE;
    }
    else if (!strcmp(cmd->command, "/rename_audio_port") && !strcmp(cmd->arg_types, "ss"))
    {
        const char *uuidstr = CBOX_ARG_S(cmd, 0);
        const char *new_name = CBOX_ARG_S(cmd, 1);
        struct cbox_uuid uuid;
        if (!cbox_uuid_fromstring(&uuid, uuidstr, error))
            return FALSE;
        struct cbox_audio_output *audioout = cbox_io_get_audio_output(io, NULL, &uuid);
        if (!audioout)
        {
            g_set_error(error, CBOX_MODULE_ERROR, CBOX_MODULE_ERROR_FAILED, "Port '%s' not found", uuidstr);
            return FALSE;
        }
        if (0 != jack_port_rename_fn(jii->client, ((struct cbox_jack_audio_output *)audioout)->port, new_name))
        {
            g_set_error(error, CBOX_MODULE_ERROR, CBOX_MODULE_ERROR_FAILED, "Cannot set port name to '%s'", new_name);
            return FALSE;
        }
        g_free(audioout->name);
        audioout->name = g_strdup(new_name);
        return TRUE;
    }
    else if (!strcmp(cmd->command, "/autoconnect") && !strcmp(cmd->arg_types, "ss"))
    {
        const char *uuidstr = CBOX_ARG_S(cmd, 0);
        const char *spec = CBOX_ARG_S(cmd, 1);
        struct cbox_uuid uuid;
        if (!cbox_uuid_fromstring(&uuid, uuidstr, error))
            return FALSE;
        struct cbox_midi_output *midiout = cbox_io_get_midi_output(io, NULL, &uuid);
        if (midiout)
        {
            cbox_jack_midi_output_set_autoconnect((struct cbox_jack_midi_output *)midiout, spec);
            return TRUE;
        }
        struct cbox_midi_input *midiin = cbox_io_get_midi_input(io, NULL, &uuid);
        if (midiin)
        {
            cbox_jack_midi_input_set_autoconnect((struct cbox_jack_midi_input *)midiin, spec);
            return TRUE;
        }
        struct cbox_audio_output *audioout = cbox_io_get_audio_output(io, NULL, &uuid);
        if (audioout)
        {
            cbox_jack_audio_output_set_autoconnect((struct cbox_jack_audio_output *)audioout, spec);
            return TRUE;
        }
        g_set_error(error, CBOX_MODULE_ERROR, CBOX_MODULE_ERROR_FAILED, "Port '%s' not found", uuidstr);
        return FALSE;
    }
    else if (!strcmp(cmd->command, "/disconnect_audio_output") && !strcmp(cmd->arg_types, "s"))
    {
        const char *uuidstr = CBOX_ARG_S(cmd, 0);
        struct cbox_uuid uuid;
        if (!cbox_uuid_fromstring(&uuid, uuidstr, error))
            return FALSE;
        struct cbox_audio_output *audioout = cbox_io_get_audio_output(io, NULL, &uuid);
        if (!audioout)
        {
            g_set_error(error, CBOX_MODULE_ERROR, CBOX_MODULE_ERROR_FAILED, "Port '%s' not found", uuidstr);
            return FALSE;
        }
        jack_port_disconnect(jii->client, ((struct cbox_jack_audio_output *)audioout)->port);
        return TRUE;
    }
    else if (!strncmp(cmd->command, "/disconnect_midi_", 17) && !strcmp(cmd->arg_types, "s"))
    {
        bool is_both = !strcmp(cmd->command + 17, "port");
        bool is_in = is_both || !strcmp(cmd->command + 17, "input");
        bool is_out = is_both || !strcmp(cmd->command + 17, "output");
        if (is_in || is_out) {
            const char *uuidstr = CBOX_ARG_S(cmd, 0);
            struct cbox_uuid uuid;
            if (!cbox_uuid_fromstring(&uuid, uuidstr, error))
                return FALSE;
            struct cbox_midi_input *midiin = is_in ? cbox_io_get_midi_input(io, NULL, &uuid) : NULL;
            struct cbox_midi_output *midiout = is_out ? cbox_io_get_midi_output(io, NULL, &uuid) : NULL;
            if (!midiout && !midiin)
            {
                g_set_error(error, CBOX_MODULE_ERROR, CBOX_MODULE_ERROR_FAILED, "Port '%s' not found", uuidstr);
                return FALSE;
            }
            jack_port_t *port = midiout ? ((struct cbox_jack_midi_output *)midiout)->port
                : ((struct cbox_jack_midi_input *)midiin)->port;
            jack_port_disconnect(jii->client, port);
            return TRUE;
        }
    }

    if (!strcmp(cmd->command, "/port_connect") && !strcmp(cmd->arg_types, "ss"))
    {
        const char *port_from = CBOX_ARG_S(cmd, 0);
        const char *port_to = CBOX_ARG_S(cmd, 1);
        int res = jack_connect(jii->client, port_from, port_to);
        if (res == EEXIST)
            res = 0;
        if (res)
            g_set_error(error, CBOX_MODULE_ERROR, CBOX_MODULE_ERROR_FAILED, "Cannot connect port '%s' to '%s'", port_from, port_to);
        return res == 0;
    }
    else if (!strcmp(cmd->command, "/port_disconnect") && !strcmp(cmd->arg_types, "ss"))
    {
        const char *port_from = CBOX_ARG_S(cmd, 0);
        const char *port_to = CBOX_ARG_S(cmd, 1);
        int res = jack_disconnect(jii->client, port_from, port_to);
        if (res)
            g_set_error(error, CBOX_MODULE_ERROR, CBOX_MODULE_ERROR_FAILED, "Cannot disconnect port '%s' from '%s'", port_from, port_to);
        return res == 0;
    }
    else if (!strcmp(cmd->command, "/get_connected_ports") && !strcmp(cmd->arg_types, "s"))
    {
        if (!cbox_check_fb_channel(fb, cmd->command, error))
            return FALSE;
        const char *name = CBOX_ARG_S(cmd, 0);
        jack_port_t *port = NULL;
        if (!strchr(name, ':')) {
            // try UUID
            struct cbox_uuid uuid;
            if (!cbox_uuid_fromstring(&uuid, name, error))
                return FALSE;
            struct cbox_midi_output *midiout = cbox_io_get_midi_output(io, NULL, &uuid);
            if (midiout)
                port = ((struct cbox_jack_midi_output *)midiout)->port;
            else {
                struct cbox_midi_input *midiin = cbox_io_get_midi_input(io, NULL, &uuid);
                if (midiin)
                    port = ((struct cbox_jack_midi_input *)midiin)->port;
            }
        }
        else
            port = jack_port_by_name(jii->client, name);
        if (!port)
        {
            g_set_error(error, CBOX_MODULE_ERROR, CBOX_MODULE_ERROR_FAILED, "Port '%s' not found", name);
            return FALSE;
        }
        const char** ports = jack_port_get_all_connections(jii->client, port);
        for (int i = 0; ports && ports[i]; i++)
        {
            if (!cbox_execute_on(fb, NULL, "/port", "s", error, ports[i]))
                return FALSE;
        }
        jack_free(ports);
        return TRUE;
    }
    else if (!strcmp(cmd->command, "/get_ports") && !strcmp(cmd->arg_types, "ssi"))
    {
        if (!cbox_check_fb_channel(fb, cmd->command, error))
            return FALSE;
        const char *mask = CBOX_ARG_S(cmd, 0);
        const char *type = CBOX_ARG_S(cmd, 1);
        uint32_t flags = CBOX_ARG_I(cmd, 2);
        const char** ports = jack_get_ports(jii->client, mask, type, flags);
        for (int i = 0; ports && ports[i]; i++)
        {
            if (!cbox_execute_on(fb, NULL, "/port", "s", error, ports[i]))
                return FALSE;
        }
        jack_free(ports);
        return TRUE;
    }
    else if (!strcmp(cmd->command, "/external_tempo") && !strcmp(cmd->arg_types, "i"))
    {
        jii->external_tempo = CBOX_ARG_I(cmd, 0);
        return TRUE;
    }

    //Metadata

    else if (!strcmp(cmd->command, "/set_property") && !strcmp(cmd->arg_types, "ssss"))
    //parameters: "client:port", key, value, type according to jack_property_t (empty or NULL for string)
    {
        const char *name = CBOX_ARG_S(cmd, 0);
        const char *key = CBOX_ARG_S(cmd, 1);
        const char *value = CBOX_ARG_S(cmd, 2);
        const char *type = CBOX_ARG_S(cmd, 3);

        jack_uuid_t subject;
        if (!cbox_jack_io_get_jack_uuid_from_name(jii, name, &subject, error)) //error message set inside
            return FALSE;

        if (jack_set_property(jii->client, subject, key, value, type)) // 0 on success
        {
            g_set_error(error, CBOX_MODULE_ERROR, CBOX_MODULE_ERROR_FAILED, "Set property key:'%s' value: '%s' to port '%s' was not successful", key, value, name);
            return FALSE;
        }
        return TRUE;
    }
    else if (!strcmp(cmd->command, "/get_property") && !strcmp(cmd->arg_types, "ss"))
    //parameters: "client:port", key
    //returns python key, value and type as strings
    {
        const char *name = CBOX_ARG_S(cmd, 0);
        const char *key = CBOX_ARG_S(cmd, 1);

        jack_uuid_t subject;
        if (!cbox_jack_io_get_jack_uuid_from_name(jii, name, &subject, error)) //error message set inside
            return FALSE;

        char* value = NULL;
        char* type = NULL;

        if (jack_get_property(subject, key, &value, &type)) // 0 on success, -1 if the subject has no key property.
        {
            g_set_error(error, CBOX_MODULE_ERROR, CBOX_MODULE_ERROR_FAILED, "Port '%s' does not have key '%s'", name, key);
            return FALSE;
        }

        char* returntype; //We need to call jack_free on type in any case so it can't be our own data.
        if (type == NULL)
             returntype = "";
        else
            returntype = type;

        if (!cbox_execute_on(fb, NULL, "/value", "ss", error, value, returntype)) //send return values to Python.
           return FALSE;

        jack_free(value);
        jack_free(type);
        return TRUE;
    }
    else if (!strcmp(cmd->command, "/get_properties") && !strcmp(cmd->arg_types, "s"))
    //parameters: "client:port"
    {
        const char *name = CBOX_ARG_S(cmd, 0);

        jack_uuid_t subject;
        if (!cbox_jack_io_get_jack_uuid_from_name(jii, name, &subject, error))  //error message set inside
            return FALSE;

        jack_description_t desc;
        if (!jack_get_properties(subject, &desc)) // 0 on success, -1 if no subject with any properties exists.
        {
            g_set_error(error, CBOX_MODULE_ERROR, CBOX_MODULE_ERROR_FAILED, "Port '%s' with uuid '%lli' does not have any properties", name, (long long)subject);
            return FALSE;
        }

        const char *returntype;
        for (uint32_t i = 0; i<desc.property_cnt ; i++)
        {
            if (desc.properties[i].type == NULL)
                 returntype = "";
            else
                returntype = desc.properties[i].type;
            if (!cbox_execute_on(fb, NULL, "/properties", "sss", error, desc.properties[i].key, desc.properties[i].data, returntype))
                return FALSE;
        }
        jack_free_description(&desc, 0); //if non-zero desc will also be passed to free()
        return TRUE;
    }
    else if (!strcmp(cmd->command, "/get_all_properties") && !strcmp(cmd->arg_types, ""))
    {
        jack_description_t *descs;
        int counter;
        counter = jack_get_all_properties(&descs);
        const char *returntype;
        for (int j = 0; j < counter; j++)
        {
            jack_description_t *one_desc = &descs[j];
            for (uint32_t i = 0; i < one_desc->property_cnt ; i++)
            {
                if (one_desc->properties[i].type == NULL)
                    returntype = "";
                else
                    returntype = one_desc->properties[i].type;

                /*
                index = jack_uuid_to_index(one_desc->subject)
                portid = jack_port_by_id(jii->client, index);
                portname = jack_port_name(port);
                */
                if (!cbox_execute_on(fb, NULL, "/all_properties", "ssss",
                        error,
                        jack_port_name(jack_port_by_id(jii->client, jack_uuid_to_index(one_desc->subject))),
                        one_desc->properties[i].key,
                        one_desc->properties[i].data,
                        returntype))
                    return FALSE;
            }
            jack_free_description(one_desc, 0); //if non-zero one_desc will also be passed to free()
        }
        jack_free(descs);
        return TRUE;
    }


    else if (!strcmp(cmd->command, "/remove_property") && !strcmp(cmd->arg_types, "ss"))
    {
        const char *name = CBOX_ARG_S(cmd, 0);
        const char *key = CBOX_ARG_S(cmd, 1);

        jack_uuid_t subject;
        if (!cbox_jack_io_get_jack_uuid_from_name(jii, name, &subject, error)) //error message set inside
            return FALSE;

        if (jack_remove_property(jii->client, subject, key)) // 0 on success, -1 otherwise
        {
            g_set_error(error, CBOX_MODULE_ERROR, CBOX_MODULE_ERROR_FAILED, "Could not remove port '%s' key '%s'", name, key);
            return FALSE;
        }
        return TRUE;
    }

    else if (!strcmp(cmd->command, "/remove_properties") && !strcmp(cmd->arg_types, "s"))
    {
        const char *name = CBOX_ARG_S(cmd, 0);

        jack_uuid_t subject;
        if (!cbox_jack_io_get_jack_uuid_from_name(jii, name, &subject, error)) //error message set inside
            return FALSE;

        if (jack_remove_properties(jii->client, subject) == -1) // number of removed properties returned, -1 on error
        {
            g_set_error(error, CBOX_MODULE_ERROR, CBOX_MODULE_ERROR_FAILED, "Could not remove properties of port '%s'", name);
            return FALSE;
        }
        return TRUE;
    }


    else if (!strcmp(cmd->command, "/remove_all_properties") && !strcmp(cmd->arg_types, ""))
    {
        if (jack_remove_all_properties(jii->client)) // 0 on success, -1 otherwise
        {
            g_set_error(error, CBOX_MODULE_ERROR, CBOX_MODULE_ERROR_FAILED, "Remove all JACK properties was not successful");
            return FALSE;
        }
        return TRUE;
    }

    else
    {
        gboolean result = cbox_io_process_cmd(io, fb, cmd, error, &handled);
        if (!handled)
            g_set_error(error, CBOX_MODULE_ERROR, CBOX_MODULE_ERROR_FAILED, "Unknown combination of target path and argument: '%s', '%s'", cmd->command, cmd->arg_types);
        return result;
    }
}
Exemple #7
0
static gboolean sampler_layer_process_cmd(struct cbox_command_target *ct, struct cbox_command_target *fb, struct cbox_osc_command *cmd, GError **error)
{
    struct sampler_layer *layer = ct->user_data;
    if (!strcmp(cmd->command, "/status") && !strcmp(cmd->arg_types, ""))
    {
        if (!cbox_check_fb_channel(fb, cmd->command, error))
            return FALSE;

        if (!((!layer->parent_program || cbox_execute_on(fb, NULL, "/parent_program", "o", error, layer->parent_program)) && 
            (!layer->parent_group || cbox_execute_on(fb, NULL, "/parent_group", "o", error, layer->parent_group)) && 
            CBOX_OBJECT_DEFAULT_STATUS(layer, fb, error)))
            return FALSE;
        return TRUE;
    }
    if ((!strcmp(cmd->command, "/as_string") || !strcmp(cmd->command, "/as_string_full")) && !strcmp(cmd->arg_types, ""))
    {
        if (!cbox_check_fb_channel(fb, cmd->command, error))
            return FALSE;
        gchar *res = sampler_layer_to_string(layer, !strcmp(cmd->command, "/as_string_full"));
        gboolean result = cbox_execute_on(fb, NULL, "/value", "s", error, res);
        g_free(res);
        return result;
    }
    if (!strcmp(cmd->command, "/set_param") && !strcmp(cmd->arg_types, "ss"))
    {
        const char *key = CBOX_ARG_S(cmd, 0);
        const char *value = CBOX_ARG_S(cmd, 1);
        if (sampler_layer_apply_param(layer, key, value, error))
        {
            sampler_layer_update(layer);
            sampler_program_update_layers(layer->parent_program);
            return TRUE;
        }
        return FALSE;
    }
    if (!strcmp(cmd->command, "/new_region") && !strcmp(cmd->arg_types, ""))
    {
        // XXXKF needs a string argument perhaps
        if (layer->parent_group)
        {
            g_set_error(error, CBOX_MODULE_ERROR, CBOX_MODULE_ERROR_FAILED, "Cannot create a region within a region");
            return FALSE;
        }
        struct sampler_layer *l = sampler_layer_new(layer->module, layer->parent_program, layer);
        sampler_layer_data_finalize(&l->data, l->parent_group ? &l->parent_group->data : NULL, layer->parent_program);
        sampler_layer_reset_switches(l, l->module);
        sampler_layer_update(l);

        sampler_program_add_layer(layer->parent_program, l);
        sampler_program_update_layers(layer->parent_program);
        
        return cbox_execute_on(fb, NULL, "/uuid", "o", error, l);
    }
    if (!strcmp(cmd->command, "/get_children") && !strcmp(cmd->arg_types, ""))
    {
        if (!cbox_check_fb_channel(fb, cmd->command, error))
            return FALSE;
        GHashTableIter iter;
        g_hash_table_iter_init(&iter, layer->child_layers);
        gpointer key, value;
        while(g_hash_table_iter_next(&iter, &key, &value))
        {
            if (!cbox_execute_on(fb, NULL, "/region", "o", error, key))
                return FALSE;
        }
        return TRUE;
    }
    // otherwise, treat just like an command on normal (non-aux) output
    return cbox_object_default_process_cmd(ct, fb, cmd, error);
    
}