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