Beispiel #1
0
// Attempt to connect to the Jack server
static PyObject* attach(PyObject* self, PyObject* args)
{
    char* cname;
    if (! PyArg_ParseTuple(args, "s", &cname))
        return NULL;

    pyjack_client_t * client = self_or_global_client(self);
    if(client->pjc != NULL) {
        PyErr_SetString(JackUsageError, "A connection is already established.");
        return NULL;
    }

    jack_status_t status;
    client->pjc = jack_client_open(cname, JackNoStartServer, &status);
    if(client->pjc == NULL) {
        //TODO check status
        PyErr_SetString(JackNotConnectedError, "Failed to connect to Jack audio server.");
        return NULL;
    }

    jack_on_shutdown(client->pjc, pyjack_shutdown, client);
    signal(SIGHUP, pyjack_hangup); // TODO: This just works with global clients

    if(jack_set_process_callback(client->pjc, pyjack_process, client) != 0) {
        PyErr_SetString(JackError, "Failed to set jack process callback.");
        return NULL;
    }

    if(jack_set_buffer_size_callback(client->pjc, pyjack_buffer_size_changed, client) != 0) {
        PyErr_SetString(JackError, "Failed to set jack buffer size callback.");
        return NULL;
    }

    if(jack_set_sample_rate_callback(client->pjc, pyjack_sample_rate_changed, client) != 0) {
        PyErr_SetString(JackError, "Failed to set jack sample rate callback.");
        return NULL;
    }

    if(jack_set_port_registration_callback(client->pjc, pyjack_port_registration, client) != 0) {
        PyErr_SetString(JackError, "Failed to set jack port registration callback.");
        return NULL;
    }

    if(jack_set_graph_order_callback(client->pjc, pyjack_graph_order, client) != 0) {
        PyErr_SetString(JackError, "Failed to set jack graph order callback.");
        return NULL;
    }

    if(jack_set_xrun_callback(client->pjc, pyjack_xrun, client) != 0) {
        PyErr_SetString(JackError, "Failed to set jack xrun callback.");
        return NULL;
    }

    // Get buffer size
    client->buffer_size = jack_get_buffer_size(client->pjc);

    // Success!
    Py_INCREF(Py_None);
    return Py_None;
}
static int start_jack(AVFormatContext *context, AVFormatParameters *params)
{
    JackData *self = context->priv_data;
    jack_status_t status;
    int i, test;
    double o, period;

    /* Register as a JACK client, using the context filename as client name. */
    self->client = jack_client_open(context->filename, JackNullOption, &status);
    if (!self->client) {
        av_log(context, AV_LOG_ERROR, "Unable to register as a JACK client\n");
        return AVERROR(EIO);
    }

    sem_init(&self->packet_count, 0, 0);

    self->sample_rate = jack_get_sample_rate(self->client);
    self->nports      = params->channels;
    self->ports       = av_malloc(self->nports * sizeof(*self->ports));
    self->buffer_size = jack_get_buffer_size(self->client);

    /* Register JACK ports */
    for (i = 0; i < self->nports; i++) {
        char str[16];
        snprintf(str, sizeof(str), "input_%d", i + 1);
        self->ports[i] = jack_port_register(self->client, str,
                                            JACK_DEFAULT_AUDIO_TYPE,
                                            JackPortIsInput, 0);
        if (!self->ports[i]) {
            av_log(context, AV_LOG_ERROR, "Unable to register port %s:%s\n",
                   context->filename, str);
            jack_client_close(self->client);
            return AVERROR(EIO);
        }
    }

    /* Register JACK callbacks */
    jack_set_process_callback(self->client, process_callback, self);
    jack_on_shutdown(self->client, shutdown_callback, self);
    jack_set_xrun_callback(self->client, xrun_callback, self);

    /* Create time filter */
    period            = (double) self->buffer_size / self->sample_rate;
    o                 = 2 * M_PI * 1.5 * period; /// bandwidth: 1.5Hz
    self->timefilter  = ff_timefilter_new (1.0 / self->sample_rate, sqrt(2 * o), o * o);

    /* Create FIFO buffers */
    self->filled_pkts = av_fifo_alloc(FIFO_PACKETS_NUM * sizeof(AVPacket));
    /* New packets FIFO with one extra packet for safety against underruns */
    self->new_pkts    = av_fifo_alloc((FIFO_PACKETS_NUM + 1) * sizeof(AVPacket));
    if ((test = supply_new_packets(self, context))) {
        jack_client_close(self->client);
        return test;
    }

    return 0;

}
Beispiel #3
0
    void open_client(std::string const & server_name, std::string const & name, uint32_t input_port_count,
                     uint32_t output_port_count, uint32_t blocksize)
    {
        blocksize_ = blocksize;

        /* open client */
        client = server_name.empty() ? jack_client_open(name.c_str(), JackNoStartServer, &status)
                                     : jack_client_open(name.c_str(), jack_options_t(JackNoStartServer | JackServerName),
                                                        &status, server_name.c_str());
        boost::atomic_thread_fence(boost::memory_order_release); // ensure visibility on other threads

        if (status & JackServerFailed)
            throw std::runtime_error("Unable to connect to JACK server");

        if (status & JackNameNotUnique) {
            const char * client_name = jack_get_client_name(client);
            std::cout << "unique client name: " << client_name << std::endl;
        }

        /* initialize callbacks */
        jack_set_thread_init_callback (client, jack_thread_init_callback, this);
        jack_set_process_callback (client, jack_process_callback, this);
        jack_set_xrun_callback(client, jack_xrun_callback, this);
        jack_on_info_shutdown(client, (JackInfoShutdownCallback)jack_on_info_shutdown_callback, NULL);

        /* register ports */
        input_ports.clear();
        for (uint32_t i = 0; i != input_port_count; ++i) {
            std::string portname ("input_");
            portname += std::to_string(i+1);
            jack_port_t * port =
                jack_port_register(client, portname.c_str(), JACK_DEFAULT_AUDIO_TYPE, JackPortIsInput, 0);
            input_ports.push_back(port);
        }
        input_channels = input_port_count;
        super::input_samples.resize(input_port_count);

        output_ports.clear();
        for (uint32_t i = 0; i != output_port_count; ++i) {
            std::string portname ("output_");
            portname += std::to_string(i+1);
            jack_port_t * port =
                jack_port_register(client, portname.c_str(), JACK_DEFAULT_AUDIO_TYPE, JackPortIsOutput, 0);
            output_ports.push_back(port);
        }
        output_channels = output_port_count;
        super::output_samples.resize(output_port_count);

        samplerate_ = jack_get_sample_rate(client);
        jack_frames = jack_get_buffer_size(client);

        if (jack_frames % blocksize_)
            throw std::runtime_error("Jack buffer size is not a multiple of blocksize");
    }
Beispiel #4
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;
}
void gojack_generic_callback_sync_destroy(struct gojack_generic_callback_sync *sync) {
    jack_set_freewheel_callback(sync->client, NULL, NULL);
    jack_set_buffer_size_callback(sync->client, NULL, NULL);
    jack_set_sample_rate_callback(sync->client, NULL, NULL);
    jack_set_client_registration_callback(sync->client, NULL, NULL);
    jack_set_port_registration_callback(sync->client, NULL, NULL);
    jack_set_port_connect_callback(sync->client, NULL, NULL);
    jack_set_port_rename_callback(sync->client, NULL, NULL);
    jack_set_graph_order_callback(sync->client, NULL, NULL);
    jack_set_xrun_callback(sync->client, NULL, NULL);
    jack_set_latency_callback(sync->client, NULL, NULL);
    cgo_callback_sync_destroy(sync->base);
    pthread_mutex_destroy(&sync->lock);
    free(sync);
}
Beispiel #6
0
AudioJACKTarget::AudioJACKTarget(AudioCallbackPlaySource *source) :
    AudioCallbackPlayTarget(source),
    m_client(0),
    m_bufferSize(0),
    m_sampleRate(0),
    m_done(false)
{
    JackOptions options = JackNullOption;
#ifdef HAVE_PORTAUDIO_2_0
    options = JackNoStartServer;
#endif
#ifdef HAVE_LIBPULSE
    options = JackNoStartServer;
#endif

    JackStatus status = JackStatus(0);
    m_client = jack_client_open(source->getClientName().toLocal8Bit().data(),
                                options, &status);
    
    if (!m_client) {
        std::cerr << "AudioJACKTarget: Failed to connect to JACK server: status code "
                  << status << std::endl;
        return;
    }

    m_bufferSize = jack_get_buffer_size(m_client);
    m_sampleRate = jack_get_sample_rate(m_client);

    jack_set_xrun_callback(m_client, xrunStatic, this);
    jack_set_process_callback(m_client, processStatic, this);

    if (jack_activate(m_client)) {
	std::cerr << "ERROR: AudioJACKTarget: Failed to activate JACK client"
		  << std::endl;
    }

    if (m_source) {
	sourceModelReplaced();
    }
    
    // Mainstream JACK (though not jackdmp) calls mlockall() to lock
    // down all memory for real-time operation.  That isn't a terribly
    // good idea in an application like this that may have very high
    // dynamic memory usage in other threads, as mlockall() applies
    // across all threads.  We're far better off undoing it here and
    // accepting the possible loss of true RT capability.
    MUNLOCKALL();
}
Beispiel #7
0
bool SC_JackDriver::DriverSetup(int* outNumSamples, double* outSampleRate)
{
	char* clientName = 0;
	char* serverName = 0;

	if (mWorld->hw->mInDeviceName && (strlen(mWorld->hw->mInDeviceName) > 0)) {
		// parse string <serverName>:<clientName>
		SC_StringParser sp(mWorld->hw->mInDeviceName, ':');
		if (!sp.AtEnd()) serverName = strdup(sp.NextToken());
		if (!sp.AtEnd()) clientName = strdup(sp.NextToken());
		if (clientName == 0) {
			// no semicolon found
			clientName = serverName;
			serverName = 0;
		} else if (strlen(clientName) == 0) {
			free(clientName);
			clientName = 0;
		}
	}

	mClient = jack_client_open(
		clientName ? clientName : kJackDefaultClientName,
		serverName ? JackServerName : JackNullOption,
		NULL, serverName);
	if (serverName) free(serverName); if (clientName) free(clientName);
	if (mClient == 0) return false;

	scprintf("%s: client name is '%s'\n", kJackDriverIdent, jack_get_client_name(mClient));

	// create jack I/O ports
	mInputList = new SC_JackPortList(mClient, mWorld->mNumInputs, JackPortIsInput);
	mOutputList = new SC_JackPortList(mClient, mWorld->mNumOutputs, JackPortIsOutput);

	// register callbacks
	jack_set_process_callback(mClient, sc_jack_process_cb, this);
	jack_set_buffer_size_callback(mClient, sc_jack_bufsize_cb, this);
	jack_set_sample_rate_callback(mClient, sc_jack_srate_cb, this);
	jack_set_graph_order_callback(mClient, sc_jack_graph_order_cb, this);
	jack_set_xrun_callback(mClient, sc_jack_xrun_cb, this);
	jack_on_shutdown(mClient, sc_jack_shutdown_cb, mWorld);

	*outNumSamples = (int)jack_get_buffer_size(mClient);
	*outSampleRate = (double)jack_get_sample_rate(mClient);

	return true;
}
Beispiel #8
0
// Initialise Jack related stuff
int init_jack( const char* client_name, jack_options_t jack_opt )
{
  jack_status_t status;

  // Register with Jack
  if ((client = jack_client_open(client_name, jack_opt, &status)) == 0) {
    rotter_fatal("Failed to start jack client: 0x%x", status);
    return -1;
  }
  rotter_info( "JACK client registered as '%s'.", jack_get_client_name( client ) );


  // Create our input port(s)
  if (channels==1) {
    if (!(inport[0] = jack_port_register(client, "mono", JACK_DEFAULT_AUDIO_TYPE, JackPortIsInput, 0))) {
      rotter_fatal("Cannot register mono input port.");
      return -1;
    }
  } else {
    if (!(inport[0] = jack_port_register(client, "left", JACK_DEFAULT_AUDIO_TYPE, JackPortIsInput, 0))) {
      rotter_fatal("Cannot register left input port.");
      return -1;
    }

    if (!(inport[1] = jack_port_register(client, "right", JACK_DEFAULT_AUDIO_TYPE, JackPortIsInput, 0))) {
      rotter_fatal( "Cannot register left input port.");
      return -1;
    }
  }

  // Register xrun callback
  jack_set_xrun_callback(client, xrun_callback_jack, client);

  // Register shutdown callback
  jack_on_shutdown(client, shutdown_callback_jack, NULL);

  // Register callback
  if (jack_set_process_callback(client, callback_jack, NULL)) {
    rotter_fatal( "Failed to set Jack process callback.");
    return -1;
  }

  // Success
  return 0;
}
struct gojack_generic_callback_sync * gojack_generic_callback_sync_create(jack_client_t *client) {
    struct gojack_generic_callback_sync *sync = (struct gojack_generic_callback_sync *) malloc(sizeof(struct gojack_generic_callback_sync));
    void *arg = (void *) sync;
    sync->base = cgo_callback_sync_create();
    cgo_callback_sync_set_log_callback(sync->base, &handle_log, NULL);
    pthread_mutex_init(&sync->lock, NULL);
    sync->client = client;
    jack_set_freewheel_callback(client, &handle_freewheel, arg);
    jack_set_buffer_size_callback(client, &handle_buffer_size, arg);
    //jack_set_sample_rate_callback(client, &handle_sample_rate, arg);
    jack_set_client_registration_callback(client, &handle_client_registration, arg);
    jack_set_port_registration_callback(client, &handle_port_registration, arg);
    jack_set_port_connect_callback(client, &handle_port_connect, arg);
    jack_set_port_rename_callback(client, &handle_port_rename, arg);
    jack_set_graph_order_callback(client, &handle_graph_order, arg);
    jack_set_xrun_callback(client, &handle_xrun, arg);
    //jack_set_latency_callback(client, &handle_latency, arg);
    return sync;
}
Beispiel #10
0
static SCM start_jack(void *data) {
	int i;
	char name[16];
	jack_status_t jstatus;
	jack_client = jack_client_open(client_name,
					JackServerName,
					&jstatus, server_name);
	if (jack_client == 0) {
		log_msg("JACK server not running?\n") ;
		cleanup();
		return SCM_UNSPECIFIED;
		}
	log_msg("JACK status: %04x\n", jstatus);
	if (jstatus & JackServerStarted)
		log_msg("\tserver started\n");
	if (jstatus & JackServerFailed)
		log_msg("\tcan't connect\n");
	if (jstatus & JackInitFailure)
		log_msg("\tcan't initialize client\n");
	client_name = (const char *)jack_get_client_name(jack_client);
	sampling_rate = jack_get_sample_rate(jack_client) ;
	period_frames = jack_get_buffer_size(jack_client);
	jack_set_error_function(jack_error);
	jack_set_info_function(jack_info);
	jack_set_xrun_callback(jack_client, jack_xrun, NULL);
	jack_set_process_callback(jack_client, mixmaster, NULL);
	jack_set_port_registration_callback(jack_client, check_ports, NULL);
	jack_on_shutdown(jack_client, jack_shutdown, 0);
	for (i = 0; i < QMX_CHANNELS; i++) {
		sprintf(name, "out%02d", i + 1);
		jack_cauldron[i] = jack_port_register(jack_client, name,
				JACK_DEFAULT_AUDIO_TYPE, JackPortIsOutput, 0);
		}
	if (jack_activate(jack_client)) {
		log_msg("Cannot activate client.\n");
		cleanup();
		return SCM_UNSPECIFIED;
		}
	log_msg("JACK client activated: '%s'\n", client_name);
	return SCM_UNSPECIFIED;
	}
Beispiel #11
0
int main(int argc, char **argv)
{
    int fd, black_keys;
    char *button;
    unsigned char axes = 2;
    unsigned char buttons = 2;

    if (argc < 2) {
        printf("Usage: %s [-black] <jsX device>\n", argv[0]);
        return 1;
    }

    black_keys = 0;
    if (argc == 3)
      if (argv[1][0] == '-')
        if (argv[1][1] == 'b') {
          black_keys = 1;
          if (debug) printf("Using black keys\n");
        }

    if (black_keys)
      fd = open(argv[2], O_RDONLY);
    else
      fd = open(argv[1], O_RDONLY);

    if (fd < 0) {
        perror("open(argv[x])");
        return 1;
    }

    client = jack_client_open("sixad-jack", JackNullOption, 0);

    if (client == NULL) {
        perror("jack_client_open()");
        return 1;
    }

    nframes = jack_get_buffer_size(client);
    output_port = jack_port_register(client, "midi_out", JACK_DEFAULT_MIDI_TYPE, JackPortIsOutput, 0);
    jack_set_process_callback(client, process_callback, 0);
    jack_set_xrun_callback(client, xrun_callback, 0);

    if (jack_activate(client)) {
        perror("jack_activate()");
        return 1;
    }

    ioctl(fd, JSIOCGAXES, &axes);
    ioctl(fd, JSIOCGBUTTONS, &buttons);

    axis = calloc(axes, sizeof(int));
    button = calloc(buttons, sizeof(char));

    int h;
    for (h=0; h<20; h++) {
      axis_prev_action[h] = 0;
      axis_prev_velocity[h] = 0;
    }
    oct = 0;

    while (1) {

        if (read(fd, &js, sizeof(struct js_event)) != sizeof(struct js_event)) {
            perror("read(stdin)");
            jack_client_close(client);
            return 1;
        }

        switch (js.type & ~JS_EVENT_INIT) {
        case JS_EVENT_BUTTON:
            button[js.number] = js.value;
            break;
        case JS_EVENT_AXIS:
            axis[js.number] = js.value;
            break;
        }

        do_jack(client, button, black_keys);

    }

    jack_client_close(client);

    return 0;
}
Beispiel #12
0
int jack_open_audio(int inchans, int outchans, int rate)
{
    int j;
    char port_name[80] = "";
    int client_iterator = 0;
    int new_jack = 0;
    int srate;
    jack_status_t status;

    jack_dio_error = 0;
    
    if ((inchans == 0) && (outchans == 0)) return 0;

    if (outchans > NUM_JACK_PORTS)
    {
        error("JACK: %d output ports not supported, setting to %d",
            outchans, NUM_JACK_PORTS);
        outchans = NUM_JACK_PORTS;
    }

    if (inchans > NUM_JACK_PORTS)
    {
        error("JACK: %d input ports not supported, setting to %d",
            inchans, NUM_JACK_PORTS);
        inchans = NUM_JACK_PORTS;
    }

    /* try to become a client of the JACK server */
    /* if no JACK server exists, start a default one
       (jack_client_open() does that for us... */
    if (!jack_client)
    {
        do {
            sprintf(port_name,"pure_data_%d",client_iterator);
            client_iterator++;
            /* do not try to start the jack-server...
               seems to make problems... */
            jack_client = jack_client_open(port_name,
                JackNoStartServer, &status, NULL);
            if (status & JackServerFailed)
            {
                error("JACK: unable to connect to JACK server");
                jack_client=NULL;
                break;
            }
        } while (status & JackNameNotUnique);

        if(status)
        {
            if (status & JackServerStarted)
            {
                post("JACK: started JACK server?");
            }
            else
            {
                post("JACK: jack returned status %d", status);
            }
        }
      
        if (!jack_client)
        { // jack spits out enough messages already, do not warn
            sys_inchannels = sys_outchannels = 0;
            return 1;
        }
      
        jack_get_clients();

        /* tell the JACK server to call `process()' whenever
           there is work to be done.
        */
      
        jack_set_process_callback (jack_client, process, 0);
      
        // jack_set_error_function (jack_error);
      
#ifdef JACK_XRUN
        jack_set_xrun_callback (jack_client, jack_xrun, NULL);
#endif
      
        /* tell the JACK server to call `srate()' whenever
           the sample rate of the system changes.
        */
      
        jack_set_sample_rate_callback (jack_client, jack_srate, 0);
      
      
        /* tell the JACK server to call `jack_shutdown()' if
           it ever shuts down, either entirely, or if it
           just decides to stop calling us.
        */
      
        jack_on_shutdown (jack_client, jack_shutdown, 0);
      
        for (j = 0; j < NUM_JACK_PORTS; j++)
        {
             input_port[j]=NULL;
             output_port[j] = NULL;
        }

        new_jack = 1;
    }

    /* display the current sample rate. once the client is activated
       (see below), you should rely on your own sample rate
       callback (see above) for this value.
    */
    
    srate = jack_get_sample_rate (jack_client);
    sys_dacsr = srate;
            
    /* create the ports */
    
    for (j = 0; j < inchans; j++)
    {
        sprintf(port_name, "input%d", j);
        if (!input_port[j])
            input_port[j] = jack_port_register(jack_client, port_name,
                JACK_DEFAULT_AUDIO_TYPE, JackPortIsInput, 0);
        if (!input_port[j])
        {
            error("JACK: can only register %d input ports "
                  "(instead of requested %d)",
                j, inchans);
            sys_inchannels = inchans = j;
            break;
        }
    }

    for (j = 0; j < outchans; j++)
    {
        sprintf(port_name, "output%d", j);
        if (!output_port[j])
            output_port[j] = jack_port_register(jack_client, port_name,
                JACK_DEFAULT_AUDIO_TYPE, JackPortIsOutput, 0);
        if (!output_port[j])
        {
            error("JACK: can only register %d output ports "
                  "(instead of requested %d)",
                j, outchans);
            sys_outchannels = outchans = j;
            break;
        }
    } 
    outport_count = outchans;

    /* tell the JACK server that we are ready to roll */

    if (new_jack)
    {
        if (jack_activate (jack_client))
        {
            error("JACK: cannot activate client");
            sys_inchannels = sys_outchannels = 0;
            return 1;
        }
        
        memset(jack_outbuf,0,sizeof(jack_outbuf));
        
        if (jack_client_names[0])
            jack_connect_ports(jack_client_names[0]);

        pthread_mutex_init(&jack_mutex,NULL);
        pthread_cond_init(&jack_sem,NULL);
    }
    return 0;
}
bool JackAudioInterface::go()
{
    // start JACK
    if (jack_server_is_running())
    {
        qDebug() << "JackAudioInterface::start Warning: JACK was already running" << endl;
    }
    else
    {
        qDebug() << "JackAudioInterface::start Starting JACK:" << endl;
        pid_t jackPID = start_jack(m_sampleRate, m_bufferSamples);
        qDebug() << "JackAudioInterface::start Finished starting JACK" << endl;
        if (jackPID >= 0)
        {
            qDebug() << "JackAudioInterface::start: Successfully started the JACK server with PID " << QString::number(jackPID) << endl;
        }
        else
        {
            qWarning() << "JackAudioInterface::start: Couldn't start JACK server" << endl;
            return false;
        }
    }
    
    // create a jack client
    if (!open_jack_client())
    {
        qWarning() << "JackAudioInterface::start Couldn't open JACK client" << endl;
        return false;
    }

    qDebug() << "JackAudioInterface::start opened JACK client" << endl;

    // check that buffer size and sample rate are correct
    if (jack_get_buffer_size(m_client) != m_bufferSamples || jack_get_sample_rate(m_client) != m_sampleRate)
    {
        qWarning() << "JackAudioInterface::start ERROR: JACK is running with incorrect parameters: sample rate = " << jack_get_sample_rate(m_client) << ", buffer size = " << jack_get_buffer_size(m_client) << endl;
        // TODO: how to communicate this error back to the app?
        return false;
    }
    
    qDebug() << "JackAudioInterface::start checked JACK parameters" << endl;

    // register jack callbacks
    jack_set_buffer_size_callback(m_client, JackAudioInterface::jack_buffer_size_changed, this);
    jack_set_process_callback(m_client, JackAudioInterface::jack_process, this);
    jack_set_sample_rate_callback(m_client, JackAudioInterface::jack_sample_rate_changed, this);
    jack_on_shutdown(m_client, JackAudioInterface::jack_shutdown, this);
    jack_set_xrun_callback(m_client, JackAudioInterface::jack_xrun, this);

    qDebug() << "JackAudioInterface::start registered JACK callbacks" << endl;

     // activate client (starts processing)
    if (jack_activate(m_client) != 0)
    {
        qDebug() << "JackAudioInterface::start Couldn't activate JACK client" << endl;
        return false;
    }

    qDebug() << "JackAudioInterface::start activated JACK client" << endl;
    return true;
}
Beispiel #14
0
int
jack_open_audio(int inchans, int outchans, int rate, t_audiocallback callback)
{
    int j;
    char port_name[80] = "";
    char client_name[80] = "";

    int client_iterator = 0;
    int new_jack = 0;
    int srate;
    jack_status_t status;

#ifdef __APPLE__
    if (!jack_client_open)
    {
        error("Can't open Jack (it seems not to be installed on this Mac)");
        return 1;
    }
#endif

    jack_dio_error = 0;

    if ((inchans == 0) && (outchans == 0)) return 0;

    if (outchans > MAX_JACK_PORTS) {
        error("JACK: %d output ports not supported, setting to %d",
            outchans, MAX_JACK_PORTS);
        outchans = MAX_JACK_PORTS;
    }

    if (inchans > MAX_JACK_PORTS) {
        error("JACK: %d input ports not supported, setting to %d",
            inchans, MAX_JACK_PORTS);
        inchans = MAX_JACK_PORTS;
    }

    /* try to become a client of the JACK server.  (If no JACK server exists,
        jack_client_open() will start uone up by default.  It's not clear
        whether or not this is desirable; see long Pd list thread started by
        yvan volochine, June 2013) */
    if (!jack_client) {
        do {
          sprintf(client_name,"pure_data_%d",client_iterator);
          client_iterator++;
          jack_client = jack_client_open (client_name, JackNoStartServer,
            &status, NULL);
          if (status & JackServerFailed) {
            error("JACK: unable to connect to JACK server.  Is JACK running?");
            jack_client=NULL;
            break;
          }
        } while (status & JackNameNotUnique);

        if(status) {
          if (status & JackServerStarted) {
            verbose(1, "JACK: started server");
          } else {
            error("JACK: server returned status %d", status);
          }
        }
        verbose(1, "JACK: started server as '%s'", client_name);

        if (!jack_client) {
            /* jack spits out enough messages already, do not warn */
            sys_inchannels = sys_outchannels = 0;
            return 1;
        }

        sys_inchannels = inchans;
        sys_outchannels = outchans;
        if (jack_inbuf)
            free(jack_inbuf);
        if (sys_inchannels)
            jack_inbuf = calloc(sizeof(t_sample), sys_inchannels * BUF_JACK);
        if (jack_outbuf)
            free(jack_outbuf);
        if (sys_outchannels)
            jack_outbuf = calloc(sizeof(t_sample), sys_outchannels * BUF_JACK);

        jack_get_clients();

        /* set JACK callback functions */

        jack_callback = callback;
        jack_set_process_callback(jack_client,
            (callback? callbackprocess : pollprocess), 0);

        jack_set_error_function (pd_jack_error_callback);

#ifdef JACK_XRUN
        jack_set_xrun_callback (jack_client, jack_xrun, NULL);
#endif

        /* tell the JACK server to call `srate()' whenever
           the sample rate of the system changes.
        */

        jack_set_sample_rate_callback (jack_client, jack_srate, 0);


        /* tell the JACK server to call `jack_shutdown()' if
           it ever shuts down, either entirely, or if it
           just decides to stop calling us.
        */

        jack_on_shutdown (jack_client, jack_shutdown, 0);

        for (j=0; j<sys_inchannels; j++)
             input_port[j]=NULL;
        for (j=0; j<sys_outchannels; j++)
             output_port[j] = NULL;

        new_jack = 1;
    }

    /* display the current sample rate. once the client is activated
       (see below), you should rely on your own sample rate
       callback (see above) for this value.
    */

    srate = jack_get_sample_rate (jack_client);
    sys_dacsr = srate;

    /* create the ports */

    for (j = 0; j < inchans; j++)
    {
        sprintf(port_name, "input%d", j);
        if (!input_port[j]) input_port[j] = jack_port_register (jack_client,
            port_name, JACK_DEFAULT_AUDIO_TYPE, JackPortIsInput, 0);
        if (!input_port[j])
        {
          error("JACK: can only register %d input ports (of %d requested)",
            j, inchans);
          sys_inchannels = inchans = j;
          break;
        }
    }

    for (j = 0; j < outchans; j++)
    {
        sprintf(port_name, "output%d", j);
        if (!output_port[j]) output_port[j] = jack_port_register (jack_client,
            port_name, JACK_DEFAULT_AUDIO_TYPE, JackPortIsOutput, 0);
        if (!output_port[j])
        {
          error("JACK: can only register %d output ports (of %d requested)",
            j, outchans);
          sys_outchannels = outchans = j;
          break;
        }
    }
    outport_count = outchans;

    /* tell the JACK server that we are ready to roll */

    if (new_jack)
    {
        if (jack_activate (jack_client)) {
            error("cannot activate client");
            sys_inchannels = sys_outchannels = 0;
            return 1;
        }

        for (j = 0; j < outchans; j++)
            memset(jack_outbuf + j * BUF_JACK, 0,
                BUF_JACK * sizeof(t_sample));

        if (jack_client_names[0])
            jack_connect_ports(jack_client_names[0]);

        pthread_mutex_init(&jack_mutex, NULL);
        pthread_cond_init(&jack_sem, NULL);
    }
    return 0;
}
int
main (int argc, char *argv[])
{
	const char **ports;
	const char *client_name;
	const char *server_name = NULL;
	jack_options_t options = JackNullOption;
	jack_status_t status;

	client_name = "jacktester";
	if (argc > 1) {
		chunksize = atoi (argv[1]);
		printf ("using chunksize of %d\n", chunksize);
	}

	/* open a client connection to the JACK server */

	client = jack_client_open (client_name, options, &status, server_name);
	if (client == NULL) {
		fprintf (stderr, "jack_client_open() failed, status = 0x%x\n",
			 status);
		if (status & JackServerFailed) {
			fprintf (stderr, "Unable to connect to JACK server\n");
		}
		exit (1);
	}
	if (status & JackServerStarted) {
		fprintf (stderr, "JACK server started\n");
	}
	if (status & JackNameNotUnique) {
		client_name = jack_get_client_name(client);
		fprintf (stderr, "unique name `%s' assigned\n", client_name);
	}

	/* tell the JACK server to call `process()' whenever
	   there is work to be done.
	*/

	jack_set_process_callback (client, process, 0);
	jack_set_xrun_callback (client, jack_xrun, 0);
	jack_on_shutdown (client, jack_shutdown, 0);

	/* create two ports */

	input_port = jack_port_register (client, "input",
					 JACK_DEFAULT_AUDIO_TYPE,
					 JackPortIsInput, 0);
	output_port = jack_port_register (client, "output",
					  JACK_DEFAULT_AUDIO_TYPE,
					  JackPortIsOutput, 0);

	if ((input_port == NULL) || (output_port == NULL)) {
		fprintf(stderr, "no more JACK ports available\n");
		exit (1);
	}

	at_loop_size = jack_get_sample_rate (client) * 2;
	if ((thechunk = (char *) malloc (chunksize)) == NULL) {
		fprintf (stderr, "cannot allocate chunk\n");
		exit (1);
	}

	/* Tell the JACK server that we are ready to roll.  Our
	 * process() callback will start running now. */

	if (jack_activate (client)) {
		fprintf (stderr, "cannot activate client");
		exit (1);
	}

	/* connect the ports. Note: you can't do this before the
	   client is activated, because we can't allow connections to
	   be made to clients that aren't running.
	*/

	ports = jack_get_ports (client, NULL, NULL,
				JackPortIsPhysical|JackPortIsOutput);
	if (ports == NULL) {
		fprintf(stderr, "no physical capture ports\n");
		exit (1);
	}

	if (jack_connect (client, ports[0], jack_port_name (input_port))) {
		fprintf (stderr, "cannot connect input ports\n");
	}

	free (ports);

	ports = jack_get_ports (client, NULL, NULL,
				JackPortIsPhysical|JackPortIsInput);
	if (ports == NULL) {
		fprintf(stderr, "no physical playback ports\n");
		exit (1);
	}

	if (jack_connect (client, jack_port_name (output_port), ports[0])) {
		fprintf (stderr, "cannot connect output ports\n");
	}

	free (ports);

	while (1) {
		sleep (1);
	}

	jack_client_close (client);
	exit (0);
}
Beispiel #16
0
static int instream_open_jack(struct SoundIoPrivate *si, struct SoundIoInStreamPrivate *is) {
    SoundIoInStream *instream = &is->pub;
    SoundIoInStreamJack *isj = &is->backend_data.jack;
    SoundIoJack *sij = &si->backend_data.jack;
    SoundIoDevice *device = instream->device;
    SoundIoDevicePrivate *dev = (SoundIoDevicePrivate *)device;
    SoundIoDeviceJack *dj = &dev->backend_data.jack;

    if (sij->is_shutdown)
        return SoundIoErrorBackendDisconnected;

    if (!instream->name)
        instream->name = "SoundIoInStream";

    instream->software_latency = device->software_latency_current;
    isj->period_size = sij->period_size;

    jack_status_t status;
    isj->client = jack_client_open(instream->name, JackNoStartServer, &status);
    if (!isj->client) {
        instream_destroy_jack(si, is);
        assert(!(status & JackInvalidOption));
        if (status & JackShmFailure)
            return SoundIoErrorSystemResources;
        if (status & JackNoSuchClient)
            return SoundIoErrorNoSuchClient;
        return SoundIoErrorOpeningDevice;
    }

    int err;
    if ((err = jack_set_process_callback(isj->client, instream_process_callback, is))) {
        instream_destroy_jack(si, is);
        return SoundIoErrorOpeningDevice;
    }
    if ((err = jack_set_buffer_size_callback(isj->client, instream_buffer_size_callback, is))) {
        instream_destroy_jack(si, is);
        return SoundIoErrorOpeningDevice;
    }
    if ((err = jack_set_sample_rate_callback(isj->client, instream_sample_rate_callback, is))) {
        instream_destroy_jack(si, is);
        return SoundIoErrorOpeningDevice;
    }
    if ((err = jack_set_xrun_callback(isj->client, instream_xrun_callback, is))) {
        instream_destroy_jack(si, is);
        return SoundIoErrorOpeningDevice;
    }
    jack_on_shutdown(isj->client, instream_shutdown_callback, is);

    jack_nframes_t max_port_latency = 0;

    // register ports and map channels
    int connected_count = 0;
    for (int ch = 0; ch < instream->layout.channel_count; ch += 1) {
        SoundIoChannelId my_channel_id = instream->layout.channels[ch];
        const char *channel_name = soundio_get_channel_name(my_channel_id);
        unsigned long flags = JackPortIsInput;
        if (!instream->non_terminal_hint)
            flags |= JackPortIsTerminal;
        jack_port_t *jport = jack_port_register(isj->client, channel_name, JACK_DEFAULT_AUDIO_TYPE, flags, 0);
        if (!jport) {
            instream_destroy_jack(si, is);
            return SoundIoErrorOpeningDevice;
        }
        SoundIoInStreamJackPort *isjp = &isj->ports[ch];
        isjp->dest_port = jport;
        // figure out which source port this connects to
        SoundIoDeviceJackPort *djp = find_port_matching_channel(device, my_channel_id);
        if (djp) {
            isjp->source_port_name = djp->full_name;
            isjp->source_port_name_len = djp->full_name_len;
            connected_count += 1;
            max_port_latency = max(max_port_latency, djp->latency_range.max);
        }
    }
    // If nothing got connected, channel layouts aren't working. Just send the
    // data in the order of the ports.
    if (connected_count == 0) {
        max_port_latency = 0;
        instream->layout_error = SoundIoErrorIncompatibleDevice;

        int ch_count = min(instream->layout.channel_count, dj->port_count);
        for (int ch = 0; ch < ch_count; ch += 1) {
            SoundIoInStreamJackPort *isjp = &isj->ports[ch];
            SoundIoDeviceJackPort *djp = &dj->ports[ch];
            isjp->source_port_name = djp->full_name;
            isjp->source_port_name_len = djp->full_name_len;
            max_port_latency = max(max_port_latency, djp->latency_range.max);
        }
    }

    isj->hardware_latency = max_port_latency / (double)instream->sample_rate;

    return 0;
}
Beispiel #17
0
int
main(int argc, char **argv)
{
    int jitter_plot[101];
    int latency_plot[101];
    int long_index = 0;
    struct option long_options[] = {
        {"help", 0, NULL, 'h'},
        {"message-size", 1, NULL, 'm'},
        {"samples", 1, NULL, 's'},
        {"timeout", 1, NULL, 't'}
    };
    size_t name_arg_count;
    size_t name_size;
    char *option_string = "hm:s:t:";
    int show_usage = 0;
    connections_established = 0;
    error_message = NULL;
    message_size = 3;
    program_name = argv[0];
    remote_in_port = 0;
    remote_out_port = 0;
    samples = 1024;
    timeout = 5;

    for (;;) {
        signed char c = getopt_long(argc, argv, option_string, long_options,
                             &long_index);
        switch (c) {
        case 'h':
            show_usage = 1;
            break;
        case 'm':
            message_size = parse_positive_number_arg(optarg, "message-size");
            break;
        case 's':
            samples = parse_positive_number_arg(optarg, "samples");
            break;
        case 't':
            timeout = parse_positive_number_arg(optarg, "timeout");
            break;
        default:
            {
                char *s = "'- '";
                s[2] = c;
                die(s, "invalid switch");
            }
        case -1:
            if (show_usage) {
                output_usage();
                exit(EXIT_SUCCESS);
            }
            goto parse_port_names;
        case 1:
            /* end of switch :) */
            ;
        }
    }
 parse_port_names:
    name_arg_count = argc - optind;
    switch (name_arg_count) {
    case 2:
        target_in_port_name = argv[optind + 1];
        target_out_port_name = argv[optind];
        break;
    case 0:
        target_in_port_name = 0;
        target_out_port_name = 0;
        break;
    default:
        output_usage();
        return EXIT_FAILURE;
    }
    name_size = jack_port_name_size();
    alias1 = malloc(name_size * sizeof(char));
    if (alias1 == NULL) {
        error_message = strerror(errno);
        error_source = "malloc";
        goto show_error;
    }
    alias2 = malloc(name_size * sizeof(char));
    if (alias2 == NULL) {
        error_message = strerror(errno);
        error_source = "malloc";
        goto free_alias1;
    }
    latency_values = malloc(sizeof(jack_nframes_t) * samples);
    if (latency_values == NULL) {
        error_message = strerror(errno);
        error_source = "malloc";
        goto free_alias2;
    }
    latency_time_values = malloc(sizeof(jack_time_t) * samples);
    if (latency_time_values == NULL) {
        error_message = strerror(errno);
        error_source = "malloc";
        goto free_latency_values;
    }
    message_1 = malloc(message_size * sizeof(jack_midi_data_t));
    if (message_1 == NULL) {
        error_message = strerror(errno);
        error_source = "malloc";
        goto free_latency_time_values;
    }
    message_2 = malloc(message_size * sizeof(jack_midi_data_t));
    if (message_2 == NULL) {
        error_message = strerror(errno);
        error_source = "malloc";
        goto free_message_1;
    }
    switch (message_size) {
    case 1:
        message_1[0] = 0xf6;
        message_2[0] = 0xfe;
        break;
    case 2:
        message_1[0] = 0xc0;
        message_1[1] = 0x00;
        message_2[0] = 0xd0;
        message_2[1] = 0x7f;
        break;
    case 3:
        message_1[0] = 0x80;
        message_1[1] = 0x00;
        message_1[2] = 0x00;
        message_2[0] = 0x90;
        message_2[1] = 0x7f;
        message_2[2] = 0x7f;
        break;
    default:
        message_1[0] = 0xf0;
        memset(message_1 + 1, 0,
               (message_size - 2) * sizeof(jack_midi_data_t));
        message_1[message_size - 1] = 0xf7;
        message_2[0] = 0xf0;
        memset(message_2 + 1, 0x7f,
               (message_size - 2) * sizeof(jack_midi_data_t));
        message_2[message_size - 1] = 0xf7;
    }
    client = jack_client_open(program_name, JackNullOption, NULL);
    if (client == NULL) {
        error_message = "failed to open JACK client";
        error_source = "jack_client_open";
        goto free_message_2;
    }
    in_port = jack_port_register(client, "in", JACK_DEFAULT_MIDI_TYPE,
                                 JackPortIsInput, 0);
    if (in_port == NULL) {
        error_message = "failed to register MIDI-in port";
        error_source = "jack_port_register";
        goto close_client;
    }
    out_port = jack_port_register(client, "out", JACK_DEFAULT_MIDI_TYPE,
                                  JackPortIsOutput, 0);
    if (out_port == NULL) {
        error_message = "failed to register MIDI-out port";
        error_source = "jack_port_register";
        goto unregister_in_port;
    }
    if (jack_set_process_callback(client, handle_process, NULL)) {
        error_message = "failed to set process callback";
        error_source = "jack_set_process_callback";
        goto unregister_out_port;
    }
    if (jack_set_xrun_callback(client, handle_xrun, NULL)) {
        error_message = "failed to set xrun callback";
        error_source = "jack_set_xrun_callback";
        goto unregister_out_port;
    }
    if (jack_set_port_connect_callback(client, handle_port_connection_change,
                                       NULL)) {
        error_message = "failed to set port connection callback";
        error_source = "jack_set_port_connect_callback";
        goto unregister_out_port;
    }
    jack_on_shutdown(client, handle_shutdown, NULL);
    jack_set_info_function(handle_info);
    process_state = 0;

    connect_semaphore = create_semaphore(0);
    if (connect_semaphore == NULL) {
        error_message = get_semaphore_error();
        error_source = "create_semaphore";
        goto unregister_out_port;
    }
    init_semaphore = create_semaphore(1);
    if (init_semaphore == NULL) {
        error_message = get_semaphore_error();
        error_source = "create_semaphore";
        goto destroy_connect_semaphore;;
    }
    process_semaphore = create_semaphore(2);
    if (process_semaphore == NULL) {
        error_message = get_semaphore_error();
        error_source = "create_semaphore";
        goto destroy_init_semaphore;
    }
    if (jack_activate(client)) {
        error_message = "could not activate client";
        error_source = "jack_activate";
        goto destroy_process_semaphore;
    }
    if (name_arg_count) {
        if (jack_connect(client, jack_port_name(out_port),
                         target_out_port_name)) {
            error_message = "could not connect MIDI out port";
            error_source = "jack_connect";
            goto deactivate_client;
        }
        if (jack_connect(client, target_in_port_name,
                         jack_port_name(in_port))) {
            error_message = "could not connect MIDI in port";
            error_source = "jack_connect";
            goto deactivate_client;
        }
    }
    if (! register_signal_handler(handle_signal)) {
        error_message = strerror(errno);
        error_source = "register_signal_handler";
        goto deactivate_client;
    }
    printf("Waiting for connections ...\n");
    if (wait_semaphore(connect_semaphore, 1) == -1) {
        error_message = get_semaphore_error();
        error_source = "wait_semaphore";
        goto deactivate_client;
    }
    if (connections_established) {
        printf("Waiting for test completion ...\n\n");
        if (wait_semaphore(process_semaphore, 1) == -1) {
            error_message = get_semaphore_error();
            error_source = "wait_semaphore";
            goto deactivate_client;
        }
    }
    if (! register_signal_handler(SIG_DFL)) {
        error_message = strerror(errno);
        error_source = "register_signal_handler";
        goto deactivate_client;
    }
    if (process_state == 2) {
        double average_latency = ((double) total_latency) / samples;
        double average_latency_time = total_latency_time / samples;
        size_t i;
        double latency_plot_offset =
            floor(((double) lowest_latency_time) / 100.0) / 10.0;
        double sample_rate = (double) jack_get_sample_rate(client);
        jack_nframes_t total_jitter = 0;
        jack_time_t total_jitter_time = 0;
        for (i = 0; i <= 100; i++) {
            jitter_plot[i] = 0;
            latency_plot[i] = 0;
        }
        for (i = 0; i < samples; i++) {
            double latency_time_value = (double) latency_time_values[i];
            double latency_plot_time =
                (latency_time_value / 1000.0) - latency_plot_offset;
            double jitter_time = ABS(average_latency_time -
                                     latency_time_value);
            if (latency_plot_time >= 10.0) {
                (latency_plot[100])++;
            } else {
                (latency_plot[(int) (latency_plot_time * 10.0)])++;
            }
            if (jitter_time >= 10000.0) {
                (jitter_plot[100])++;
            } else {
                (jitter_plot[(int) (jitter_time / 100.0)])++;
            }
            total_jitter += ABS(average_latency -
                                ((double) latency_values[i]));
            total_jitter_time += jitter_time;
        }
        printf("Reported out-port latency: %.2f-%.2f ms (%u-%u frames)\n"
               "Reported in-port latency: %.2f-%.2f ms (%u-%u frames)\n"
               "Average latency: %.2f ms (%.2f frames)\n"
               "Lowest latency: %.2f ms (%u frames)\n"
               "Highest latency: %.2f ms (%u frames)\n"
               "Peak MIDI jitter: %.2f ms (%u frames)\n"
               "Average MIDI jitter: %.2f ms (%.2f frames)\n",
               (out_latency_range.min / sample_rate) * 1000.0,
               (out_latency_range.max / sample_rate) * 1000.0,
               out_latency_range.min, out_latency_range.max,
               (in_latency_range.min / sample_rate) * 1000.0,
               (in_latency_range.max / sample_rate) * 1000.0,
               in_latency_range.min, in_latency_range.max,
               average_latency_time / 1000.0, average_latency,
               lowest_latency_time / 1000.0, lowest_latency,
               highest_latency_time / 1000.0, highest_latency,
               (highest_latency_time - lowest_latency_time) / 1000.0,
               highest_latency - lowest_latency,
               (total_jitter_time / 1000.0) / samples,
               ((double) total_jitter) / samples);
        printf("\nJitter Plot:\n");
        for (i = 0; i < 100; i++) {
            if (jitter_plot[i]) {
                printf("%.1f - %.1f ms: %d\n", ((float) i) / 10.0,
                       ((float) (i + 1)) / 10.0, jitter_plot[i]);
            }
        }
        if (jitter_plot[100]) {
            printf("     > 10 ms: %d\n", jitter_plot[100]);
        }
        printf("\nLatency Plot:\n");
        for (i = 0; i < 100; i++) {
            if (latency_plot[i]) {
                printf("%.1f - %.1f ms: %d\n",
                       latency_plot_offset + (((float) i) / 10.0),
                       latency_plot_offset + (((float) (i + 1)) / 10.0),
                       latency_plot[i]);
            }
        }
        if (latency_plot[100]) {
            printf("     > %.1f ms: %d\n", latency_plot_offset + 10.0,
                   latency_plot[100]);
        }
    }
 deactivate_client:
    jack_deactivate(client);
    printf("\nMessages sent: %d\nMessages received: %d\n", messages_sent,
           messages_received);
    if (unexpected_messages) {
        printf("Unexpected messages received: %d\n", unexpected_messages);
    }
    if (xrun_count) {
        printf("Xruns: %d\n", xrun_count);
    }
 destroy_process_semaphore:
    destroy_semaphore(process_semaphore, 2);
 destroy_init_semaphore:
    destroy_semaphore(init_semaphore, 1);
 destroy_connect_semaphore:
    destroy_semaphore(connect_semaphore, 0);
 unregister_out_port:
    jack_port_unregister(client, out_port);
 unregister_in_port:
    jack_port_unregister(client, in_port);
 close_client:
    jack_client_close(client);
 free_message_2:
    free(message_2);
 free_message_1:
    free(message_1);
 free_latency_time_values:
    free(latency_time_values);
 free_latency_values:
    free(latency_values);
 free_alias2:
    free(alias2);
 free_alias1:
    free(alias1);
    if (error_message != NULL) {
    show_error:
        output_error(error_source, error_message);
        exit(EXIT_FAILURE);
    }
    return EXIT_SUCCESS;
}
Beispiel #18
0
/*****************************************************************************
 *
 * JACK_INIT()
 *
 * Setup the jack client.
 *
 *****************************************************************************/
int
jack_init(void) {
    const char		*server_name = NULL;
    static char		client_name[32];
    jack_options_t	options = JackNoStartServer | JackUseExactName;
    jack_status_t	status = 0;

    if (debug) {
	fprintf (stderr, "Initializing JACK client from thread 0x%lx\n", pthread_self());
    }

    if (client != NULL) {
	if (debug) {
	    fprintf (stderr, "Warning: closing stale JACK client...\n");
	}
	jack_client_close (client);
	client = NULL;
    }

    /* open a client connection to the JACK server */
    for( phasex_instance = 0; phasex_instance != 16; phasex_instance++)
    {
    if(!phasex_instance) {
        snprintf (client_name, 32, "%s", phasex_title);
    }
    else {
        snprintf (client_name, 32, "%s-%02d", phasex_title, phasex_instance);
    }
    printf("Using client name %s\n", client_name);
    if (client = jack_client_open ((const char *)client_name, options, &status, server_name))
        break;
    }
    
    /* deal with non-unique client name */
    if (status & JackNameNotUnique) {
	fprintf (stderr, "Unable to start JACK client '%s'!\n", client_name);
	return 1;
    }

    /* deal with jack server problems */
    if (status & (JackServerFailed | JackServerError)) {
	if (debug) {
	    fprintf (stderr, "Unable to connect to JACK server.  Status = 0x%2.0x\n", status);
	}
	return 1;
    }

    /* deal with missing client */
    if (client == NULL) {
	if (debug) {
	    fprintf (stderr, "Unable to open JACK client.  Status = 0x%2.0x\n", status);
	}
	return 1;
    }

    /* callback for when jack shuts down (needs to be set as early as possible) */
    jack_on_shutdown (client, jack_shutdown_handler, 0);

    if (debug) {
	fprintf (stderr, "Unique JACK client name '%s' assigned.\n", client_name);
    }

    /* notify if we started jack server */
    if (status & JackServerStarted) {
	fprintf (stderr, "JACK server started.\n");
    }

    /* report realtime scheduling in JACK */
    if (debug) {
	if (jack_is_realtime (client)) {
	    fprintf (stderr, "JACK is running with realtime scheduling.\n");
	}
	else {
	    fprintf (stderr, "JACK is running without realtime scheduling.\n");
	}
    }

    /* get sample rate early and notify other threads */
    sample_rate = jack_get_sample_rate (client);

    if (debug) {
	fprintf (stderr, "JACK sample rate:  %d\n", sample_rate);
    }

    /* scale sample rate depending on mode */
    switch (sample_rate_mode) {
    case SAMPLE_RATE_UNDERSAMPLE:
	sample_rate /= 2;
	break;
    case SAMPLE_RATE_OVERSAMPLE:
	sample_rate *= 2;
	break;
    }

    /* set samplerate related vars */
    f_sample_rate = (sample_t)sample_rate;
    nyquist_freq  = (sample_t)(sample_rate / 2);
    wave_period   = (sample_t)(F_WAVEFORM_SIZE / (double)sample_rate);

    if (debug) {
	fprintf (stderr, "Internal sample rate:  %d\n", sample_rate);
    }

    /* callback for setting our sample rate when jack tells us to */
    jack_set_sample_rate_callback (client, jack_samplerate_handler, 0);

    /* now that we have the sample rate, signal anyone else who needs to know */
    pthread_mutex_lock (&sample_rate_mutex);
    pthread_cond_broadcast (&sample_rate_cond);
    pthread_mutex_unlock (&sample_rate_mutex);

    /* get buffer size */
    buffer_size = jack_get_buffer_size (client) * 2;
    if (buffer_size > (PHASEX_MAX_BUFSIZE / 2)) {
    	fprintf (stderr, "JACK requested buffer size:  %d.  Max is:  %d.\n",
		 buffer_size, (PHASEX_MAX_BUFSIZE / 2));
    	fprintf (stderr, "JACK buffer size exceeded.  Closing client...\n");
	jack_client_close (client);
	client = NULL;
	jack_running = 0;
	return 1;
    }
    buffer_full = buffer_size;
    if (debug) {
	fprintf (stderr, "JACK output buffer size:  %d.\n", buffer_size);
    }

    /* callback for setting our buffer size when jack tells us to */
    jack_set_buffer_size_callback (client, jack_bufsize_handler, 0);

    /* callback for dealing with xruns */
    jack_set_xrun_callback (client, jack_xrun_handler, 0);

    /* create ports */
    input_port1 = jack_port_register (client, "in_1",
				      JACK_DEFAULT_AUDIO_TYPE,
				      JackPortIsInput, 0);
    input_port2 = jack_port_register (client, "in_2",
				      JACK_DEFAULT_AUDIO_TYPE,
				      JackPortIsInput, 0);

    output_port1 = jack_port_register (client, "out_1",
				       JACK_DEFAULT_AUDIO_TYPE,
				       JackPortIsOutput, 0);
    output_port2 = jack_port_register (client, "out_2",
				       JACK_DEFAULT_AUDIO_TYPE,
				       JackPortIsOutput, 0);

    if ( (output_port1 == NULL) || (output_port2 == NULL) ||
	 (input_port1 == NULL) || (input_port2 == NULL) )
    {
	fprintf (stderr, "JACK has no output ports available.\n");
	jack_client_close (client);
	client = NULL;
	jack_running = 0;
	return 0;
    }

    /* set callback for jack to grab audio data */
    jack_set_process_callback (client, process_buffer, 0);

    return 0;
}
//================================================================
int main(int argc, char *argv[])
{
	//jack
	const char **ports;
	//jack_options_t options = JackNullOption;
	jack_status_t status;

//options struct was here

	if(argc-optind<1)
	{
		print_header("jack_audio_receive");
		fprintf(stderr, "Missing arguments, see --help.\n\n");
		exit(1);
	}

	int opt;
 	//do until command line options parsed
	while(1)
	{
		/* getopt_long stores the option index here. */
		int option_index=0;

		opt=getopt_long(argc, argv, "", long_options, &option_index);

		/* Detect the end of the options. */
		if(opt==-1)
		{
			break;
		}
		switch(opt)
		{
			case 0:

			 /* If this option set a flag, do nothing else now. */
			if(long_options[option_index].flag!=0)
			{
				break;
			}

			case 'h':
				print_header("jack_audio_receive");
				print_help();
				break;

			case 'v':
				print_version();
				break;

			case 'x':
				print_header("jack_audio_receive");
				check_lo_props(1);
				return 1;

			case 'o':
				output_port_count=atoi(optarg);

				if(output_port_count>max_channel_count)
				{
					output_port_count=max_channel_count;
				}
				port_count=fmin(input_port_count,output_port_count);
				break;

			case 'f':
				channel_offset=atoi(optarg);
				break;

			case 'y':
				bytes_per_sample=2;
				break;

			case 'n':
				client_name=optarg;
				break;

			case 's':
				server_name=optarg;
				jack_opts |= JackServerName;
				break;

			case 'b':
				pre_buffer_size=fmax(1,(uint64_t)atoll(optarg));
				break;

			case 'm':
				max_buffer_size=fmax(1,(uint64_t)atoll(optarg));
				break;

			case 'u':
				update_display_every_nth_cycle=fmax(1,(uint64_t)atoll(optarg));
				break;

			case 'l':
				receive_max=fmax(1,(uint64_t)atoll(optarg));
				test_mode=1;
				break;

			case 'a':
				io_host=optarg;
				break;

			case 'c':
				io_port=optarg;
				break;

			case 't':
				use_tcp=1;
				remote_tcp_server_port=optarg;
				break;

			case '?': //invalid commands
				/* getopt_long already printed an error message. */
				print_header("jack_audio_receive");
				fprintf(stderr, "Wrong arguments, see --help.\n\n");
				exit(1);

				break;
 	 
			default:
				break;
		 } //end switch op
	}//end while(1)


	//remaining non optional parameters listening port
	if(argc-optind!=1)
	{
		print_header("jack_audio_receive");
		fprintf(stderr, "Wrong arguments, see --help.\n\n");
		exit(1);
	}

	localPort=argv[optind];

	//for commuication with a gui / other controller / visualizer
	loio=lo_address_new_with_proto(LO_UDP, io_host, io_port);

	//if was set to use random port
	if(atoi(localPort)==0)
	{
		//for lo_server_thread_new_with_proto
		localPort=NULL;
	}

	//add osc hooks & start osc server early (~right after cmdline parsing)
	registerOSCMessagePatterns(localPort);

	lo_server_thread_start(lo_st);

	//read back port (in case of random)
	//could use 
	//int lo_server_thread_get_port(lo_server_thread st)
	const char *osc_server_url=lo_server_get_url(lo_server_thread_get_server(lo_st));
	localPort=lo_url_get_port(osc_server_url);
	//int lport=lo_server_thread_get_port(lo_st);

	//notify osc gui
	if(io_())
	{
		lo_message msgio=lo_message_new();
		lo_message_add_float(msgio, version);
		lo_message_add_float(msgio, format_version);
		lo_send_message(loio, "/startup", msgio);
		lo_message_free(msgio);
	}

	if(check_lo_props(0)>0)
	{
		return 1;
	}


	if(use_tcp==1)
	{
		lo_proto=LO_TCP;
	}

	if(shutup==0)
	{
		print_header("jack_audio_receive");

		if(output_port_count>max_channel_count)
		{
			fprintf(stderr,"/!\\ limiting playback ports to %d, sry\n",max_channel_count);
		}

		if(test_mode==1)
		{
			fprintf(stderr,"/!\\ limiting number of messages: %" PRId64 "\n",receive_max);
		}
	}

	//check for default jack server env var
	char *evar=getenv("JACK_DEFAULT_SERVER");
	if(evar==NULL || strlen(evar)<1)
	{
#ifndef _WIN
		unsetenv("JACK_DEFAULT_SERVER");
#endif
	}

	else if(server_name==NULL)
	{
		//use env var if no server was given with --sname
		server_name=evar;
	}

	if(server_name==NULL || strlen(server_name)<=0)
	{
		server_name="default";
	}

	if(client_name==NULL)
	{
		client_name="receive";
	}

	if(have_libjack()!=0)
	{
		fprintf(stderr,"/!\\ libjack not found (JACK not installed?). this is fatal: jack_audio_receive needs JACK to run.\n");
		io_quit("nolibjack");
		exit(1);
	}

	//initialize time
	gettimeofday(&tv, NULL);
	tt_prev.sec=tv.tv_sec;
	tt_prev.frac=tv.tv_usec;

	//create an array of input ports
	ioPortArray=(jack_port_t**) malloc(output_port_count * sizeof(jack_port_t*));

	//open a client connection to the JACK server
	client=jack_client_open(client_name, jack_opts, &status, server_name);
	if(client==NULL) 
		{
		fprintf(stderr,"jack_client_open() failed, status = 0x%2.0x\n", status);
		if(status & JackServerFailed) 
		{
			fprintf(stderr,"Unable to connect to JACK server.\n");
			io_quit("nojack");
		}
		exit(1);
	}

	if(use_tcp==1)
	{

		if(shutup==0)
		{
			fprintf(stderr,"receiving on TCP port: %s\n",localPort);
		}
	}
	else
	{
		if(shutup==0)
		{
			fprintf(stderr,"receiving on UDP port: %s\n",localPort);
	}
	}

	client_name=jack_get_client_name(client);

	if(shutup==0)
	{
		fprintf(stderr,"started JACK client '%s' on server '%s'\n",client_name,server_name);
		if(status & JackNameNotUnique) 
		{
			fprintf(stderr, "/!\\ name '%s' was automatically assigned\n", client_name);
		}
	}

	if(status & JackNameNotUnique) 
	{
		io_simple("/client_name_changed");
	}

	//print startup info

	read_jack_properties();

	if(shutup==0)
	{
		print_common_jack_properties();

		fprintf(stderr,"channels (playback): %d\n",output_port_count);
		fprintf(stderr,"channel offset: %d\n",channel_offset);

		print_bytes_per_sample();

		fprintf(stderr,"multi-channel period size: %d bytes\n",
			output_port_count*period_size*bytes_per_sample
		);

		char *strat="fill with zero (silence)";
		if(zero_on_underflow==0)
		{
			strat="re-use last available period";
		}

		fprintf(stderr,"underflow strategy: %s\n",strat);

		if(rebuffer_on_restart==1)
		{
			fprintf(stderr,"rebuffer on sender restart: yes\n");
		}
		else
		{
			fprintf(stderr,"rebuffer on sender restart: no\n");
		}

		if(rebuffer_on_underflow==1)
		{
			fprintf(stderr,"rebuffer on underflow: yes\n");
		}
		else
		{
			fprintf(stderr,"rebuffer on underflow: no\n");
		}

		if(allow_remote_buffer_control==1)
		{
			fprintf(stderr,"allow external buffer control: yes\n");
		}
		else
		{
			fprintf(stderr,"allow external buffer control: no\n");
		}

		if(close_on_incomp==1)
		{
			fprintf(stderr,"shutdown receiver when incompatible data received: yes\n");
		}
		else
		{
			fprintf(stderr,"shutdown receiver when incompatible data received: no\n");
		}

	}//end cond. print

	char buf[64];
	format_seconds(buf,(float)pre_buffer_size*period_size/(float)sample_rate);

	uint64_t rb_size_pre=pre_buffer_size*output_port_count*period_size*bytes_per_sample;

	if(shutup==0)
	{
		fprintf(stderr,"initial buffer size: %" PRId64 " mc periods (%s, %" PRId64 " bytes, %.2f MB)\n",
			pre_buffer_size,
			buf,
			rb_size_pre,
			(float)rb_size_pre/1000/1000
		);
	}
	buf[0]='\0';

	//ringbuffer size bytes
	uint64_t rb_size;

	//ringbuffer mc periods
	int max_buffer_mc_periods;

	//max given as param (user knows best. if pre=max, overflows are likely)
	if(max_buffer_size>0)
	{
		max_buffer_mc_periods=fmax(pre_buffer_size,max_buffer_size);
		rb_size=max_buffer_mc_periods
			*output_port_count*period_size*bytes_per_sample;
	}
	else //"auto"
	{
		//make max buffer 0.5 seconds larger than pre buffer
		max_buffer_mc_periods=pre_buffer_size+ceil(0.5*(float)sample_rate/period_size);
		rb_size=max_buffer_mc_periods
			*output_port_count*period_size*bytes_per_sample;
	}

	max_buffer_size=max_buffer_mc_periods;

	format_seconds(buf,(float)max_buffer_mc_periods*period_size/sample_rate);
	if(shutup==0)
	{
		fprintf(stderr,"allocated buffer size: %" PRId64 " mc periods (%s, %" PRId64 " bytes, %.2f MB)\n",
			max_buffer_size,
			buf,
			rb_size,
			(float)rb_size/1000/1000
		);
	}
	buf[0]='\0';

	io_dump_config();

	//====================================
	//main ringbuffer osc blobs -> jack output
	rb=jack_ringbuffer_create(rb_size);
	//helper ringbuffer: used when remote period size < local period size
	rb_helper=jack_ringbuffer_create(rb_size);

	if(rb==NULL)
	{
		fprintf(stderr,"could not create a ringbuffer with that size.\n");
		fprintf(stderr,"try --max <smaller size>.\n");
		io_quit("ringbuffer_too_large");
		exit(1);
	}

	//JACK will call process() for every cycle (given by JACK)
	//NULL could be config/data struct
	jack_set_process_callback(client, process, NULL);

	jack_set_xrun_callback(client, xrun_handler, NULL);

	//register hook to know when JACK shuts down or the connection 
	//was lost (i.e. client zombified)
	jack_on_shutdown(client, jack_shutdown_handler, 0);

	// Register each output port
	int port;
	for(port=0; port<output_port_count; port ++)
	{
		// Create port name
		char* portName;
		if(asprintf(&portName, "output_%d", (port+1)) < 0) 
		{
			fprintf(stderr,"Could not create portname for port %d", port);
			io_quit("port_error");
			exit(1);
		}

		// Register the output port
		ioPortArray[port]=jack_port_register(client, portName, JACK_DEFAULT_AUDIO_TYPE, JackPortIsOutput, 0);
		if(ioPortArray[port]==NULL) 
		{
			fprintf(stderr,"Could not create output port %d\n", (port+1));
			io_quit("port_error");
			exit(1);
		}
	}

	/* Tell the JACK server that we are ready to roll. Our
	 * process() callback will start running now. */
	if(jack_activate(client)) 
	{
		fprintf(stderr, "cannot activate client");
		io_quit("cannot_activate_client");
		exit(1);
	}

	/* Connect the ports. You can't do this before the client is
	 * activated, because we can't make connections to clients
	 * that aren't running. Note the confusing (but necessary)
	 * orientation of the driver backend ports: playback ports are
	 * "input" to the backend, and capture ports are "output" from
	 * it.
	 */
	//prevent to get physical midi ports
	const char* pat="audio";

	ports=jack_get_ports(client, NULL, pat, JackPortIsPhysical|JackPortIsInput);

	if(ports==NULL) 
	{
		if(shutup==0)		
		{
			fprintf(stderr,"no physical playback ports\n");
		}
		//exit(1);
	}
	
	if(autoconnect==1)
	{
		fprintf(stderr, "\n");

		int j=0;
		int i;
		for(i=0;i<output_port_count;i++)
		{
			if(ports[i]!=NULL 
				&& ioPortArray[j]!=NULL 
				&& jack_port_name(ioPortArray[j])!=NULL)
			{
				if(!jack_connect(client, jack_port_name(ioPortArray[j]), ports[i]))
				{
					if(shutup==0)
					{
						fprintf(stderr, "autoconnect: %s -> %s\n",
							jack_port_name(ioPortArray[j]),ports[i]
						);
					}
					io_simple_string_double("/autoconnect",jack_port_name(ioPortArray[j]),ports[i]);
					j++;
				}
				else
				{
					if(shutup==0)
					{
						fprintf(stderr, "autoconnect: failed: %s -> %s\n",
							jack_port_name(ioPortArray[j]),ports[i]
						);
					}
				}
			}
			else
			{
				//no more playback ports
				break;
			}
		}//end for all output ports

		if(shutup==0)
		{
			fprintf(stderr, "\n");
		}
	}

	free(ports);

	fflush(stderr);

	/* install a signal handler to properly quits jack client */
#ifndef _WIN
	signal(SIGQUIT, signal_handler);
	signal(SIGHUP, signal_handler);
#endif
	signal(SIGTERM, signal_handler);
	signal(SIGINT, signal_handler);

	if(use_tcp==1)
	{
		//10 MB max
		int desired_max_tcp_size=10000000;

		lo_server s=lo_server_thread_get_server(lo_st);
		int ret_set_size=lo_server_max_msg_size(s, desired_max_tcp_size);

		if(shutup==0)
		{
			printf("set tcp max size return: %d\n",ret_set_size);
			io_simple("/tcp_max_size_xxxx");
		}
	}

	not_yet_ready=0;

	io_simple("/start_main_loop");

	//run possibly forever until not interrupted by any means
	while(1) 
	{
		//possibly clean shutdown without any glitches
		if(shutdown_in_progress==1)
		{
			signal_handler(42);
		}
#ifdef WIN_
		Sleep(1000);
#else
		sleep(1);
#endif
	}

	exit(0);
}//end main
Beispiel #20
0
static void openJackStreams(RtJackGlobals *p)
{
    char    buf[256];
    int     i, j, k;
    CSOUND *csound = p->csound;

    /* connect to JACK server */
    p->client = jack_client_open(&(p->clientName[0]), JackNoStartServer, NULL);
    if (UNLIKELY(p->client == NULL))
      rtJack_Error(csound, -1, Str("could not connect to JACK server"));

    csound->system_sr(csound, jack_get_sample_rate(p->client));
    csound->Message(csound, "system sr: %f\n", csound->system_sr(csound,0));

    /* check consistency of parameters */
    if (UNLIKELY(p->nChannels < 1 || p->nChannels > 255))
      rtJack_Error(csound, -1, Str("invalid number of channels"));
    if (UNLIKELY(p->sampleRate < 1000 || p->sampleRate > 768000))
      rtJack_Error(csound, -1, Str("invalid sample rate"));
    if (UNLIKELY(p->sampleRate != (int) jack_get_sample_rate(p->client))) {
      snprintf(&(buf[0]), 256, Str("sample rate %d does not match "
                             "JACK sample rate %d"),
              p->sampleRate, (int) jack_get_sample_rate(p->client));
      rtJack_Error(p->csound, -1, &(buf[0]));
    }
    if (UNLIKELY(p->bufSize < 8 || p->bufSize > 32768))
      rtJack_Error(csound, -1, Str("invalid period size (-b)"));
    if (p->nBuffers < 2)
      p->nBuffers = 2;
    if (UNLIKELY((unsigned int) (p->nBuffers * p->bufSize) > (unsigned int) 65536))
      rtJack_Error(csound, -1, Str("invalid buffer size (-B)"));
    if (UNLIKELY(((p->nBuffers - 1) * p->bufSize)
                 < (int) jack_get_buffer_size(p->client)))
      rtJack_Error(csound, -1, Str("buffer size (-B) is too small"));

    /* register ports */
    rtJack_RegisterPorts(p);

    /* allocate ring buffers if not done yet */
    if (p->bufs == NULL)
      rtJack_AllocateBuffers(p);

    /* initialise ring buffers */
    p->csndBufCnt = 0;
    p->csndBufPos = 0;
    p->jackBufCnt = 0;
    p->jackBufPos = 0;
    for (i = 0; i < p->nBuffers; i++) {
      rtJack_TryLock(p->csound, &(p->bufs[i]->csndLock));
      rtJack_Unlock(p->csound, &(p->bufs[i]->jackLock));
      for (j = 0; j < p->nChannels; j++) {
        if (p->inputEnabled) {
          for (k = 0; k < p->bufSize; k++)
            p->bufs[i]->inBufs[j][k] = (jack_default_audio_sample_t) 0;
        }
        if (p->outputEnabled) {
          for (k = 0; k < p->bufSize; k++)
            p->bufs[i]->outBufs[j][k] = (jack_default_audio_sample_t) 0;
        }
      }
    }

    /* output port buffer pointer cache is invalid initially */
    if (p->outputEnabled)
      p->outPortBufs[0] = (jack_default_audio_sample_t*) NULL;

    /* register callback functions */
    if (UNLIKELY(jack_set_sample_rate_callback(p->client,
                                               sampleRateCallback, (void*) p)
                 != 0))
      rtJack_Error(csound, -1, Str("error setting sample rate callback"));
    if (UNLIKELY(jack_set_buffer_size_callback(p->client,
                                               bufferSizeCallback, (void*) p)
                 != 0))
      rtJack_Error(csound, -1, Str("error setting buffer size callback"));
#ifdef LINUX
    if (UNLIKELY(jack_set_freewheel_callback(p->client,
                                             freeWheelCallback, (void*) p)
                 != 0))
      rtJack_Error(csound, -1, Str("error setting freewheel callback"));
#endif
    if (UNLIKELY(jack_set_xrun_callback(p->client, xrunCallback, (void*) p) != 0))
      rtJack_Error(csound, -1, Str("error setting xrun callback"));
    jack_on_shutdown(p->client, shutDownCallback, (void*) p);
    if (UNLIKELY(jack_set_process_callback(p->client,
                                           processCallback, (void*) p) != 0))
      rtJack_Error(csound, -1, Str("error setting process callback"));

    /* activate client */
    if (UNLIKELY(jack_activate(p->client) != 0))
      rtJack_Error(csound, -1, Str("error activating JACK client"));

    /* connect ports if requested */
    if (p->inputEnabled) {
      char dev[128], *dev_final, *sp;
      {
        int i,n = listDevices(csound,NULL,0);
        CS_AUDIODEVICE *devs = (CS_AUDIODEVICE *)
                malloc(n*sizeof(CS_AUDIODEVICE));
        listDevices(csound,devs,0);
        for(i=0; i < n; i++)
          csound->Message(csound, " %d: %s (%s)\n",
                          i, devs[i].device_id, devs[i].device_name);
        strncpy(dev, devs[0].device_name, 128);
        free(devs);
      }
      if(p->inDevName != NULL) {
        strncpy(dev, p->inDevName, 128); dev[127]='\0';
      }
      //if (dev) {
      dev_final = dev;
      sp = strchr(dev_final, '\0');
      if (!isalpha(dev_final[0])) dev_final++;
      for (i = 0; i < p->nChannels; i++) {
        snprintf(sp, 128-(dev-sp), "%d", i + 1);
        if (UNLIKELY(jack_connect(p->client, dev_final,
                                  jack_port_name(p->inPorts[i])) != 0)) {
          //rtJack_Error(csound, -1, Str("error connecting input ports"));
          csound->Warning(csound,
                          Str("not autoconnecting input channel %d \n"
                              "(needs manual connection)"), i+1);
        }
      }
      *sp = (char) 0;
      //}

    }
    if (p->outputEnabled) {
      char dev[128], *dev_final, *sp;
      {
          int i,n = listDevices(csound,NULL,1);
          CS_AUDIODEVICE *devs = (CS_AUDIODEVICE *)
                  malloc(n*sizeof(CS_AUDIODEVICE));
          listDevices(csound,devs,1);
          for(i=0; i < n; i++)
            csound->Message(csound, " %d: %s (%s)\n",
                            i, devs[i].device_id, devs[i].device_name);
          strncpy(dev, devs[0].device_name, 128);
          free(devs);
      }
      if (p->outDevName != NULL) {
        strncpy(dev, p->outDevName, 128); dev[127]='\0';
      }
      //if (dev) { this test is rubbish
      dev_final = dev;
      sp = strchr(dev_final, '\0');
      if(!isalpha(dev_final[0])) dev_final++;
      for (i = 0; i < p->nChannels; i++) {
        snprintf(sp, 128-(dev-sp), "%d", i + 1);
        if (jack_connect(p->client, jack_port_name(p->outPorts[i]),
                         dev_final) != 0) {
          //rtJack_Error(csound, -1, Str("error connecting output ports"));
          csound->Warning(csound, Str("not autoconnecting input channel %d \n"
                                      "(needs manual connection)"), i+1);

        }
      }
      *sp = (char) 0;
    }
    /* stream is now active */
    p->jackState = 0;
}
Beispiel #21
0
void JACKInput::Init() {

	m_message_queue.Reset(RING_BUFFER_SIZE * m_channels * sizeof(float));

	m_jack_client = jack_client_open("SimpleScreenRecorder", JackNoStartServer, NULL);
	if(m_jack_client == NULL) {
		Logger::LogError("[JACKInput::Init] " + Logger::tr("Error: Could not connect to JACK!"));
		throw JACKException();
	}

	m_jack_ports.resize(m_channels, NULL);
	for(unsigned int i = 0; i < m_channels; ++i) {
		std::string port_name = "in_" + NumToString(i + 1);
		m_jack_ports[i] = jack_port_register(m_jack_client, port_name.c_str(), JACK_DEFAULT_AUDIO_TYPE, JackPortIsInput, 0);
		if(m_jack_ports[i] == NULL) {
			Logger::LogError("[JACKInput::Init] " + Logger::tr("Error: Could not create JACK port!"));
			throw JACKException();
		}
	}

	if(jack_set_process_callback(m_jack_client, ProcessCallback, this) != 0) {
		Logger::LogError("[JACKInput::Init] " + Logger::tr("Error: Could not set JACK process callback!"));
		throw JACKException();
	}
	if(jack_set_sample_rate_callback(m_jack_client, SampleRateCallback, this) != 0) {
		Logger::LogError("[JACKInput::Init] " + Logger::tr("Error: Could not set JACK sample rate callback!"));
		throw JACKException();
	}
	if(jack_set_xrun_callback(m_jack_client, XRunCallback, this) != 0) {
		Logger::LogError("[JACKInput::Init] " + Logger::tr("Error: Could not set JACK xrun callback!"));
		throw JACKException();
	}
	if(jack_set_port_connect_callback(m_jack_client, PortConnectCallback, this) != 0) {
		Logger::LogError("[JACKInput::Init] " + Logger::tr("Error: Could not set JACK port connect callback!"));
		throw JACKException();
	}

	if(jack_activate(m_jack_client) != 0) {
		Logger::LogError("[JACKInput::Init] " + Logger::tr("Error: Could not activate JACK client!"));
		throw JACKException();
	}

	for(unsigned int i = 0; i < m_channels; ++i) {
		std::string port_name_full = std::string(jack_get_client_name(m_jack_client)) + ":in_" + NumToString(i + 1);
		if(m_connect_system_capture) {
			std::string capture_name = "system:capture_" + NumToString(i + 1);
			Logger::LogInfo("[JACKInput::Init] " + Logger::tr("Connecting port %1 to %2.")
							.arg(QString::fromStdString(capture_name)).arg(QString::fromStdString(port_name_full)));
			jack_connect(m_jack_client, capture_name.c_str(), port_name_full.c_str());
		}
		if(m_connect_system_playback) {
			std::string playback_name = "system:playback_" + NumToString(i + 1);
			jack_port_t *port = jack_port_by_name(m_jack_client, playback_name.c_str());
			if(port != NULL) {
				const char **connected_ports = jack_port_get_all_connections(m_jack_client, port);
				if(connected_ports != NULL) {
					for(const char **p = connected_ports; *p != NULL; ++p) {
						Logger::LogInfo("[JACKInput::Init] " + Logger::tr("Connecting port %1 to %2.")
										.arg(*p).arg(QString::fromStdString(port_name_full)));
						jack_connect(m_jack_client, *p, port_name_full.c_str());
					}
					jack_free(connected_ports);
				}
			}
		}

	}

	// start input thread
	m_should_stop = false;
	m_error_occurred = false;
	m_thread = std::thread(&JACKInput::InputThread, this);

}