static guint gst_jack_ring_buffer_delay (GstRingBuffer * buf) { GstJackAudioSrc *src; guint i, res = 0; #ifdef HAVE_JACK_0_120_2 jack_latency_range_t range; #else guint latency; #endif jack_client_t *client; src = GST_JACK_AUDIO_SRC (GST_OBJECT_PARENT (buf)); client = gst_jack_audio_client_get_client (src->client); for (i = 0; i < src->port_count; i++) { #ifdef HAVE_JACK_0_120_2 jack_port_get_latency_range (src->ports[i], JackCaptureLatency, &range); if (range.max > res) res = range.max; #else latency = jack_port_get_total_latency (client, src->ports[i]); if (latency > res) res = latency; #endif } GST_DEBUG_OBJECT (src, "delay %u", res); return res; }
static int process_callback(jack_nframes_t nframes, void *arg) { /* Warning: this function runs in realtime. One mustn't allocate memory here * or do any other thing that could block. */ int i, j; JackData *self = arg; float * buffer; jack_nframes_t latency, cycle_delay; AVPacket pkt; float *pkt_data; double cycle_time; if (!self->client) return 0; /* The approximate delay since the hardware interrupt as a number of frames */ cycle_delay = jack_frames_since_cycle_start(self->client); /* Retrieve filtered cycle time */ cycle_time = ff_timefilter_update(self->timefilter, av_gettime() / 1000000.0 - (double) cycle_delay / self->sample_rate, self->buffer_size); /* Check if an empty packet is available, and if there's enough space to send it back once filled */ if ((av_fifo_size(self->new_pkts) < sizeof(pkt)) || (av_fifo_space(self->filled_pkts) < sizeof(pkt))) { self->pkt_xrun = 1; return 0; } /* Retrieve empty (but allocated) packet */ av_fifo_generic_read(self->new_pkts, &pkt, sizeof(pkt), NULL); pkt_data = (float *) pkt.data; latency = 0; /* Copy and interleave audio data from the JACK buffer into the packet */ for (i = 0; i < self->nports; i++) { latency += jack_port_get_total_latency(self->client, self->ports[i]); buffer = jack_port_get_buffer(self->ports[i], self->buffer_size); for (j = 0; j < self->buffer_size; j++) pkt_data[j * self->nports + i] = buffer[j]; } /* Timestamp the packet with the cycle start time minus the average latency */ pkt.pts = (cycle_time - (double) latency / (self->nports * self->sample_rate)) * 1000000.0; /* Send the now filled packet back, and increase packet counter */ av_fifo_generic_write(self->filled_pkts, &pkt, sizeof(pkt), NULL); sem_post(&self->packet_count); return 0; }
/** returns the sum of latency of all ports between this one and a terminal port. */ nframes_t Port::total_latency ( void ) const { #ifdef HAVE_JACK_PORT_GET_LATENCY_RANGE jack_latency_range_t range; jack_port_get_latency_range( _port, _direction == Input ? JackPlaybackLatency : JackCaptureLatency, &range ); return range.max; #else return jack_port_get_total_latency( _client->jack_client() , _port ); #endif }
bool SC_JackDriver::GraphOrderChanged() { SC_JackPortList* outputs = mOutputList; jack_nframes_t lat = 0; for (int i=0; i < outputs->mSize; ++i) { jack_nframes_t portLat = jack_port_get_total_latency(mClient, outputs->mPorts[i]); if (portLat > lat) lat = portLat; } double maxLat = (double)lat / mSampleRate; if (maxLat != mMaxOutputLatency) { mMaxOutputLatency = maxLat; scprintf("%s: max output latency %.1f ms\n", kJackDriverIdent, maxLat * 1e3); } return true; }
static guint gst_jack_ring_buffer_delay (GstRingBuffer * buf) { GstJackAudioSrc *src; guint i, res = 0, latency; jack_client_t *client; src = GST_JACK_AUDIO_SRC (GST_OBJECT_PARENT (buf)); client = gst_jack_audio_client_get_client (src->client); for (i = 0; i < src->port_count; i++) { latency = jack_port_get_total_latency (client, src->ports[i]); if (latency > res) res = latency; } GST_DEBUG_OBJECT (src, "delay %u", res); return res; }
static int GraphChange( void *p_arg ) { audio_output_t *p_aout = (audio_output_t*) p_arg; struct aout_sys_t *p_sys = p_aout->sys; unsigned int i; jack_nframes_t port_latency; p_sys->latency = 0; for( i = 0; i < p_sys->i_channels; ++i ) { port_latency = jack_port_get_total_latency( p_sys->p_jack_client, p_sys->p_jack_ports[i] ); p_sys->latency = __MAX( p_sys->latency, port_latency ); } msg_Dbg(p_aout, "JACK graph reordered. Our maximum latency=%d.", p_sys->latency); return 0; }
/* free the buffer */ gst_buffer_unref (buf->data); buf->data = NULL; return TRUE; } static gboolean gst_jack_ring_buffer_start (GstRingBuffer * buf) { GstJackAudioSink *sink; sink = GST_JACK_AUDIO_SINK (GST_OBJECT_PARENT (buf)); GST_DEBUG_OBJECT (sink, "start"); if (sink->transport & GST_JACK_TRANSPORT_MASTER) { jack_client_t *client; client = gst_jack_audio_client_get_client (sink->client); jack_transport_start (client); } return TRUE; } static gboolean gst_jack_ring_buffer_pause (GstRingBuffer * buf) { GstJackAudioSink *sink; sink = GST_JACK_AUDIO_SINK (GST_OBJECT_PARENT (buf)); GST_DEBUG_OBJECT (sink, "pause"); if (sink->transport & GST_JACK_TRANSPORT_MASTER) { jack_client_t *client; client = gst_jack_audio_client_get_client (sink->client); jack_transport_stop (client); } return TRUE; } static gboolean gst_jack_ring_buffer_stop (GstRingBuffer * buf) { GstJackAudioSink *sink; sink = GST_JACK_AUDIO_SINK (GST_OBJECT_PARENT (buf)); GST_DEBUG_OBJECT (sink, "stop"); if (sink->transport & GST_JACK_TRANSPORT_MASTER) { jack_client_t *client; client = gst_jack_audio_client_get_client (sink->client); jack_transport_stop (client); } return TRUE; } #if defined (HAVE_JACK_0_120_1) || defined(HAVE_JACK_1_9_7) static guint gst_jack_ring_buffer_delay (GstRingBuffer * buf) { GstJackAudioSink *sink; guint i, res = 0; jack_latency_range_t range; sink = GST_JACK_AUDIO_SINK (GST_OBJECT_PARENT (buf)); for (i = 0; i < sink->port_count; i++) { jack_port_get_latency_range (sink->ports[i], JackPlaybackLatency, &range); if (range.max > res) res = range.max; } GST_LOG_OBJECT (sink, "delay %u", res); return res; } #else /* !(defined (HAVE_JACK_0_120_1) || defined(HAVE_JACK_1_9_7)) */ static guint gst_jack_ring_buffer_delay (GstRingBuffer * buf) { GstJackAudioSink *sink; guint i, res = 0; guint latency; jack_client_t *client; sink = GST_JACK_AUDIO_SINK (GST_OBJECT_PARENT (buf)); client = gst_jack_audio_client_get_client (sink->client); for (i = 0; i < sink->port_count; i++) { latency = jack_port_get_total_latency (client, sink->ports[i]); if (latency > res) res = latency; } GST_LOG_OBJECT (sink, "delay %u", res); return res; }
static int sink_process_msg(pa_msgobject *o, int code, void *data, int64_t offset, pa_memchunk *memchunk) { struct userdata *u = PA_SINK(o)->userdata; switch (code) { case SINK_MESSAGE_RENDER: /* Handle the request from the JACK thread */ if (u->sink->thread_info.state == PA_SINK_RUNNING) { pa_memchunk chunk; size_t nbytes; void *p; pa_assert(offset > 0); nbytes = (size_t) offset * pa_frame_size(&u->sink->sample_spec); pa_sink_render_full(u->sink, nbytes, &chunk); p = (uint8_t*) pa_memblock_acquire(chunk.memblock) + chunk.index; pa_deinterleave(p, u->buffer, u->channels, sizeof(float), (unsigned) offset); pa_memblock_release(chunk.memblock); pa_memblock_unref(chunk.memblock); } else { unsigned c; pa_sample_spec ss; /* Humm, we're not RUNNING, hence let's write some silence */ ss = u->sink->sample_spec; ss.channels = 1; for (c = 0; c < u->channels; c++) pa_silence_memory(u->buffer[c], (size_t) offset * pa_sample_size(&ss), &ss); } u->frames_in_buffer = (jack_nframes_t) offset; u->saved_frame_time = * (jack_nframes_t*) data; u->saved_frame_time_valid = TRUE; return 0; case SINK_MESSAGE_BUFFER_SIZE: pa_sink_set_max_request_within_thread(u->sink, (size_t) offset * pa_frame_size(&u->sink->sample_spec)); return 0; case SINK_MESSAGE_ON_SHUTDOWN: pa_asyncmsgq_post(u->thread_mq.outq, PA_MSGOBJECT(u->core), PA_CORE_MESSAGE_UNLOAD_MODULE, u->module, 0, NULL, NULL); return 0; case PA_SINK_MESSAGE_GET_LATENCY: { jack_nframes_t l, ft, d; size_t n; /* This is the "worst-case" latency */ l = jack_port_get_total_latency(u->client, u->port[0]) + u->frames_in_buffer; if (u->saved_frame_time_valid) { /* Adjust the worst case latency by the time that * passed since we last handed data to JACK */ ft = jack_frame_time(u->client); d = ft > u->saved_frame_time ? ft - u->saved_frame_time : 0; l = l > d ? l - d : 0; } /* Convert it to usec */ n = l * pa_frame_size(&u->sink->sample_spec); *((pa_usec_t*) data) = pa_bytes_to_usec(n, &u->sink->sample_spec); return 0; } } return pa_sink_process_msg(o, code, data, offset, memchunk); }
static int init(int rate, int channels, int format, int flags) { const char **matching_ports = NULL; char *port_name = NULL; char *client_name = NULL; int autostart = 0; int connect = 1; const opt_t subopts[] = { {"port", OPT_ARG_MSTRZ, &port_name, NULL}, {"name", OPT_ARG_MSTRZ, &client_name, NULL}, {"estimate", OPT_ARG_BOOL, &estimate, NULL}, {"autostart", OPT_ARG_BOOL, &autostart, NULL}, {"connect", OPT_ARG_BOOL, &connect, NULL}, {NULL} }; jack_options_t open_options = JackUseExactName; int port_flags = JackPortIsInput; int i; estimate = 1; if (subopt_parse(ao_subdevice, subopts) != 0) { print_help(); return 0; } if (channels > MAX_CHANS) { mp_msg(MSGT_AO, MSGL_FATAL, "[JACK] Invalid number of channels: %i\n", channels); goto err_out; } if (!client_name) { client_name = malloc(40); sprintf(client_name, "MPlayer [%d]", getpid()); } if (!autostart) open_options |= JackNoStartServer; client = jack_client_open(client_name, open_options, NULL); if (!client) { mp_msg(MSGT_AO, MSGL_FATAL, "[JACK] cannot open server\n"); goto err_out; } buffer = av_fifo_alloc(BUFFSIZE); jack_set_process_callback(client, outputaudio, 0); // list matching ports if connections should be made if (connect) { if (!port_name) port_flags |= JackPortIsPhysical; matching_ports = jack_get_ports(client, port_name, NULL, port_flags); i = 0; while (matching_ports && matching_ports[i]) i++; if (!i) { mp_msg(MSGT_AO, MSGL_FATAL, "[JACK] no physical ports available\n"); goto err_out; } if (channels > i) channels = i; } num_ports = channels; // create out_* output ports for (i = 0; i < num_ports; i++) { char pname[30]; snprintf(pname, 30, "out_%d", i); ports[i] = jack_port_register(client, pname, JACK_DEFAULT_AUDIO_TYPE, JackPortIsOutput, 0); if (!ports[i]) { mp_msg(MSGT_AO, MSGL_FATAL, "[JACK] not enough ports available\n"); goto err_out; } } if (jack_activate(client)) { mp_msg(MSGT_AO, MSGL_FATAL, "[JACK] activate failed\n"); goto err_out; } for (i = 0; i < num_ports && matching_ports && matching_ports[i]; i++) { if (jack_connect(client, jack_port_name(ports[i]), matching_ports[i])) { mp_msg(MSGT_AO, MSGL_FATAL, "[JACK] connecting failed\n"); goto err_out; } } rate = jack_get_sample_rate(client); jack_latency = (float)(jack_port_get_total_latency(client, ports[0]) + jack_get_buffer_size(client)) / (float)rate; callback_interval = 0; ao_data.channels = channels; ao_data.samplerate = rate; ao_data.format = AF_FORMAT_FLOAT_NE; ao_data.bps = channels * rate * sizeof(float); ao_data.buffersize = CHUNK_SIZE * NUM_CHUNKS; ao_data.outburst = CHUNK_SIZE; free(matching_ports); free(port_name); free(client_name); return 1; err_out: free(matching_ports); free(port_name); free(client_name); if (client) jack_client_close(client); av_fifo_free(buffer); buffer = NULL; return 0; }
/***************************************************************************** * * JACK_START() * * Start jack client and attach to playback ports. * *****************************************************************************/ int jack_start(void) { const char **ports; char *p; char *q; int j; /* activate client (callbacks start, so everything else needs to be ready) */ if (jack_activate (client)) { fprintf (stderr, "Unable to activate JACK client.\n"); jack_client_close (client); jack_running = 0; jack_thread_p = 0; client = NULL; return 1; } /* all up and running now */ jack_running = 1; jack_thread_p = jack_client_thread_id (client); /* connect ports. in/out is from server perspective */ /* By default, connect PHASEX output to first two JACK hardware playback ports found */ if (setting_jack_autoconnect) { ports = jack_get_ports (client, NULL, NULL, JackPortIsPhysical | JackPortIsInput); if ((ports == NULL) || (ports[0] == NULL)) { fprintf (stderr, "Warning: PHASEX output not connected!\n"); fprintf (stderr, " (No physical JACK playback ports available.)\n"); } else { if (jack_connect (client, jack_port_name (output_port1), ports[0])) { fprintf (stderr, "Unable to connect PHASEX output ports to JACK input.\n"); } if (jack_connect (client, jack_port_name (output_port2), ports[1])) { fprintf (stderr, "Unable to connect PHASEX output ports to JACK input.\n"); } } } /* otherwise, connect to ports that match -o command line flag */ else { ports = jack_get_ports (client, NULL, NULL, JackPortIsInput); if ((ports == NULL) || (ports[0] == NULL)) { fprintf (stderr, "Warning: PHASEX output not connected!\n"); fprintf (stderr, " (No JACK playback ports available.)\n"); } else { p = jack_outputs; if (p != NULL) { if ((q = index (p, ',')) != NULL) { *q = '\0'; q++; } else { q = p; } for (j = 0; ports[j] != NULL; j++) { if (strstr (ports[j], p) != NULL) { if (jack_connect (client, jack_port_name (output_port1), ports[j])) { fprintf (stderr, "Unable to connect PHASEX output ports to JACK input.\n"); } else if (debug) { fprintf (stderr, "JACK connected PHASEX out_1 to %s.\n", ports[j]); } p = "_no_port_"; } if (strstr (ports[j], q) != NULL) { if (jack_connect (client, jack_port_name (output_port2), ports[j])) { fprintf (stderr, "Unable to connect PHASEX output ports to JACK input.\n"); } else if (debug) { fprintf (stderr, "JACK connected PHASEX out_2 to %s.\n", ports[j]); } q = "_no_port_"; } } if (p != q) { q--; *q = ','; } } } } free (ports); /* By default, connect PHASEX input to first two JACK hardware capture ports found */ if (setting_jack_autoconnect) { ports = jack_get_ports (client, NULL, NULL, JackPortIsPhysical | JackPortIsOutput); if ((ports == NULL) || (ports[0] == NULL) || (ports[1] == NULL)) { fprintf (stderr, "Warning: PHASEX input not connected!\n"); fprintf (stderr, " (No physical JACK capture ports available.)\n"); } else { if (jack_connect (client, ports[0], jack_port_name (input_port1))) { fprintf (stderr, "Unable to connect PHASEX input ports to JACK output.\n"); } if (jack_connect (client, ports[1], jack_port_name (input_port2))) { fprintf (stderr, "Unable to connect PHASEX input ports to JACK output.\n"); } } } /* otherwise, connect to ports that match -i command line flag */ else { ports = jack_get_ports (client, NULL, NULL, JackPortIsOutput); if ((ports == NULL) || (ports[0] == NULL) || (ports[1] == NULL)) { fprintf (stderr, "Warning: PHASEX input not connected!\n"); fprintf (stderr, " (No JACK capture ports available.)\n"); } else { p = jack_inputs; if (p != NULL) { if ((q = index (p, ',')) != NULL) { *q = '\0'; q++; } else { q = p; } for (j = 0; ports[j] != NULL; j++) { if (strstr (ports[j], p) != NULL) { if (jack_connect (client, ports[j], jack_port_name (input_port1))) { fprintf (stderr, "Unable to connect PHASEX input ports to JACK output.\n"); } else if (debug) { fprintf (stderr, "JACK connected %s to PHASEX in_1.\n", ports[j]); } p = "_no_port_"; } if (strstr (ports[j], q) != NULL) { if (jack_connect (client, ports[j], jack_port_name (input_port2))) { fprintf (stderr, "Unable to connect PHASEX input ports to JACK output.\n"); } else if (debug) { fprintf (stderr, "JACK connected %s to PHASEX in_2.\n", ports[j]); } q = "_no_port_"; } } } } } free (ports); /* report latency and total latency */ if (debug) { fprintf (stderr, "JACK latency: %d\n", jack_port_get_latency (output_port1)); fprintf (stderr, "JACK total latency: %d\n", jack_port_get_total_latency (client, output_port1)); } return 0; }
static int JackCallback( jack_nframes_t frames, void *userData ) { PaJackStream *stream = (PaJackStream*)userData; PaStreamCallbackTimeInfo timeInfo; int callbackResult; int chn; int framesProcessed; /* TODO: make this a lot more accurate */ PaTime now = GetStreamTime(stream); timeInfo.currentTime = now; timeInfo.outputBufferDacTime = now; timeInfo.inputBufferAdcTime = now; if( stream->t0 == -1 ) { if( stream->num_outgoing_connections == 0 ) { /* TODO: how to handle stream time for capture-only operation? */ } else { /* the beginning time needs to be initialized */ stream->t0 = jack_frame_time( stream->jack_client ) - jack_frames_since_cycle_start( stream->jack_client) + jack_port_get_total_latency( stream->jack_client, stream->local_output_ports[0] ); } } PaUtil_BeginCpuLoadMeasurement( &stream->cpuLoadMeasurer ); PaUtil_BeginBufferProcessing( &stream->bufferProcessor, &timeInfo, 0 /* @todo pass underflow/overflow flags when necessary */ ); for( chn = 0; chn < stream->num_incoming_connections; chn++ ) { jack_default_audio_sample_t *channel_buf; channel_buf = (jack_default_audio_sample_t*) jack_port_get_buffer( stream->local_input_ports[chn], frames ); PaUtil_SetNonInterleavedInputChannel( &stream->bufferProcessor, chn, channel_buf ); } for( chn = 0; chn < stream->num_outgoing_connections; chn++ ) { jack_default_audio_sample_t *channel_buf; channel_buf = (jack_default_audio_sample_t*) jack_port_get_buffer( stream->local_output_ports[chn], frames ); PaUtil_SetNonInterleavedOutputChannel( &stream->bufferProcessor, chn, channel_buf ); } if( stream->num_incoming_connections > 0 ) PaUtil_SetInputFrameCount( &stream->bufferProcessor, frames ); if( stream->num_outgoing_connections > 0 ) PaUtil_SetOutputFrameCount( &stream->bufferProcessor, frames ); callbackResult = paContinue; framesProcessed = PaUtil_EndBufferProcessing( &stream->bufferProcessor, &callbackResult ); PaUtil_EndCpuLoadMeasurement( &stream->cpuLoadMeasurer, framesProcessed ); stream->total_frames_sent += frames; if( callbackResult == paContinue ) { /* nothing special */ } else if( callbackResult == paAbort ) { /* finish playback immediately */ /* TODO: memset 0 the outgoing samples to "cancel" them */ stream->is_active = FALSE; /* return nonzero so we get deactivated (and the callback won't * get called again) */ return 1; } else { /* User callback has asked us to stop with paComplete or other non-zero value. */ stream->is_active = FALSE; /* return nonzero so we get deactivated (and the callback won't * get called again) */ return 1; } return 0; }
int main (int argc, char *argv[]) { jack_client_t *client; jack_status_t status; jack_options_t options = JackNoStartServer; const char **ports, **connections; unsigned int i, j, k; int skip_port; int show_aliases = 0; int show_con = 0; int show_port_latency = 0; int show_total_latency = 0; int show_properties = 0; int show_type = 0; int c; int option_index; char* aliases[2]; char *server_name = NULL; jack_port_t *port; struct option long_options[] = { { "server", 1, 0, 's' }, { "aliases", 0, 0, 'A' }, { "connections", 0, 0, 'c' }, { "port-latency", 0, 0, 'l' }, { "total-latency", 0, 0, 'L' }, { "properties", 0, 0, 'p' }, { "type", 0, 0, 't' }, { "help", 0, 0, 'h' }, { "version", 0, 0, 'v' }, { 0, 0, 0, 0 } }; my_name = strrchr(argv[0], '/'); if (my_name == 0) { my_name = argv[0]; } else { my_name ++; } while ((c = getopt_long (argc, argv, "s:AclLphvt", long_options, &option_index)) >= 0) { switch (c) { case 's': server_name = (char *) malloc (sizeof (char) * strlen(optarg)); strcpy (server_name, optarg); options |= JackServerName; break; case 'A': aliases[0] = (char *) malloc (jack_port_name_size()); aliases[1] = (char *) malloc (jack_port_name_size()); show_aliases = 1; break; case 'c': show_con = 1; break; case 'l': show_port_latency = 1; break; case 'L': show_total_latency = 1; break; case 'p': show_properties = 1; break; case 't': show_type = 1; break; case 'h': show_usage (); return 1; break; case 'v': show_version (); return 1; break; default: show_usage (); return 1; break; } } /* Open a client connection to the JACK server. Starting a * new server only to list its ports seems pointless, so we * specify JackNoStartServer. */ //JOQ: need a new server name option client = jack_client_open ("lsp", options, &status, server_name); if (client == NULL) { if (status & JackServerFailed) { fprintf (stderr, "JACK server not running\n"); } else { fprintf (stderr, "jack_client_open() failed, " "status = 0x%2.0x\n", status); } return 1; } ports = jack_get_ports (client, NULL, NULL, 0); if (!ports) goto error; for (i = 0; ports && ports[i]; ++i) { // skip over any that don't match ALL of the strings presented at command line skip_port = 0; for(k = optind; k < argc; k++){ if(strstr(ports[i], argv[k]) == NULL ){ skip_port = 1; } } if (skip_port) continue; printf ("%s\n", ports[i]); port = jack_port_by_name (client, ports[i]); if (show_aliases) { int cnt; int i; cnt = jack_port_get_aliases (port, aliases); for (i = 0; i < cnt; ++i) { printf (" %s\n", aliases[i]); } } if (show_con) { if ((connections = jack_port_get_all_connections (client, jack_port_by_name(client, ports[i]))) != 0) { for (j = 0; connections[j]; j++) { printf (" %s\n", connections[j]); } free (connections); } } if (show_port_latency) { if (port) { jack_latency_range_t range; printf (" port latency = %" PRIu32 " frames\n", jack_port_get_latency (port)); jack_port_get_latency_range (port, JackPlaybackLatency, &range); printf (" port playback latency = [ %" PRIu32 " %" PRIu32 " ] frames\n", range.min, range.max); jack_port_get_latency_range (port, JackCaptureLatency, &range); printf (" port capture latency = [ %" PRIu32 " %" PRIu32 " ] frames\n", range.min, range.max); } } if (show_total_latency) { if (port) { printf (" total latency = %d frames\n", jack_port_get_total_latency (client, port)); } } if (show_properties) { if (port) { int flags = jack_port_flags (port); printf (" properties: "); if (flags & JackPortIsInput) { fputs ("input,", stdout); } if (flags & JackPortIsOutput) { fputs ("output,", stdout); } if (flags & JackPortCanMonitor) { fputs ("can-monitor,", stdout); } if (flags & JackPortIsPhysical) { fputs ("physical,", stdout); } if (flags & JackPortIsTerminal) { fputs ("terminal,", stdout); } putc ('\n', stdout); } } if (show_type) { if (port) { putc ('\t', stdout); fputs (jack_port_type (port), stdout); putc ('\n', stdout); } } } error: if (show_aliases) { free(aliases[0]); free(aliases[1]); } if (ports) jack_free (ports); jack_client_close (client); exit (0); }