//------------------------------------------------------------------------ bool TJackSynchro::Open() { OSStatus err; if ((fClient = jack_client_new("JackSynchro")) == 0) { fprintf (stderr, "jack server not running?\n"); return false; } jack_set_process_callback(fClient, Process, this); jack_set_sync_callback(fClient, SyncCallback, this); jack_on_shutdown(fClient, Shutdown, 0); if (jack_activate(fClient)) { fprintf (stderr, "cannot activate client"); return false; } DBUG(("MIDIClientCreate \n")); err = MIDIClientCreate(CFSTR("JAS Sync"), NotifyProc, NULL, &fMidiClient); if (!fClient) { printf("Can not open Midi client\n"); goto error; } err = MIDIDestinationCreate(fMidiClient, CFSTR("Jack Sync In"), ReadSyncProc, this, &fDestination); if (!fDestination) { printf("Can not open create destination \n"); goto error; } DBUG(("MIDIDestinationCreate OK\n")); DBUG(("MIDISourceCreate \n")); err = MIDISourceCreate(fMidiClient, CFSTR("Jack Sync Out"), &fSource); if (!fSource) { printf("Can not open create source \n"); goto error; } return true; error: Close(); return false; }
gboolean cbox_jackio_start(struct cbox_io_impl *impl, struct cbox_command_target *fb, GError **error) { struct cbox_jack_io_impl *jii = (struct cbox_jack_io_impl *)impl; struct cbox_io *io = jii->ioi.pio; if (io->cb->on_transport_sync) jack_set_sync_callback(jii->client, sync_cb, jii); jack_set_process_callback(jii->client, process_cb, jii); jack_set_port_registration_callback(jii->client, port_connect_cb, jii); jack_on_info_shutdown(jii->client, client_shutdown_cb, jii); if (io->cb->on_started) io->cb->on_started(io->cb->user_data); jack_activate(jii->client); if (cbox_config_has_section(cbox_io_section)) port_autoconnect(jii, NULL, fb); return TRUE; }
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); }
void netjack_attach( netjack_driver_state_t *netj ) { //puts ("net_driver_attach"); jack_port_t * port; char buf[32]; unsigned int chn; int port_flags; if( netj->bitdepth == CELT_MODE ) { #if HAVE_CELT #if HAVE_CELT_API_0_7 || HAVE_CELT_API_0_8 celt_int32 lookahead; netj->celt_mode = celt_mode_create( netj->sample_rate, netj->period_size, NULL ); #else celt_int32_t lookahead; netj->celt_mode = celt_mode_create( netj->sample_rate, 1, netj->period_size, NULL ); #endif celt_mode_info( netj->celt_mode, CELT_GET_LOOKAHEAD, &lookahead ); netj->codec_latency = 2*lookahead; #endif } if (netj->handle_transport_sync) jack_set_sync_callback(netj->client, (JackSyncCallback) net_driver_sync_cb, NULL); port_flags = JackPortIsOutput | JackPortIsPhysical | JackPortIsTerminal; for (chn = 0; chn < netj->capture_channels_audio; chn++) { snprintf (buf, sizeof(buf) - 1, "capture_%u", chn + 1); port = jack_port_register (netj->client, buf, JACK_DEFAULT_AUDIO_TYPE, port_flags, 0); if (!port) { jack_error ("NET: cannot register port for %s", buf); break; } netj->capture_ports = jack_slist_append (netj->capture_ports, port); if( netj->bitdepth == CELT_MODE ) { #if HAVE_CELT #if HAVE_CELT_API_0_7 || HAVE_CELT_API_0_8 netj->capture_srcs = jack_slist_append(netj->capture_srcs, celt_decoder_create( netj->celt_mode, 1, NULL ) ); #else netj->capture_srcs = jack_slist_append(netj->capture_srcs, celt_decoder_create( netj->celt_mode ) ); #endif #endif } else { #if HAVE_SAMPLERATE netj->capture_srcs = jack_slist_append(netj->capture_srcs, src_new(SRC_LINEAR, 1, NULL)); #endif } } for (chn = netj->capture_channels_audio; chn < netj->capture_channels; chn++) { snprintf (buf, sizeof(buf) - 1, "capture_%u", chn + 1); port = jack_port_register (netj->client, buf, JACK_DEFAULT_MIDI_TYPE, port_flags, 0); if (!port) { jack_error ("NET: cannot register port for %s", buf); break; } netj->capture_ports = jack_slist_append (netj->capture_ports, port); } port_flags = JackPortIsInput | JackPortIsPhysical | JackPortIsTerminal; for (chn = 0; chn < netj->playback_channels_audio; chn++) { snprintf (buf, sizeof(buf) - 1, "playback_%u", chn + 1); port = jack_port_register (netj->client, buf, JACK_DEFAULT_AUDIO_TYPE, port_flags, 0); if (!port) { jack_error ("NET: cannot register port for %s", buf); break; } netj->playback_ports = jack_slist_append (netj->playback_ports, port); if( netj->bitdepth == CELT_MODE ) { #if HAVE_CELT #if HAVE_CELT_API_0_7 || HAVE_CELT_API_0_8 CELTMode *celt_mode = celt_mode_create( netj->sample_rate, netj->period_size, NULL ); netj->playback_srcs = jack_slist_append(netj->playback_srcs, celt_encoder_create( celt_mode, 1, NULL ) ); #else CELTMode *celt_mode = celt_mode_create( netj->sample_rate, 1, netj->period_size, NULL ); netj->playback_srcs = jack_slist_append(netj->playback_srcs, celt_encoder_create( celt_mode ) ); #endif #endif } else { #if HAVE_SAMPLERATE netj->playback_srcs = jack_slist_append(netj->playback_srcs, src_new(SRC_LINEAR, 1, NULL)); #endif } } for (chn = netj->playback_channels_audio; chn < netj->playback_channels; chn++) { snprintf (buf, sizeof(buf) - 1, "playback_%u", chn + 1); port = jack_port_register (netj->client, buf, JACK_DEFAULT_MIDI_TYPE, port_flags, 0); if (!port) { jack_error ("NET: cannot register port for %s", buf); break; } netj->playback_ports = jack_slist_append (netj->playback_ports, port); } jack_activate (netj->client); }
void netjack_attach( netjack_driver_state_t *netj ) { //puts ("net_driver_attach"); jack_port_t * port; char buf[32]; unsigned int chn; int port_flags; if( netj->bitdepth == CELT_MODE ) { #if HAVE_CELT #if HAVE_CELT_API_0_7 || HAVE_CELT_API_0_8 || HAVE_CELT_API_0_11 celt_int32 lookahead; netj->celt_mode = celt_mode_create( netj->sample_rate, netj->period_size, NULL ); #else celt_int32_t lookahead; netj->celt_mode = celt_mode_create( netj->sample_rate, 1, netj->period_size, NULL ); #endif celt_mode_info( netj->celt_mode, CELT_GET_LOOKAHEAD, &lookahead ); netj->codec_latency = 2 * lookahead; #endif } if( netj->bitdepth == OPUS_MODE ) { #if HAVE_OPUS netj->opus_mode = opus_custom_mode_create(netj->sample_rate, netj->period_size, NULL); #endif } if (netj->handle_transport_sync) jack_set_sync_callback(netj->client, (JackSyncCallback) net_driver_sync_cb, NULL); port_flags = JackPortIsOutput | JackPortIsPhysical | JackPortIsTerminal; for (chn = 0; chn < netj->capture_channels_audio; chn++) { snprintf (buf, sizeof(buf) - 1, "capture_%u", chn + 1); port = jack_port_register (netj->client, buf, JACK_DEFAULT_AUDIO_TYPE, port_flags, 0); if (!port) { jack_error ("NET: cannot register port for %s", buf); break; } netj->capture_ports = jack_slist_append (netj->capture_ports, port); if( netj->bitdepth == CELT_MODE ) { #if HAVE_CELT #if HAVE_CELT_API_0_11 netj->capture_srcs = jack_slist_append(netj->capture_srcs, celt_decoder_create_custom( netj->celt_mode, 1, NULL ) ); #elif HAVE_CELT_API_0_7 || HAVE_CELT_API_0_8 netj->capture_srcs = jack_slist_append(netj->capture_srcs, celt_decoder_create( netj->celt_mode, 1, NULL ) ); #else netj->capture_srcs = jack_slist_append(netj->capture_srcs, celt_decoder_create( netj->celt_mode ) ); #endif #endif } else if( netj->bitdepth == OPUS_MODE ) { #if HAVE_OPUS OpusCustomDecoder *decoder = opus_custom_decoder_create( netj->opus_mode, 1, NULL ); netj->capture_srcs = jack_slist_append(netj->capture_srcs, decoder ); #endif } else { #if HAVE_SAMPLERATE netj->capture_srcs = jack_slist_append(netj->capture_srcs, src_new(SRC_LINEAR, 1, NULL)); #endif } } for (chn = netj->capture_channels_audio; chn < netj->capture_channels; chn++) { snprintf (buf, sizeof(buf) - 1, "capture_%u", chn + 1); port = jack_port_register (netj->client, buf, JACK_DEFAULT_MIDI_TYPE, port_flags, 0); if (!port) { jack_error ("NET: cannot register port for %s", buf); break; } netj->capture_ports = jack_slist_append (netj->capture_ports, port); } port_flags = JackPortIsInput | JackPortIsPhysical | JackPortIsTerminal; for (chn = 0; chn < netj->playback_channels_audio; chn++) { snprintf (buf, sizeof(buf) - 1, "playback_%u", chn + 1); port = jack_port_register (netj->client, buf, JACK_DEFAULT_AUDIO_TYPE, port_flags, 0); if (!port) { jack_error ("NET: cannot register port for %s", buf); break; } netj->playback_ports = jack_slist_append (netj->playback_ports, port); if( netj->bitdepth == CELT_MODE ) { #if HAVE_CELT #if HAVE_CELT_API_0_11 CELTMode *celt_mode = celt_mode_create( netj->sample_rate, netj->period_size, NULL ); netj->playback_srcs = jack_slist_append(netj->playback_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( netj->sample_rate, netj->period_size, NULL ); netj->playback_srcs = jack_slist_append(netj->playback_srcs, celt_encoder_create( celt_mode, 1, NULL ) ); #else CELTMode *celt_mode = celt_mode_create( netj->sample_rate, 1, netj->period_size, NULL ); netj->playback_srcs = jack_slist_append(netj->playback_srcs, celt_encoder_create( celt_mode ) ); #endif #endif } else if( netj->bitdepth == OPUS_MODE ) { #if HAVE_OPUS const int kbps = netj->resample_factor; jack_log( "OPUS %dkbps\n", kbps); OpusCustomMode *opus_mode = opus_custom_mode_create( netj->sample_rate, netj->period_size, NULL ); // XXX free me in the end OpusCustomEncoder *oe = opus_custom_encoder_create( opus_mode, 1, NULL ); 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)); netj->playback_srcs = jack_slist_append(netj->playback_srcs, oe ); #endif } else { #if HAVE_SAMPLERATE netj->playback_srcs = jack_slist_append(netj->playback_srcs, src_new(SRC_LINEAR, 1, NULL)); #endif } } for (chn = netj->playback_channels_audio; chn < netj->playback_channels; chn++) { snprintf (buf, sizeof(buf) - 1, "playback_%u", chn + 1); port = jack_port_register (netj->client, buf, JACK_DEFAULT_MIDI_TYPE, port_flags, 0); if (!port) { jack_error ("NET: cannot register port for %s", buf); break; } netj->playback_ports = jack_slist_append (netj->playback_ports, port); } jack_activate (netj->client); }
void jackSetSyncCb() { jack_client_t *client = jackGetHandle(); jack_set_sync_callback(client, jackSyncCb, NULL); //jack_set_sync_timeout(client, 8); }
AUD_JackDevice::AUD_JackDevice(std::string name, AUD_DeviceSpecs specs, int buffersize) { if(specs.channels == AUD_CHANNELS_INVALID) specs.channels = AUD_CHANNELS_STEREO; // jack uses floats m_specs = specs; m_specs.format = AUD_FORMAT_FLOAT32; jack_options_t options = JackNullOption; jack_status_t status; // open client m_client = jack_client_open(name.c_str(), options, &status); if(m_client == NULL) AUD_THROW(AUD_ERROR_JACK, clientopen_error); // set callbacks jack_set_process_callback(m_client, AUD_JackDevice::jack_mix, this); jack_on_shutdown(m_client, AUD_JackDevice::jack_shutdown, this); jack_set_sync_callback(m_client, AUD_JackDevice::jack_sync, this); // register our output channels which are called ports in jack m_ports = new jack_port_t*[m_specs.channels]; try { char portname[64]; for(int i = 0; i < m_specs.channels; i++) { sprintf(portname, "out %d", i+1); m_ports[i] = jack_port_register(m_client, portname, JACK_DEFAULT_AUDIO_TYPE, JackPortIsOutput, 0); if(m_ports[i] == NULL) AUD_THROW(AUD_ERROR_JACK, port_error); } } catch(AUD_Exception&) { jack_client_close(m_client); delete[] m_ports; throw; } m_specs.rate = (AUD_SampleRate)jack_get_sample_rate(m_client); buffersize *= sizeof(sample_t); m_ringbuffers = new jack_ringbuffer_t*[specs.channels]; for(unsigned int i = 0; i < specs.channels; i++) m_ringbuffers[i] = jack_ringbuffer_create(buffersize); buffersize *= specs.channels; m_deinterleavebuf.resize(buffersize); m_buffer.resize(buffersize); create(); m_valid = true; m_sync = 0; m_syncFunc = NULL; m_nextState = m_state = jack_transport_query(m_client, NULL); pthread_mutex_init(&m_mixingLock, NULL); pthread_cond_init(&m_mixingCondition, NULL); // activate the client if(jack_activate(m_client)) { jack_client_close(m_client); delete[] m_ports; for(unsigned int i = 0; i < specs.channels; i++) jack_ringbuffer_free(m_ringbuffers[i]); delete[] m_ringbuffers; pthread_mutex_destroy(&m_mixingLock); pthread_cond_destroy(&m_mixingCondition); destroy(); AUD_THROW(AUD_ERROR_JACK, activate_error); } const char** ports = jack_get_ports(m_client, NULL, NULL, JackPortIsPhysical | JackPortIsInput); if(ports != NULL) { for(int i = 0; i < m_specs.channels && ports[i]; i++) jack_connect(m_client, jack_port_name(m_ports[i]), ports[i]); free(ports); } pthread_attr_t attr; pthread_attr_init(&attr); pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_JOINABLE); pthread_create(&m_mixingThread, &attr, runMixingThread, this); pthread_attr_destroy(&attr); }
static void init_jack(void) { int i, err; #ifdef WITH_LASH lash_event_t *event; #endif jack_client = jack_client_open(PROGRAM_NAME, JackNoStartServer, NULL); if (jack_client == NULL) { g_critical("Could not connect to the JACK server; run jackd first?"); exit(EX_UNAVAILABLE); } #ifdef WITH_LASH event = lash_event_new_with_type(LASH_Client_Name); assert (event); /* Documentation does not say anything about return value. */ lash_event_set_string(event, jack_get_client_name(jack_client)); lash_send_event(lash_client, event); lash_jack_client_name(lash_client, jack_get_client_name(jack_client)); #endif err = jack_set_process_callback(jack_client, process_callback, 0); if (err) { g_critical("Could not register JACK process callback."); exit(EX_UNAVAILABLE); } if (use_transport) { err = jack_set_sync_callback(jack_client, sync_callback, 0); if (err) { g_critical("Could not register JACK sync callback."); exit(EX_UNAVAILABLE); } #if 0 err = jack_set_timebase_callback(jack_client, 1, timebase_callback, 0); if (err) { g_critical("Could not register JACK timebase callback."); exit(EX_UNAVAILABLE); } #endif } jack_on_shutdown(jack_client, jack_shutdown, 0); int number_of_tracks; if (remote_control) { number_of_tracks = 0; // TODO allow more ports } else { assert(smf->number_of_tracks >= 1); number_of_tracks = smf->number_of_tracks; } /* We are allocating number_of_tracks + 1 output ports. */ for (i = 0; i <= number_of_tracks; i++) { char port_name[32]; if (i == 0) snprintf(port_name, sizeof(port_name), "midi_out"); else snprintf(port_name, sizeof(port_name), "track_%d_midi_out", i); output_ports[i] = jack_port_register(jack_client, port_name, JACK_DEFAULT_MIDI_TYPE, JackPortIsOutput, 0); if (output_ports[i] == NULL) { g_critical("Could not register JACK output port '%s'.", port_name); exit(EX_UNAVAILABLE); } if (just_one_output) break; } if (jack_activate(jack_client)) { g_critical("Cannot activate JACK client."); exit(EX_UNAVAILABLE); } }