Example #1
0
static int
_jack_init(prog_t *handle, const char *id)
{
	jack_options_t opts = JackNullOption | JackNoStartServer;
	if(handle->server_name)
		opts |= JackServerName;
	if(handle->session_id)
		opts |= JackSessionID;

	jack_status_t status;
	if(!(handle->client = jack_client_open(id, opts, &status,
		handle->server_name ? handle->server_name : handle->session_id,
		handle->server_name ? handle->session_id : NULL)))
	{
		return -1;
	}

	//TODO check status

	// set client pretty name
#if defined(JACK_HAS_METADATA_API)
	jack_uuid_t uuid;
	const char *client_name = jack_get_client_name(handle->client);
	const char *uuid_str = jack_get_uuid_for_client_name(handle->client, client_name);
	if(uuid_str)
		jack_uuid_parse(uuid_str, &uuid);
	else
		jack_uuid_clear(&uuid);

	if(!jack_uuid_empty(uuid))
	{
		jack_set_property(handle->client, uuid,
			JACK_METADATA_PRETTY_NAME, "Synthpod", "text/plain");
	}
#endif

	// set client process callback
	if(jack_set_process_callback(handle->client, _process, handle))
		return -1;
	if(jack_set_session_callback(handle->client, _session, handle))
		return -1;
	if(jack_set_sample_rate_callback(handle->client, _sample_rate, handle))
		return -1;
	if(jack_set_buffer_size_callback(handle->client, _buffer_size, handle))
		return -1;
	jack_on_shutdown(handle->client, _shutdown, handle);
	jack_set_xrun_callback(handle->client, _xrun, handle);

	return 0;
}
Example #2
0
    bool
    Port::activate ( void )
    {
        /* assert( !_port ); */

        int flags = 0;
        
        if ( _direction == Output )
            flags |= JackPortIsOutput;
        else
            flags |= JackPortIsInput;

        if ( _terminal )
            flags |= JackPortIsTerminal;

        char jackname[max_name()];

        snprintf( jackname, sizeof(jackname), "%s%s%s", _trackname ? _trackname : "", _trackname ? "/" : "", _name );

        DMESSAGE( "Activating port name %s", jackname );
        _port = jack_port_register( _client->jack_client(), jackname,
                                    ( _type == Audio ) || ( _type == CV ) ? JACK_DEFAULT_AUDIO_TYPE : JACK_DEFAULT_MIDI_TYPE,
                                    flags,
                                    0 );

#ifdef HAVE_JACK_METADATA
        if ( _type == CV )
        {
                jack_uuid_t uuid = jack_port_uuid( _port );
                jack_set_property( _client->jack_client(), uuid, "http://jackaudio.org/metadata/signal-type", "CV", "text/plain" );
        }
#endif

        DMESSAGE( "Port = %p", _port );

        if ( ! _port )
            return false;

        _client->port_added( this );
 
        return true;
    }
Example #3
0
static void *
_system_port_add(void *data, system_port_t type, const char *short_name,
	const char *pretty_name, int input)
{
	bin_t *bin = data;
	prog_t *handle = (void *)bin - offsetof(prog_t, bin);
	
	//printf("_system_port_add: %s\n", short_name);

	jack_port_t *jack_port = NULL;

	unsigned long flags = input ? JackPortIsInput : JackPortIsOutput;

	switch(type)
	{
		case SYSTEM_PORT_NONE:
		{
			// skip
			break;
		}

		case SYSTEM_PORT_CONTROL:
		{
			// unsupported, skip
			break;
		}

		case SYSTEM_PORT_AUDIO:
		{
			jack_port = jack_port_register(handle->client, short_name,
				JACK_DEFAULT_AUDIO_TYPE, flags, 0);
			break;
		}
		case SYSTEM_PORT_CV:
		{
			jack_port = jack_port_register(handle->client, short_name,
				JACK_DEFAULT_AUDIO_TYPE, flags, 0);

#if defined(JACK_HAS_METADATA_API)
			if(jack_port)
			{
				jack_uuid_t uuid = jack_port_uuid(jack_port);
				if(!jack_uuid_empty(uuid))
				{
					jack_set_property(handle->client, uuid,
						"http://jackaudio.org/metadata/signal-type", "CV", "text/plain");
				}
			}
#endif
			break;
		}

		case SYSTEM_PORT_MIDI:
		{
			jack_port = jack_port_register(handle->client, short_name,
				JACK_DEFAULT_MIDI_TYPE, flags, 0);
			break;
		}
		case SYSTEM_PORT_OSC:
		{
			jack_port = jack_port_register(handle->client, short_name,
				JACK_DEFAULT_MIDI_TYPE, flags, 0);

#if defined(JACK_HAS_METADATA_API)
			if(jack_port)
			{
				jack_uuid_t uuid = jack_port_uuid(jack_port);
				if(!jack_uuid_empty(uuid))
				{
					jack_set_property(handle->client, uuid,
						"http://jackaudio.org/metadata/event-types", "OSC", "text/plain");
				}
			}
#endif
			break;
		}

		case SYSTEM_PORT_COM:
		{
			// unsupported, skip
			break;
		}
	}

#if defined(JACK_HAS_METADATA_API)
	if(jack_port && pretty_name)
	{
		jack_uuid_t uuid = jack_port_uuid(jack_port);
		if(!jack_uuid_empty(uuid))
		{
			jack_set_property(handle->client, uuid,
				JACK_METADATA_PRETTY_NAME, pretty_name, "text/plain");
		}
	}
#endif

	return jack_port;
}
Example #4
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;
    }
}