static size_t find_buffersize(jack_t *jd, int latency) { jack_latency_range_t range; int i, buffer_frames, min_buffer_frames, jack_latency = 0; settings_t *settings = config_get_ptr(); int frames = latency * settings->audio.out_rate / 1000; for (i = 0; i < 2; i++) { jack_port_get_latency_range(jd->ports[i], JackPlaybackLatency, &range); if ((int)range.max > jack_latency) jack_latency = range.max; } RARCH_LOG("JACK: Jack latency is %d frames.\n", jack_latency); buffer_frames = frames - jack_latency; min_buffer_frames = jack_get_buffer_size(jd->client) * 2; RARCH_LOG("JACK: Minimum buffer size is %d frames.\n", min_buffer_frames); if (buffer_frames < min_buffer_frames) buffer_frames = min_buffer_frames; return buffer_frames * sizeof(jack_default_audio_sample_t); }
// 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; }
int JackSimpleClient::setUp (int argc, char *argv[]) { LOGD("setUp argc %d", argc); for(int i = 0;i< argc; i++){ LOGD("setup argv %s", argv[i]); } // You have to use argv[0] as the jack client name like below. jackClient = jack_client_open (argv[0], JackNullOption, NULL, NULL); if (jackClient == NULL) { return APA_RETURN_ERROR; } bufferSize = jack_get_buffer_size(jackClient); // init the sine table for(int i=0; i<bufferSize; i++ ) { sineTable[i] = (float) sin( ((double)i*8/(double)bufferSize) * 2. * 3.14159265 ); } jack_set_process_callback (jackClient, processSine, this); outPort = jack_port_register (jackClient, "out", JACK_DEFAULT_AUDIO_TYPE, JackPortIsOutput, 0); if(outPort == NULL){ return APA_RETURN_ERROR; } return APA_RETURN_SUCCESS; }
int main(int argc, char *argv[]) { int rc; parse_arguments(argc, argv); /* become a JACK client */ if ((client = jack_client_open(package, JackNullOption, NULL)) == 0) { fprintf(stderr, "JACK server not running?\n"); exit(1); } #ifndef WIN32 signal(SIGQUIT, signal_handler); signal(SIGHUP, signal_handler); #endif signal(SIGTERM, signal_handler); signal(SIGINT, signal_handler); jack_on_shutdown(client, jack_shutdown, 0); if (just_print_bufsize) { fprintf(stdout, "buffer size = %d sample rate = %d\n", jack_get_buffer_size(client), jack_get_sample_rate(client)); rc=0; } else { rc = jack_set_buffer_size(client, nframes); if (rc) fprintf(stderr, "jack_set_buffer_size(): %s\n", strerror(rc)); } jack_client_close(client); return rc; }
JackAudioProvider(Synth *synth, const std::string &name) : synth_(synth) { SampleBufferAllocator::reset(); client_ = jack_client_open(name.c_str(), JackNoStartServer, 0); if (client_ == NULL) { throw JackClientOpenError(); } std::cout << "connected to jackd as client `" << name << "`\n"; sl::sampleRate(jack_get_sample_rate(client_)); jack_set_sample_rate_callback(client_, jackSampleRateCallback, 0); sl::bufferSize(jack_get_buffer_size(client_)); jack_set_buffer_size_callback(client_, jackBufferSizeCallback, 0); jack_set_process_callback(client_, jackProcessCallback, this); midiInPort_ = jack_port_register(client_, "midi_in", JACK_DEFAULT_MIDI_TYPE, JackPortIsInput, 0); std::cout << "registered midi port: midi_in\n"; char portName[64]; for (int i=0; i<Synth::InputBuffer::nChannels; i++) { snprintf(portName, sizeof(portName), "in_%u", i+1); inputPorts_[i] = jack_port_register(client_, portName, JACK_DEFAULT_AUDIO_TYPE, JackPortIsInput, 0); std::cout << "registered audio port: " << portName << "\n"; } for (int i=0; i<Synth::OutputBuffer::nChannels; i++) { snprintf(portName, sizeof(portName), "out_%u", i+1); outputPorts_[i] = jack_port_register(client_, portName, JACK_DEFAULT_AUDIO_TYPE, JackPortIsOutput, 0); std::cout << "registered audio port: " << portName << "\n"; } for (int i=0; i<128; i++) { midiCtrlMap_[i] = i; } for (int i=11; i<=19; i++) { midiCtrlMap_[i] = i-10; } midiCtrlMap_[1] = 129; // modwheel }
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 read_jack_properties() { sample_rate=jack_get_sample_rate(client); //! new: assume JACK is always 32 bit float //bytes_per_sample only refers to data transmission //param --16 will force to use 2 bytes //bytes_per_sample = sizeof(sample_t); period_size=jack_get_buffer_size(client); }
int JACKstart(HOR *hor_) { JackOUT=hor_; jackclient = jack_client_open("Horgand",options,&status,NULL);; if (jackclient == NULL) { fprintf (stderr, "Cannot make a jack client, back to Alsa\n"); return (2); }; JackOUT->SAMPLE_RATE=DSAMPLE_RATE; fprintf (stderr, "Internal SampleRate = %d\nJack Output SampleRate= %d\n", JackOUT->SAMPLE_RATE, jack_get_sample_rate (jackclient)); if ((unsigned int) jack_get_sample_rate (jackclient) != (unsigned int) JackOUT->SAMPLE_RATE) fprintf (stderr, "Adjusting SAMPLE_RATE to jackd.\n"); JackOUT->SAMPLE_RATE = jack_get_sample_rate(jackclient); JackOUT->PERIOD = jack_get_buffer_size (jackclient); JackOUT->Put_Period(); jack_set_process_callback (jackclient, jackprocess, 0); outport_left = jack_port_register (jackclient, "out_1", JACK_DEFAULT_AUDIO_TYPE, JackPortIsOutput | JackPortIsTerminal, 0); outport_right = jack_port_register (jackclient, "out_2", JACK_DEFAULT_AUDIO_TYPE, JackPortIsOutput | JackPortIsTerminal, 0); jack_midi_in = jack_port_register(jackclient, "in", JACK_DEFAULT_MIDI_TYPE, JackPortIsInput, 0); if (jack_activate (jackclient)) { fprintf (stderr, "Cannot activate jack client, back to Alsa\n"); return (2); }; jack_connect (jackclient, jack_port_name (outport_left), "alsa_pcm:playback_1"); jack_connect (jackclient, jack_port_name (outport_right), "alsa_pcm:playback_2"); pthread_mutex_init (&jmutex, NULL); return 3; };
int main(int narg, char **args) { int i; jack_nframes_t nframes; if((narg<6) || ((narg-3)%3 !=0)) { usage(); exit(1); } if((client = jack_client_open (args[1], JackNullOption, NULL)) == 0) { fprintf (stderr, "JACK server not running?\n"); return 1; } jack_set_process_callback (client, process, 0); output_port = jack_port_register (client, "out", JACK_DEFAULT_MIDI_TYPE, JackPortIsOutput, 0); nframes = jack_get_buffer_size(client); loop_index = 0; num_notes = (narg - 3)/3; note_frqs = malloc(num_notes*sizeof(unsigned char)); note_starts = malloc(num_notes*sizeof(jack_nframes_t)); note_lengths = malloc(num_notes*sizeof(jack_nframes_t)); loop_nsamp = atoi(args[2]); for(i=0; i<num_notes; i++) { note_starts[i] = atoi(args[3 + 3*i]); note_frqs[i] = atoi(args[4 + 3*i]); note_lengths[i] = atoi(args[5 + 3*i]); } if (jack_activate(client)) { fprintf (stderr, "cannot activate client"); return 1; } /* install a signal handler to properly quits jack client */ #ifndef WIN32 signal(SIGQUIT, signal_handler); signal(SIGHUP, signal_handler); #endif signal(SIGTERM, signal_handler); signal(SIGINT, signal_handler); /* run until interrupted */ while (1) { #ifdef WIN32 Sleep(1*1000); #else sleep(1); #endif }; jack_client_close(client); exit (0); }
int rmdStartJackClient(JackData *jdata){ float ring_buffer_size=0.0; int pid; char pidbuf[8]; char rmd_client_name[32]; //construct the jack client name //which is recordMyDesktop-pid //in order to allow multiple //instances of recordMyDesktop //to connetc to a Jack Server strcpy(rmd_client_name,"recordMyDesktop-"); pid=getpid(); snprintf( pidbuf, 8, "%d", pid ); strcat(rmd_client_name,pidbuf); if ((jdata->client=(*jack_client_new)(rmd_client_name))==0){ fprintf(stderr,"Could not create new client!\n" "Make sure that Jack server is running!\n"); return 15; } //in contrast to ALSA and OSS, Jack dictates frequency //and buffersize to the values it was launched with. //Supposedly jack_set_buffer_size can set the buffersize //but that causes some kind of halt and keeps giving me //zero buffers. //recordMyDesktop cannot handle buffer size changes. //FIXME //There is a callback for buffer size changes that I should use. //It will provide clean exits, instead of ?segfaults? . //Continuing though is not possible, with the current layout //(it might be in some cases, but it will certainly be the cause //of unpredicted problems). A clean exit is preferable //and any recording up to that point will be encoded and saved. jdata->frequency=jack_get_sample_rate(jdata->client); jdata->buffersize=jack_get_buffer_size(jdata->client); ring_buffer_size=(jdata->ringbuffer_secs* jdata->frequency* sizeof(jack_default_audio_sample_t)* jdata->nports); jdata->sound_buffer= (*jack_ringbuffer_create)((int)(ring_buffer_size+0.5));//round up jack_set_process_callback(jdata->client,rmdJackCapture,jdata); jack_on_shutdown(jdata->client,rmdJackShutdown,jdata); if (jack_activate(jdata->client)) { fprintf(stderr,"cannot activate client!\n"); return 16; } if(rmdSetupPorts(jdata)){ jack_client_close(jdata->client); return 17; } 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"); }
jack_raw_output::jack_raw_output (const char* client, const char* server, int rate, int channels, callback_type cb) : detail::async_base_impl (cb) , _out_ports (channels) , _buffer_size (0) { jack_set_error_function (log_jack_error); jack_set_info_function (log_jack_info); jack_options_t options = !server ? JackNullOption : JackServerName; _client = jack_client_open (client, options, 0, server); if (!_client) throw jack_open_error (); auto grd_client = base::make_guard ([&] { jack_client_close (_client); }); PSYNTH_JACK_CHECK (jack_set_process_callback ( _client, &jack_raw_output::_process_cb, this), jack_param_error); PSYNTH_JACK_CHECK (jack_set_sample_rate_callback ( _client, &jack_raw_output::_sample_rate_cb, this), jack_param_error); jack_on_shutdown (_client, &jack_raw_output::_shutdown_cb, this); _actual_rate = jack_get_sample_rate (_client); if (_actual_rate != rate) PSYNTH_LOG << base::log::warning << "Jackd sample rate and application sample rate mismatch." << "Better sound quality is achieved if both are the same."; _buffer_size = jack_get_buffer_size (_client); PSYNTH_LOG << base::log::info << "Jackd buffer size is: " << _buffer_size; for (size_t i = 0; i < _out_ports.size(); ++i) { std::string port_name = std::string ("out_") + boost::lexical_cast<std::string> (i); _out_ports [i] = jack_port_register ( _client, port_name.c_str (), JACK_DEFAULT_AUDIO_TYPE, JackPortIsOutput, 0); if (_out_ports [i] == 0) throw jack_param_error (); } grd_client.dismiss (); }
// stage 1 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - // JACK client initialization int jack_init(){ short i; char* client_name; jack_status_t status; client = jack_client_open (default_client_name, options, &status, default_server_name); if (client == NULL){ return 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 ); } char port_name[16]; jack_ports = (jack_port_t**)calloc(n_channels, sizeof(jack_port_t*)); if(amiserver){ for(i=0;i<n_channels;i++){ sprintf(port_name, "%s%d", default_in_port_basename, i+1); jack_ports[i] = jack_port_register(client, port_name, JACK_DEFAULT_AUDIO_TYPE, JackPortIsInput, 0); if(jack_ports[i] == NULL){ fprintf ( stderr, "no more JACK ports available\n" ); return 1; } } } else{ for(i=0;i<n_channels;i++){ sprintf(port_name, "%s%d", default_out_port_basename, i+1); jack_ports[i] = jack_port_register(client, port_name, JACK_DEFAULT_AUDIO_TYPE, JackPortIsOutput, 0); if(jack_ports[i] == NULL){ fprintf ( stderr, "no more JACK ports available\n" ); return 1; } } } bufsize = jack_get_buffer_size(client); printf("JACK Client initialized\n"); printf("JACK Buffer size = %d\n", bufsize); printf("Audio Channels %hd\n", n_channels); return 0; }
// get_buffer_size static PyObject* get_buffer_size(PyObject* self, PyObject* args) { pyjack_client_t * client = self_or_global_client(self); if(client->pjc == NULL) { PyErr_SetString(JackNotConnectedError, "Jack connection has not yet been established."); return NULL; } int bs = jack_get_buffer_size(client->pjc); return Py_BuildValue("i", bs); }
JackLayer::JackLayer(const AudioPreference &p) : AudioLayer(p), captureClient_(nullptr), playbackClient_(nullptr), out_ports_(), in_ports_(), out_ringbuffers_(), in_ringbuffers_(), ringbuffer_thread_(), //workerAlive_(false), ringbuffer_thread_mutex_(), data_ready_(), playbackBuffer_(0, audioFormat_), playbackFloatBuffer_(), captureBuffer_(0, audioFormat_), captureFloatBuffer_(), hardwareBufferSize_(0), mainRingBuffer_(Manager::instance().getRingBufferPool().getRingBuffer(RingBufferPool::DEFAULT_ID)) { playbackClient_ = jack_client_open(PACKAGE_NAME, (jack_options_t) (JackNullOption | JackNoStartServer), NULL); if (!playbackClient_) throw std::runtime_error("Could not open JACK client"); captureClient_ = jack_client_open(PACKAGE_NAME, (jack_options_t) (JackNullOption | JackNoStartServer), NULL); if (!captureClient_) throw std::runtime_error("Could not open JACK client"); jack_set_process_callback(captureClient_, process_capture, this); jack_set_process_callback(playbackClient_, process_playback, this); createPorts(playbackClient_, out_ports_, true, out_ringbuffers_); createPorts(captureClient_, in_ports_, false, in_ringbuffers_); const auto playRate = jack_get_sample_rate(playbackClient_); const auto captureRate = jack_get_sample_rate(captureClient_); if (playRate != captureRate) RING_ERR("Mismatch between capture rate %u and playback rate %u", playRate, captureRate); hardwareBufferSize_ = jack_get_buffer_size(playbackClient_); auto update_buffer = [] (AudioBuffer &buf, size_t size, unsigned rate, unsigned nbChannels) { buf.setSampleRate(rate); buf.resize(size); buf.setChannelNum(nbChannels); }; update_buffer(playbackBuffer_, hardwareBufferSize_, playRate, out_ports_.size()); update_buffer(captureBuffer_, hardwareBufferSize_, captureRate, in_ports_.size()); jack_on_shutdown(playbackClient_, onShutdown, this); }
bool JackClient::setup(volatile bool* p_runFlag, uint32_t nrOfFramesInRingBuffer) { m_p_runFlag = p_runFlag; const char *server_name = NULL; jack_options_t options = JackNoStartServer; jack_status_t status; // create a jack client m_p_jackClient = jack_client_open(s_jackClientName.c_str(), options, &status, server_name); if (m_p_jackClient == NULL) { DEBUG_PRINT("jack_client_open() failed, status = 0x%2.0x", status); if (status & JackServerFailed) { DEBUG_PRINT("unable to connect to JACK server"); } return false; } if (status & JackServerStarted) { DEBUG_PRINT("jack server up and running"); } if (status & JackNameNotUnique) { char* client_name = jack_get_client_name(m_p_jackClient); DEBUG_PRINT("unique name `%s' assigned", client_name); } // create ringbuffer m_p_ringBuffer = jack_ringbuffer_create(sizeof(jack_default_audio_sample_t) * jack_get_buffer_size(m_p_jackClient) * nrOfFramesInRingBuffer); if (m_p_ringBuffer == NULL) { DEBUG_PRINT("failed to create ringbuffer"); return false; } // setup callbacks int check; if ((check = jack_set_process_callback(m_p_jackClient, JackClient::processJackCallback, this))) { return false; } jack_on_shutdown(m_p_jackClient, JackClient::shutdownJackCallback, this); if ((check = jack_set_port_connect_callback(m_p_jackClient, JackClient::connectionJackCallback, this))) { return false; } if (!registerPorts()) { return false; } return true; }
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; }
int ja_initialize(SAMPLE srate, unsigned int input_channels, unsigned int output_channels, unsigned int nframes, const char* client_name) { sigset_t sset; (void) srate; (void) nframes; ja_error_msg[0] = '\0'; client = jack_client_open(client_name, JackNoStartServer, NULL); if (client == NULL) { ja_set_error_msg("jack_client_open failure"); return 1; } ja_frames = jack_get_buffer_size(client); ja_sample_rate = (SAMPLE) jack_get_sample_rate(client); ja_in_channels = input_channels; ja_out_channels = output_channels; ja_buffer_bytes = ja_frames * JA_SAMPLE_SIZE; ja_inputs = (jack_default_audio_sample_t **) malloc(sizeof(jack_default_audio_sample_t *) * input_channels); RETURN_IF_NULLPTR(ja_inputs, "malloc failure"); ja_outputs = (jack_default_audio_sample_t **) malloc(sizeof(jack_default_audio_sample_t *) * output_channels); RETURN_IF_NULLPTR(ja_outputs, "malloc failure"); if (ja_register_ports() != 0) return 1; jack_set_process_thread(client, ja_process_thread, NULL); jack_on_shutdown(client, ja_shutdown, NULL); /* Unblock signals */ sigemptyset(&sset); if (sigprocmask(SIG_SETMASK, &sset, NULL) < 0) { ja_error("Unblock signals error\n"); return 1; } ja_lisp_busy = 1; return 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; }
//------------------------------------------------------------------------------------------------------- bool JackVST::Open() { if (CheckClient()) { fInPorts = (jack_port_t**)malloc(sizeof(jack_port_t*)*MAX_PORTS); fOutPorts = (jack_port_t**)malloc(sizeof(jack_port_t*)*MAX_PORTS); fBufferSize = jack_get_buffer_size (fJackClient); fInPortsNum = fOutPortsNum = MAX_PORTS; // steph : are 32 buffers really needed?? int numBuff = 4; for(int i = 0; i < fInPortsNum; i++) { char newName[256]; sprintf(newName,"VSTreturn%d",fInstances+i+1); fInPorts[i] = jack_port_register(JackVST::fJackClient,newName,JACK_DEFAULT_AUDIO_TYPE,JackPortIsInput,0); printf("Port: %s created\n",newName); fRBufferIn[i] = (float*)malloc(sizeof(float)*fBufferSize*numBuff); if (RingBuffer_Init(&fRingBufferIn[i],fBufferSize*numBuff*sizeof(float),fRBufferIn[i])==-1) printf("error while creating ring buffer.\n"); } for(int i = 0; i < fOutPortsNum; i++) { char newName[256]; sprintf(newName,"VSTsend%d",fInstances+i+1); fOutPorts[i] = jack_port_register(JackVST::fJackClient,newName,JACK_DEFAULT_AUDIO_TYPE,JackPortIsOutput,0); printf("Port: %s created\n",newName); fRBufferOut[i] = (float*)malloc(sizeof(float)*fBufferSize*numBuff); if (RingBuffer_Init(&fRingBufferOut[i],fBufferSize*numBuff*sizeof(float),fRBufferOut[i])==-1) printf("error while creating ring buffer.\n"); } fStatus = kIsOn; fInstances += MAX_PORTS; JackVST::fPlugInList.push_front(this); jack_activate(JackVST::fJackClient); return true; }else{ return false; } }
int connect_to_jack(char *_str,int stereo) { if (debug) fprintf(stderr,"connect_to_jack(%s)",_str); if ((client=jack_client_open(_str,0,NULL)) == 0) { if (debug) fprintf (stderr, " [FAIL]\n"); return 1; } else if (debug) fprintf(stderr," [OK]\n"); jack_buf_size=jack_get_buffer_size(client); if (debug) fprintf(stderr,"jack buf_size=%lu\n",(unsigned long)jack_buf_size); jack_sample_rate=jack_get_sample_rate(client); if (debug) fprintf(stderr,"jack rate=%lu\n",(unsigned long)jack_sample_rate); if ((!jack_buf_size) || (!jack_sample_rate)) { fprintf(stderr,"bad buf_size or sample rate!\n"); exit(13); } if (stereo) jack_set_process_callback(client,output_mix_frame_stereo,0); else jack_set_process_callback(client,output_mix_frame_mono,0); jack_on_shutdown(client,jack_shutdown,0); // zero out audio buffers memset(audio_inp,0,sizeof(audio_inp)); memset(audio_out,0,sizeof(audio_out)); memset(mmdata,0,sizeof(mmdata)); audio_ird=(0-fft_size/2+MAX_SFRAG_SIZE)%MAX_SFRAG_SIZE; if (debug) printf("AUDIO LAG IN: audio_ird=%d = %d samples\n",audio_ird,fft_size/2); audio_ord=(0-fft_size/4+MAX_SFRAG_SIZE)%MAX_SFRAG_SIZE; if (debug) printf("AUDIO LAG OUT: audio_ord=%d = %d samples\n",audio_ord,fft_size/4); audio_roff=fft_size/2; if (debug) printf("AUDIO LAG REC: audio_roff=%d samples\n",audio_roff); load_data_window(audio_data_window); return 0; }
/** * Open and initialize connection to the JACK system. * * @param Parameters - optional parameters * @throws AudioOutputException on error * @see AcquireChannels() */ AudioOutputDeviceJack::AudioOutputDeviceJack(std::map<String,DeviceCreationParameter*> Parameters) : AudioOutputDevice(Parameters) { if (((DeviceCreationParameterString*)Parameters["NAME"])->ValueAsString().size() >= jack_client_name_size()) throw Exception("JACK client name too long"); if ((hJackClient = jack_client_new(((DeviceCreationParameterString*)Parameters["NAME"])->ValueAsString().c_str())) == 0) throw AudioOutputException("Seems Jack server not running."); existingJackDevices++; jack_set_process_callback(hJackClient, __libjack_process_callback, this); jack_on_shutdown(hJackClient, __libjack_shutdown_callback, this); if (jack_activate(hJackClient)) throw AudioOutputException("Jack: Cannot activate Jack client."); uiMaxSamplesPerCycle = jack_get_buffer_size(hJackClient); // create audio channels AcquireChannels(((DeviceCreationParameterInt*)Parameters["CHANNELS"])->ValueAsInt()); // finally activate device if desired if (((DeviceCreationParameterBool*)Parameters["ACTIVE"])->ValueAsBool()) Play(); }
int engine_jack_initialize(engine_t* engine){ if (!engine->device_name){ if (!(engine->device_name = strdup("soundtank"))){ printf("memory error allocating string\n"); return -1; } } /*try to become a client of the JACK server*/ if ((client = jack_client_new(engine->device_name)) == 0){ printf ("jack engine error: couldn't make jack client, jack server not running?\n"); return -1; } /*get sample rate*/ engine->sample_rate = jack_get_sample_rate(client); /*get period size (TODO: JACK does not guarantee a static period size however the current Soundtank code can't handle a change in the period size and will crash)*/ engine->period_size = jack_get_buffer_size(client); /*set callbacks used by jack server*/ if (jack_set_process_callback(client, soundtank_jack_process_callback, 0) < 0){ printf("jack engine error: could not set processing callback function\n"); return -1; } jack_on_shutdown(client, soundtank_jack_shutdown_callback, 0); /*engine is ready to go, set state variable to indicate so*/ engine->state = ENGINE_STATE_INACTIVE; return 0; }
static int _open(const char *path, const char *name, const char *id, void *data) { bin_t *bin = data; prog_t *handle = (void *)bin - offsetof(prog_t, bin); (void)name; if(bin->path) free(bin->path); bin->path = strdup(path); // jack init if(_jack_init(handle, id)) { bin->ui_driver.close(bin); return -1; } // synthpod init bin->app_driver.sample_rate = jack_get_sample_rate(handle->client); bin->app_driver.max_block_size = jack_get_buffer_size(handle->client); bin->app_driver.min_block_size = 1; bin->app_driver.seq_size = MAX(handle->seq_size, jack_port_type_get_buffer_size(handle->client, JACK_DEFAULT_MIDI_TYPE)); // app init bin->app = sp_app_new(NULL, &bin->app_driver, bin); // jack activate atomic_init(&handle->kill, 0); jack_activate(handle->client); //TODO check sp_ui_bundle_load(bin->ui, bin->path, 1); return 0; // success }
int main (int argc, char *argv[]) { /* Some startup related basics */ char *client_name, *server_name = NULL, *peer_ip; int peer_port = 3000; jack_options_t options = JackNullOption; jack_status_t status; #ifdef WIN32 WSADATA wsa; int rc = WSAStartup(MAKEWORD(2, 0), &wsa); #endif /* Torben's famous state variables, aka "the reporting API" ! */ /* heh ? these are only the copies of them ;) */ int statecopy_connected, statecopy_latency, statecopy_netxruns; jack_nframes_t net_period; /* Argument parsing stuff */ extern char *optarg; extern int optind, optopt; int errflg = 0, c; if (argc < 3) { printUsage (); return 1; } client_name = (char *) malloc (sizeof (char) * 10); peer_ip = (char *) malloc (sizeof (char) * 10); sprintf(client_name, "netjack"); sprintf(peer_ip, "localhost"); while ((c = getopt (argc, argv, ":h:H:o:i:O:I:n:p:r:B:b:c:m:R:e:N:s:P:")) != -1) { switch (c) { case 'h': printUsage(); exit (0); break; case 'H': free(peer_ip); peer_ip = (char *) malloc (sizeof (char) * strlen (optarg) + 1); strcpy (peer_ip, optarg); break; case 'o': playback_channels_audio = atoi (optarg); break; case 'i': capture_channels_audio = atoi (optarg); break; case 'O': playback_channels_midi = atoi (optarg); break; case 'I': capture_channels_midi = atoi (optarg); break; case 'n': latency = atoi (optarg); break; case 'p': peer_port = atoi (optarg); break; case 'r': reply_port = atoi (optarg); break; case 'B': bind_port = atoi (optarg); break; case 'f': factor = atoi (optarg); printf("This feature is deprecated and will be removed in future netjack versions. CELT offers a superiour way to conserve bandwidth"); break; case 'b': bitdepth = atoi (optarg); break; case 'c': #if HAVE_CELT bitdepth = 1000; factor = atoi (optarg); #else printf( "not built with celt support\n" ); exit(10); #endif break; case 'P': #if HAVE_OPUS bitdepth = 999; factor = atoi (optarg); #else printf( "not built with opus support\n" ); exit(10); #endif break; case 'm': mtu = atoi (optarg); break; case 'R': redundancy = atoi (optarg); break; case 'e': dont_htonl_floats = 1; break; case 'N': free(client_name); client_name = (char *) malloc (sizeof (char) * strlen (optarg) + 1); strcpy (client_name, optarg); break; case 's': server_name = (char *) malloc (sizeof (char) * strlen (optarg) + 1); strcpy (server_name, optarg); options |= JackServerName; break; case ':': fprintf (stderr, "Option -%c requires an operand\n", optopt); errflg++; break; case '?': fprintf (stderr, "Unrecognized option: -%c\n", optopt); errflg++; } } if (errflg) { printUsage (); exit (2); } capture_channels = capture_channels_audio + capture_channels_midi; playback_channels = playback_channels_audio + playback_channels_midi; outsockfd = socket (AF_INET, SOCK_DGRAM, 0); insockfd = socket (AF_INET, SOCK_DGRAM, 0); if ((outsockfd == -1) || (insockfd == -1)) { fprintf (stderr, "cant open sockets\n" ); return 1; } init_sockaddr_in ((struct sockaddr_in *) &destaddr, peer_ip, peer_port); if (bind_port) { init_sockaddr_in ((struct sockaddr_in *) &bindaddr, NULL, bind_port); if( bind (outsockfd, &bindaddr, sizeof (bindaddr)) ) { fprintf (stderr, "bind failure\n" ); } } if (reply_port) { init_sockaddr_in ((struct sockaddr_in *) &bindaddr, NULL, reply_port); if( bind (insockfd, &bindaddr, sizeof (bindaddr)) ) { fprintf (stderr, "bind failure\n" ); } } /* try to become a client of the JACK server */ client = jack_client_open (client_name, options, &status, server_name); if (client == NULL) { fprintf (stderr, "jack_client_open() failed, status = 0x%2.0x\n" "Is the JACK server running ?\n", status); return 1; } /* Set up jack callbacks */ jack_set_process_callback (client, process, 0); jack_set_sync_callback (client, sync_cb, 0); jack_set_freewheel_callback (client, freewheel_cb, 0); jack_on_shutdown (client, jack_shutdown, 0); alloc_ports (capture_channels_audio, playback_channels_audio, capture_channels_midi, playback_channels_midi); if( bitdepth == 1000 || bitdepth == 999) net_period = (factor * jack_get_buffer_size(client) * 1024 / jack_get_sample_rate(client) / 8) & (~1) ; else net_period = ceilf((float) jack_get_buffer_size (client) / (float) factor); int rx_bufsize = get_sample_size (bitdepth) * capture_channels * net_period + sizeof (jacknet_packet_header); packcache = packet_cache_new (latency + 50, rx_bufsize, mtu); /* tell the JACK server that we are ready to roll */ if (jack_activate (client)) { fprintf (stderr, "Cannot activate client"); return 1; } /* Now sleep forever... and evaluate the state_ vars */ signal( SIGTERM, sigterm_handler ); signal( SIGINT, sigterm_handler ); statecopy_connected = 2; // make it report unconnected on start. statecopy_latency = state_latency; statecopy_netxruns = state_netxruns; while ( !quit ) { #ifdef WIN32 Sleep (1000); #else sleep(1); #endif if (statecopy_connected != state_connected) { statecopy_connected = state_connected; if (statecopy_connected) { state_netxruns = 1; // We want to reset the netxrun count on each new connection printf ("Connected :-)\n"); } else printf ("Not Connected\n"); fflush(stdout); } if (statecopy_connected) { if (statecopy_netxruns != state_netxruns) { statecopy_netxruns = state_netxruns; printf ("%s: at frame %06d -> total netxruns %d (%d%%) queue time= %d\n", client_name, state_currentframe, statecopy_netxruns, 100 * statecopy_netxruns / state_currentframe, state_recv_packet_queue_time); fflush(stdout); } } else { if (statecopy_latency != state_latency) { statecopy_latency = state_latency; if (statecopy_latency > 1) printf ("current latency %d\n", statecopy_latency); fflush(stdout); } } } jack_client_close (client); packet_cache_free (packcache); exit (0); }
/** * The process callback for this JACK application. * It is called by JACK at the appropriate times. */ int process (jack_nframes_t nframes, void *arg) { jack_nframes_t net_period; int rx_bufsize, tx_bufsize; jack_default_audio_sample_t *buf; jack_port_t *port; JSList *node; int chn; int size, i; const char *porttype; int input_fd; jack_position_t local_trans_pos; uint32_t *packet_buf_tx, *packet_bufX; uint32_t *rx_packet_ptr; jack_time_t packet_recv_timestamp; if( bitdepth == 1000 || bitdepth == 999) net_period = (factor * jack_get_buffer_size(client) * 1024 / jack_get_sample_rate(client) / 8) & (~1) ; else net_period = (float) nframes / (float) factor; rx_bufsize = get_sample_size (bitdepth) * capture_channels * net_period + sizeof (jacknet_packet_header); tx_bufsize = get_sample_size (bitdepth) * playback_channels * net_period + sizeof (jacknet_packet_header); /* Allocate a buffer where both In and Out Buffer will fit */ packet_buf_tx = alloca (tx_bufsize); jacknet_packet_header *pkthdr_tx = (jacknet_packet_header *) packet_buf_tx; /* * for latency==0 we need to send out the packet before we wait on the reply. * but this introduces a cycle of latency, when netsource is connected to itself. * so we send out before read only in zero latency mode. * */ if( latency == 0 ) { /* reset packet_bufX... */ packet_bufX = packet_buf_tx + sizeof (jacknet_packet_header) / sizeof (jack_default_audio_sample_t); /* ---------- Send ---------- */ render_jack_ports_to_payload (bitdepth, playback_ports, playback_srcs, nframes, packet_bufX, net_period, dont_htonl_floats); /* fill in packet hdr */ pkthdr_tx->transport_state = jack_transport_query (client, &local_trans_pos); pkthdr_tx->transport_frame = local_trans_pos.frame; pkthdr_tx->framecnt = framecnt; pkthdr_tx->latency = latency; pkthdr_tx->reply_port = reply_port; pkthdr_tx->sample_rate = jack_get_sample_rate (client); pkthdr_tx->period_size = nframes; /* playback for us is capture on the other side */ pkthdr_tx->capture_channels_audio = playback_channels_audio; pkthdr_tx->playback_channels_audio = capture_channels_audio; pkthdr_tx->capture_channels_midi = playback_channels_midi; pkthdr_tx->playback_channels_midi = capture_channels_midi; pkthdr_tx->mtu = mtu; if( freewheeling != 0 ) pkthdr_tx->sync_state = (jack_nframes_t)MASTER_FREEWHEELS; else pkthdr_tx->sync_state = (jack_nframes_t)deadline_goodness; //printf("goodness=%d\n", deadline_goodness ); packet_header_hton (pkthdr_tx); if (cont_miss < 3 * latency + 5) { int r; for( r = 0; r < redundancy; r++ ) netjack_sendto (outsockfd, (char *) packet_buf_tx, tx_bufsize, 0, &destaddr, sizeof (destaddr), mtu); } else if (cont_miss > 50 + 5 * latency) { state_connected = 0; packet_cache_reset_master_address( packcache ); //printf ("Frame %d \tRealy too many packets missed (%d). Let's reset the counter\n", framecnt, cont_miss); cont_miss = 0; } } /* * ok... now the RECEIVE code. * */ if( reply_port ) input_fd = insockfd; else input_fd = outsockfd; // for latency == 0 we can poll. if( (latency == 0) || (freewheeling != 0) ) { jack_time_t deadline = jack_get_time() + 1000000 * jack_get_buffer_size(client) / jack_get_sample_rate(client); // Now loop until we get the right packet. while(1) { jack_nframes_t got_frame; if ( ! netjack_poll_deadline( input_fd, deadline ) ) break; packet_cache_drain_socket(packcache, input_fd); if (packet_cache_get_next_available_framecnt( packcache, framecnt - latency, &got_frame )) if( got_frame == (framecnt - latency) ) break; } } else { // normally: // only drain socket. packet_cache_drain_socket(packcache, input_fd); } size = packet_cache_retreive_packet_pointer( packcache, framecnt - latency, (char**)&rx_packet_ptr, rx_bufsize, &packet_recv_timestamp ); /* First alternative : we received what we expected. Render the data * to the JACK ports so it can be played. */ if (size == rx_bufsize) { uint32_t *packet_buf_rx = rx_packet_ptr; jacknet_packet_header *pkthdr_rx = (jacknet_packet_header *) packet_buf_rx; packet_bufX = packet_buf_rx + sizeof (jacknet_packet_header) / sizeof (jack_default_audio_sample_t); // calculate how much time there would have been, if this packet was sent at the deadline. int recv_time_offset = (int) (jack_get_time() - packet_recv_timestamp); packet_header_ntoh (pkthdr_rx); deadline_goodness = recv_time_offset - (int)pkthdr_rx->latency; //printf( "deadline goodness = %d ---> off: %d\n", deadline_goodness, recv_time_offset ); if (cont_miss) { //printf("Frame %d \tRecovered from dropouts\n", framecnt); cont_miss = 0; } render_payload_to_jack_ports (bitdepth, packet_bufX, net_period, capture_ports, capture_srcs, nframes, dont_htonl_floats); state_currentframe = framecnt; state_recv_packet_queue_time = recv_time_offset; state_connected = 1; sync_state = pkthdr_rx->sync_state; packet_cache_release_packet( packcache, framecnt - latency ); } /* Second alternative : we've received something that's not * as big as expected or we missed a packet. We render silence * to the ouput ports */ else { jack_nframes_t latency_estimate; if( packet_cache_find_latency( packcache, framecnt, &latency_estimate ) ) //if( (state_latency == 0) || (latency_estimate < state_latency) ) state_latency = latency_estimate; // Set the counters up. state_currentframe = framecnt; //state_latency = framecnt - pkthdr->framecnt; state_netxruns += 1; //printf ("Frame %d \tPacket missed or incomplete (expected: %d bytes, got: %d bytes)\n", framecnt, rx_bufsize, size); //printf ("Frame %d \tPacket missed or incomplete\n", framecnt); cont_miss += 1; chn = 0; node = capture_ports; while (node != NULL) { port = (jack_port_t *) node->data; buf = jack_port_get_buffer (port, nframes); porttype = jack_port_type (port); if (strncmp (porttype, JACK_DEFAULT_AUDIO_TYPE, jack_port_type_size ()) == 0) for (i = 0; i < nframes; i++) buf[i] = 0.0; else if (strncmp (porttype, JACK_DEFAULT_MIDI_TYPE, jack_port_type_size ()) == 0) jack_midi_clear_buffer (buf); node = jack_slist_next (node); chn++; } } if (latency != 0) { /* reset packet_bufX... */ packet_bufX = packet_buf_tx + sizeof (jacknet_packet_header) / sizeof (jack_default_audio_sample_t); /* ---------- Send ---------- */ render_jack_ports_to_payload (bitdepth, playback_ports, playback_srcs, nframes, packet_bufX, net_period, dont_htonl_floats); /* fill in packet hdr */ pkthdr_tx->transport_state = jack_transport_query (client, &local_trans_pos); pkthdr_tx->transport_frame = local_trans_pos.frame; pkthdr_tx->framecnt = framecnt; pkthdr_tx->latency = latency; pkthdr_tx->reply_port = reply_port; pkthdr_tx->sample_rate = jack_get_sample_rate (client); pkthdr_tx->period_size = nframes; /* playback for us is capture on the other side */ pkthdr_tx->capture_channels_audio = playback_channels_audio; pkthdr_tx->playback_channels_audio = capture_channels_audio; pkthdr_tx->capture_channels_midi = playback_channels_midi; pkthdr_tx->playback_channels_midi = capture_channels_midi; pkthdr_tx->mtu = mtu; if( freewheeling != 0 ) pkthdr_tx->sync_state = (jack_nframes_t)MASTER_FREEWHEELS; else pkthdr_tx->sync_state = (jack_nframes_t)deadline_goodness; //printf("goodness=%d\n", deadline_goodness ); packet_header_hton (pkthdr_tx); if (cont_miss < 3 * latency + 5) { int r; for( r = 0; r < redundancy; r++ ) netjack_sendto (outsockfd, (char *) packet_buf_tx, tx_bufsize, 0, &destaddr, sizeof (destaddr), mtu); } else if (cont_miss > 50 + 5 * latency) { state_connected = 0; packet_cache_reset_master_address( packcache ); //printf ("Frame %d \tRealy too many packets missed (%d). Let's reset the counter\n", framecnt, cont_miss); cont_miss = 0; } } framecnt++; return 0; }
/** * This Function allocates all the I/O Ports which are added the lists. */ void alloc_ports (int n_capture_audio, int n_playback_audio, int n_capture_midi, int n_playback_midi) { int port_flags = JackPortIsOutput; int chn; jack_port_t *port; char buf[32]; capture_ports = NULL; /* Allocate audio capture channels */ for (chn = 0; chn < n_capture_audio; chn++) { snprintf (buf, sizeof (buf) - 1, "capture_%u", chn + 1); port = jack_port_register (client, buf, JACK_DEFAULT_AUDIO_TYPE, port_flags, 0); if (!port) { printf( "jack_netsource: cannot register %s port\n", buf); break; } if (bitdepth == 1000) { #if HAVE_CELT #if HAVE_CELT_API_0_11 CELTMode *celt_mode = celt_mode_create( jack_get_sample_rate( client ), jack_get_buffer_size(client), NULL ); capture_srcs = jack_slist_append(capture_srcs, celt_decoder_create_custom( celt_mode, 1, NULL ) ); #elif HAVE_CELT_API_0_7 || HAVE_CELT_API_0_8 CELTMode *celt_mode = celt_mode_create( jack_get_sample_rate( client ), jack_get_buffer_size(client), NULL ); capture_srcs = jack_slist_append(capture_srcs, celt_decoder_create( celt_mode, 1, NULL ) ); #else CELTMode *celt_mode = celt_mode_create( jack_get_sample_rate( client ), 1, jack_get_buffer_size(client), NULL ); capture_srcs = jack_slist_append(capture_srcs, celt_decoder_create( celt_mode ) ); #endif #endif } else if (bitdepth == 999) { #if HAVE_OPUS int err; OpusCustomMode *opus_mode = opus_custom_mode_create(jack_get_sample_rate( client ), jack_get_buffer_size(client), &err); if (err != OPUS_OK) { printf("OPUS MODE FAILED\n"); } OpusCustomDecoder *decoder = opus_custom_decoder_create(opus_mode, 1, &err); if (err != OPUS_OK) { printf("OPUS DECODER FAILED\n"); } opus_custom_decoder_init(decoder, opus_mode, 1); capture_srcs = jack_slist_append(capture_srcs, decoder); #endif } else { #if HAVE_SAMPLERATE capture_srcs = jack_slist_append (capture_srcs, src_new (SRC_LINEAR, 1, NULL)); #endif } capture_ports = jack_slist_append (capture_ports, port); } /* Allocate midi capture channels */ for (chn = n_capture_audio; chn < n_capture_midi + n_capture_audio; chn++) { snprintf (buf, sizeof (buf) - 1, "capture_%u", chn + 1); port = jack_port_register (client, buf, JACK_DEFAULT_MIDI_TYPE, port_flags, 0); if (!port) { printf ("jack_netsource: cannot register %s port\n", buf); break; } capture_ports = jack_slist_append(capture_ports, port); } /* Allocate audio playback channels */ port_flags = JackPortIsInput; playback_ports = NULL; for (chn = 0; chn < n_playback_audio; chn++) { snprintf (buf, sizeof (buf) - 1, "playback_%u", chn + 1); port = jack_port_register (client, buf, JACK_DEFAULT_AUDIO_TYPE, port_flags, 0); if (!port) { printf ("jack_netsource: cannot register %s port\n", buf); break; } if( bitdepth == 1000 ) { #if HAVE_CELT #if HAVE_CELT_API_0_11 CELTMode *celt_mode = celt_mode_create( jack_get_sample_rate (client), jack_get_buffer_size(client), NULL ); playback_srcs = jack_slist_append(playback_srcs, celt_encoder_create_custom( celt_mode, 1, NULL ) ); #elif HAVE_CELT_API_0_7 || HAVE_CELT_API_0_8 CELTMode *celt_mode = celt_mode_create( jack_get_sample_rate (client), jack_get_buffer_size(client), NULL ); playback_srcs = jack_slist_append(playback_srcs, celt_encoder_create( celt_mode, 1, NULL ) ); #else CELTMode *celt_mode = celt_mode_create( jack_get_sample_rate (client), 1, jack_get_buffer_size(client), NULL ); playback_srcs = jack_slist_append(playback_srcs, celt_encoder_create( celt_mode ) ); #endif #endif } else if( bitdepth == 999 ) { #if HAVE_OPUS const int kbps = factor; printf("new opus encoder %d kbps\n", kbps); int err; OpusCustomMode *opus_mode = opus_custom_mode_create(jack_get_sample_rate (client), jack_get_buffer_size(client), &err ); // XXX free me if (err != OPUS_OK) { printf("OPUS MODE FAILED\n"); } OpusCustomEncoder *oe = opus_custom_encoder_create( opus_mode, 1, &err ); if (err != OPUS_OK) { printf("OPUS ENCODER FAILED\n"); } opus_custom_encoder_ctl(oe, OPUS_SET_BITRATE(kbps*1024)); // bits per second opus_custom_encoder_ctl(oe, OPUS_SET_COMPLEXITY(10)); opus_custom_encoder_ctl(oe, OPUS_SET_SIGNAL(OPUS_SIGNAL_MUSIC)); opus_custom_encoder_ctl(oe, OPUS_SET_SIGNAL(OPUS_APPLICATION_RESTRICTED_LOWDELAY)); opus_custom_encoder_init(oe, opus_mode, 1); playback_srcs = jack_slist_append(playback_srcs, oe); #endif } else { #if HAVE_SAMPLERATE playback_srcs = jack_slist_append (playback_srcs, src_new (SRC_LINEAR, 1, NULL)); #endif } playback_ports = jack_slist_append (playback_ports, port); } /* Allocate midi playback channels */ for (chn = n_playback_audio; chn < n_playback_midi + n_playback_audio; chn++) { snprintf (buf, sizeof (buf) - 1, "playback_%u", chn + 1); port = jack_port_register (client, buf, JACK_DEFAULT_MIDI_TYPE, port_flags, 0); if (!port) { printf ("jack_netsource: cannot register %s port\n", buf); break; } playback_ports = jack_slist_append (playback_ports, port); } }
/* allocate a buffer and setup resources to process the audio samples of * the format as specified in @spec. * * We allocate N jack ports, one for each channel. If we are asked to * automatically make a connection with physical ports, we connect as many * ports as there are physical ports, leaving leftover ports unconnected. * * It is assumed that samplerate and number of channels are acceptable since our * getcaps method will always provide correct values. If unacceptable caps are * received for some reason, we fail here. */ static gboolean gst_jack_ring_buffer_acquire (GstRingBuffer * buf, GstRingBufferSpec * spec) { GstJackAudioSrc *src; GstJackRingBuffer *abuf; const char **ports; gint sample_rate, buffer_size; gint i, channels, res; jack_client_t *client; src = GST_JACK_AUDIO_SRC (GST_OBJECT_PARENT (buf)); abuf = GST_JACK_RING_BUFFER_CAST (buf); GST_DEBUG_OBJECT (src, "acquire"); client = gst_jack_audio_client_get_client (src->client); /* sample rate must be that of the server */ sample_rate = jack_get_sample_rate (client); if (sample_rate != spec->rate) goto wrong_samplerate; channels = spec->channels; if (!gst_jack_audio_src_allocate_channels (src, channels)) goto out_of_ports; buffer_size = jack_get_buffer_size (client); /* the segment size in bytes, this is large enough to hold a buffer of 32bit floats * for all channels */ spec->segsize = buffer_size * sizeof (gfloat) * channels; spec->latency_time = gst_util_uint64_scale (spec->segsize, (GST_SECOND / GST_USECOND), spec->rate * spec->bytes_per_sample); /* segtotal based on buffer-time latency */ spec->segtotal = spec->buffer_time / spec->latency_time; GST_DEBUG_OBJECT (src, "segsize %d, segtotal %d", spec->segsize, spec->segtotal); /* allocate the ringbuffer memory now */ buf->data = gst_buffer_new_and_alloc (spec->segtotal * spec->segsize); memset (GST_BUFFER_DATA (buf->data), 0, GST_BUFFER_SIZE (buf->data)); if ((res = gst_jack_audio_client_set_active (src->client, TRUE))) goto could_not_activate; /* if we need to automatically connect the ports, do so now. We must do this * after activating the client. */ if (src->connect == GST_JACK_CONNECT_AUTO) { /* find all the physical output ports. A physical output port is a port * associated with a hardware device. Someone needs connect to a physical * port in order to capture something. */ ports = jack_get_ports (client, NULL, NULL, JackPortIsPhysical | JackPortIsOutput); if (ports == NULL) { /* no ports? fine then we don't do anything except for posting a warning * message. */ GST_ELEMENT_WARNING (src, RESOURCE, NOT_FOUND, (NULL), ("No physical output ports found, leaving ports unconnected")); goto done; } for (i = 0; i < channels; i++) { /* stop when all output ports are exhausted */ if (ports[i] == NULL) { /* post a warning that we could not connect all ports */ GST_ELEMENT_WARNING (src, RESOURCE, NOT_FOUND, (NULL), ("No more physical ports, leaving some ports unconnected")); break; } GST_DEBUG_OBJECT (src, "try connecting to %s", jack_port_name (src->ports[i])); /* connect the physical port to a port */ res = jack_connect (client, ports[i], jack_port_name (src->ports[i])); g_print ("connecting to %s\n", jack_port_name (src->ports[i])); if (res != 0 && res != EEXIST) goto cannot_connect; } free (ports); } done: abuf->sample_rate = sample_rate; abuf->buffer_size = buffer_size; abuf->channels = spec->channels; return TRUE; /* ERRORS */ wrong_samplerate: { GST_ELEMENT_ERROR (src, RESOURCE, SETTINGS, (NULL), ("Wrong samplerate, server is running at %d and we received %d", sample_rate, spec->rate)); return FALSE; } out_of_ports: { GST_ELEMENT_ERROR (src, RESOURCE, SETTINGS, (NULL), ("Cannot allocate more Jack ports")); return FALSE; } could_not_activate: { GST_ELEMENT_ERROR (src, RESOURCE, SETTINGS, (NULL), ("Could not activate client (%d:%s)", res, g_strerror (res))); return FALSE; } cannot_connect: { GST_ELEMENT_ERROR (src, RESOURCE, SETTINGS, (NULL), ("Could not connect input ports to physical ports (%d:%s)", res, g_strerror (res))); free (ports); return FALSE; } }
static int init(struct ao *ao) { struct priv *p = ao->priv; const char **matching_ports = NULL; char *port_name = p->cfg_port && p->cfg_port[0] ? p->cfg_port : NULL; jack_options_t open_options = JackNullOption; int port_flags = JackPortIsInput; int i; struct mp_chmap_sel sel = {0}; if (p->stdlayout == 0) { mp_chmap_sel_add_waveext(&sel); } else if (p->stdlayout == 1) { mp_chmap_sel_add_alsa_def(&sel); } else { mp_chmap_sel_add_any(&sel); } if (!ao_chmap_sel_adjust(ao, &sel, &ao->channels)) goto err_out; if (!p->autostart) open_options |= JackNoStartServer; p->client = jack_client_open(p->cfg_client_name, open_options, NULL); if (!p->client) { MP_FATAL(ao, "cannot open server\n"); goto err_out; } jack_set_process_callback(p->client, outputaudio, ao); // list matching ports if connections should be made if (p->connect) { if (!port_name) port_flags |= JackPortIsPhysical; matching_ports = jack_get_ports(p->client, port_name, NULL, port_flags); if (!matching_ports || !matching_ports[0]) { MP_FATAL(ao, "no physical ports available\n"); goto err_out; } i = 1; p->num_ports = ao->channels.num; while (matching_ports[i]) i++; if (p->num_ports > i) p->num_ports = i; } // create out output ports for (i = 0; i < p->num_ports; i++) { char pname[30]; snprintf(pname, 30, "out_%d", i); p->ports[i] = jack_port_register(p->client, pname, JACK_DEFAULT_AUDIO_TYPE, JackPortIsOutput, 0); if (!p->ports[i]) { MP_FATAL(ao, "not enough ports available\n"); goto err_out; } } if (jack_activate(p->client)) { MP_FATAL(ao, "activate failed\n"); goto err_out; } for (i = 0; i < p->num_ports; i++) { if (jack_connect(p->client, jack_port_name(p->ports[i]), matching_ports[i])) { MP_FATAL(ao, "connecting failed\n"); goto err_out; } } ao->samplerate = jack_get_sample_rate(p->client); jack_latency_range_t jack_latency_range; jack_port_get_latency_range(p->ports[0], JackPlaybackLatency, &jack_latency_range); p->jack_latency = (float)(jack_latency_range.max + jack_get_buffer_size(p->client)) / (float)ao->samplerate; p->callback_interval = 0; if (!ao_chmap_sel_get_def(ao, &sel, &ao->channels, p->num_ports)) goto err_out; ao->format = AF_FORMAT_FLOAT_NE; int unitsize = ao->channels.num * sizeof(float); p->outburst = (CHUNK_SIZE + unitsize - 1) / unitsize * unitsize; p->ring = mp_ring_new(p, NUM_CHUNKS * p->outburst); free(matching_ports); return 0; err_out: free(matching_ports); if (p->client) jack_client_close(p->client); return -1; }
/***************************************************************************** * Open: create a JACK client *****************************************************************************/ static int Open( vlc_object_t *p_this ) { char psz_name[32]; audio_output_t *p_aout = (audio_output_t *)p_this; struct aout_sys_t *p_sys = NULL; int status = VLC_SUCCESS; unsigned int i; int i_error; /* Allocate structure */ p_sys = calloc( 1, sizeof( aout_sys_t ) ); if( p_sys == NULL ) { status = VLC_ENOMEM; goto error_out; } p_aout->sys = p_sys; p_sys->latency = 0; /* Connect to the JACK server */ snprintf( psz_name, sizeof(psz_name), "vlc_%d", getpid()); psz_name[sizeof(psz_name) - 1] = '\0'; p_sys->p_jack_client = jack_client_open( psz_name, JackNullOption | JackNoStartServer, NULL ); if( p_sys->p_jack_client == NULL ) { msg_Err( p_aout, "failed to connect to JACK server" ); status = VLC_EGENERIC; goto error_out; } /* Set the process callback */ jack_set_process_callback( p_sys->p_jack_client, Process, p_aout ); jack_set_graph_order_callback ( p_sys->p_jack_client, GraphChange, p_aout ); p_aout->pf_play = aout_PacketPlay; p_aout->pf_pause = aout_PacketPause; p_aout->pf_flush = aout_PacketFlush; aout_PacketInit( p_aout, &p_sys->packet, jack_get_buffer_size( p_sys->p_jack_client ) ); aout_VolumeSoftInit( p_aout ); /* JACK only supports fl32 format */ p_aout->format.i_format = VLC_CODEC_FL32; // TODO add buffer size callback p_aout->format.i_rate = jack_get_sample_rate( p_sys->p_jack_client ); p_sys->i_channels = aout_FormatNbChannels( &p_aout->format ); p_sys->p_jack_ports = malloc( p_sys->i_channels * sizeof(jack_port_t *) ); if( p_sys->p_jack_ports == NULL ) { status = VLC_ENOMEM; goto error_out; } p_sys->p_jack_buffers = malloc( p_sys->i_channels * sizeof(jack_sample_t *) ); if( p_sys->p_jack_buffers == NULL ) { status = VLC_ENOMEM; goto error_out; } /* Create the output ports */ for( i = 0; i < p_sys->i_channels; i++ ) { snprintf( psz_name, sizeof(psz_name), "out_%d", i + 1); psz_name[sizeof(psz_name) - 1] = '\0'; p_sys->p_jack_ports[i] = jack_port_register( p_sys->p_jack_client, psz_name, JACK_DEFAULT_AUDIO_TYPE, JackPortIsOutput, 0 ); if( p_sys->p_jack_ports[i] == NULL ) { msg_Err( p_aout, "failed to register a JACK port" ); status = VLC_EGENERIC; goto error_out; } } /* Tell the JACK server we are ready */ i_error = jack_activate( p_sys->p_jack_client ); if( i_error ) { msg_Err( p_aout, "failed to activate JACK client (error %d)", i_error ); status = VLC_EGENERIC; goto error_out; } /* Auto connect ports if we were asked to */ if( var_InheritBool( p_aout, AUTO_CONNECT_OPTION ) ) { unsigned int i_in_ports; char *psz_regex = var_InheritString( p_aout, CONNECT_REGEX_OPTION ); const char **pp_in_ports = jack_get_ports( p_sys->p_jack_client, psz_regex, NULL, JackPortIsInput ); free( psz_regex ); /* Count the number of returned ports */ i_in_ports = 0; while( pp_in_ports && pp_in_ports[i_in_ports] ) { i_in_ports++; } /* Tie the output ports to JACK input ports */ for( i = 0; i_in_ports > 0 && i < p_sys->i_channels; i++ ) { const char* psz_in = pp_in_ports[i % i_in_ports]; const char* psz_out = jack_port_name( p_sys->p_jack_ports[i] ); i_error = jack_connect( p_sys->p_jack_client, psz_out, psz_in ); if( i_error ) { msg_Err( p_aout, "failed to connect port %s to port %s (error %d)", psz_out, psz_in, i_error ); } else { msg_Dbg( p_aout, "connecting port %s to port %s", psz_out, psz_in ); } } free( pp_in_ports ); } msg_Dbg( p_aout, "JACK audio output initialized (%d channels, rate=%d)", p_sys->i_channels, p_aout->format.i_rate ); error_out: /* Clean up, if an error occurred */ if( status != VLC_SUCCESS && p_sys != NULL) { if( p_sys->p_jack_client ) { jack_deactivate( p_sys->p_jack_client ); jack_client_close( p_sys->p_jack_client ); aout_PacketDestroy( p_aout ); } free( p_sys->p_jack_ports ); free( p_sys->p_jack_buffers ); free( p_sys ); } return status; }