Example #1
0
    String open (const BigInteger& inputChannels, const BigInteger& outputChannels,
                 double /* sampleRate */, int /* bufferSizeSamples */)
    {
        jack_Log ("opening client");
        lastError = client.open (KV_JACK_NAME, 0);
        if (lastError.isNotEmpty())
        {
            jack_Log (lastError);
            return lastError;
        }

        DBG("num inputs: " << inputChannels.getHighestBit());
        DBG("num outputs: " << outputChannels.getHighestBit());


        jack_on_shutdown (client, JackDevice::shutdownCallback, this);
        jack_set_error_function (JackDevice::errorCallback);
        jack_set_port_connect_callback (client, JackDevice::portConnectCallback, this);
        jack_set_process_callback (client, JackDevice::processCallback, this);
        jack_set_thread_init_callback (client, JackDevice::threadInitCallback, this);
        jack_set_port_registration_callback (client, JackDevice::_portRegistration, this);

        client.registerPort ("audio_1", Jack::audioPort, JackPortIsOutput);
        client.registerPort ("audio_2", Jack::audioPort, JackPortIsOutput);

        return lastError;
    }
Example #2
0
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;
}
Example #3
0
void gojack_generic_callback_sync_destroy(struct gojack_generic_callback_sync *sync) {
    jack_set_freewheel_callback(sync->client, NULL, NULL);
    jack_set_buffer_size_callback(sync->client, NULL, NULL);
    jack_set_sample_rate_callback(sync->client, NULL, NULL);
    jack_set_client_registration_callback(sync->client, NULL, NULL);
    jack_set_port_registration_callback(sync->client, NULL, NULL);
    jack_set_port_connect_callback(sync->client, NULL, NULL);
    jack_set_port_rename_callback(sync->client, NULL, NULL);
    jack_set_graph_order_callback(sync->client, NULL, NULL);
    jack_set_xrun_callback(sync->client, NULL, NULL);
    jack_set_latency_callback(sync->client, NULL, NULL);
    cgo_callback_sync_destroy(sync->base);
    pthread_mutex_destroy(&sync->lock);
    free(sync);
}
Example #4
0
int
main (int argc, char *argv[])
{
	jack_client_t *client;
	jack_options_t options = JackNullOption;
	jack_status_t status;

	if ((client = jack_client_open ("event-monitor", options, &status, NULL)) == 0) {
		fprintf (stderr, "jack_client_open() failed, "
			 "status = 0x%2.0x\n", status);
		if (status & JackServerFailed) {
			fprintf (stderr, "Unable to connect to JACK server\n");
		}
		return 1;
	}
	
	if (jack_set_port_registration_callback (client, port_callback, NULL)) {
		fprintf (stderr, "cannot set port registration callback\n");
		return 1;
	}
	if (jack_set_port_connect_callback (client, connect_callback, NULL)) {
		fprintf (stderr, "cannot set port connect callback\n");
		return 1;
	}
	if (jack_set_client_registration_callback (client, client_callback, NULL)) {
		fprintf (stderr, "cannot set client registration callback\n");
		return 1;
	}
	if (jack_set_graph_order_callback (client, graph_callback, NULL)) {
		fprintf (stderr, "cannot set graph order registration callback\n");
		return 1;
	}
        if (jack_set_property_change_callback (client, (JackPropertyChangeCallback) propchange, 0)) {
                fprintf (stderr, "cannot set property change callback\n");
                return 1;
        }
	if (jack_activate (client)) {
		fprintf (stderr, "cannot activate client");
		return 1;
	}

	sleep (-1);
	exit (0);
}
Example #5
0
struct gojack_generic_callback_sync * gojack_generic_callback_sync_create(jack_client_t *client) {
    struct gojack_generic_callback_sync *sync = (struct gojack_generic_callback_sync *) malloc(sizeof(struct gojack_generic_callback_sync));
    void *arg = (void *) sync;
    sync->base = cgo_callback_sync_create();
    cgo_callback_sync_set_log_callback(sync->base, &handle_log, NULL);
    pthread_mutex_init(&sync->lock, NULL);
    sync->client = client;
    jack_set_freewheel_callback(client, &handle_freewheel, arg);
    jack_set_buffer_size_callback(client, &handle_buffer_size, arg);
    //jack_set_sample_rate_callback(client, &handle_sample_rate, arg);
    jack_set_client_registration_callback(client, &handle_client_registration, arg);
    jack_set_port_registration_callback(client, &handle_port_registration, arg);
    jack_set_port_connect_callback(client, &handle_port_connect, arg);
    jack_set_port_rename_callback(client, &handle_port_rename, arg);
    jack_set_graph_order_callback(client, &handle_graph_order, arg);
    jack_set_xrun_callback(client, &handle_xrun, arg);
    //jack_set_latency_callback(client, &handle_latency, arg);
    return sync;
}
Example #6
0
int
main (int argc, char *argv[])
{
	// Make output unbuffered
	setbuf(stdout, NULL);
	setbuf(stderr, NULL);

	if (argc >= 2 && 
		( strcmp(argv[1],"-h")==0 || strcmp(argv[1],"--help")==0))
	{
		printf("send jack events as OSC message\n\n");
		printf("syntax: jack_oscev <osc local port> <osc remote host> <osc remote port>\n\n");
		printf("all params are optional. order matters.\n");
		printf("default values: 6677 127.0.0.1 6678\n");
		printf("example: jack_oscev 9988 10.10.10.42\n");
		printf("test on .42: oscdump 6678\n\n");
		printf("messages sent by jack_oscev (example content):\n");
		printf("  /oscev/started\n");
		printf("  /oscev/client/registered s \"meter\"\n");
		printf("  /oscev/port/registered i 24\n");
		printf("  /oscev/port/connected ii 2 24\n");
		printf("  /oscev/port/disconnected ii 2 24\n");
		printf("  /oscev/port/unregistered i 24\n");
		printf("  /oscev/client/unregistered s \"meter\"\n\n");
		//printf("");

		printf("jack_oscev source at https://github.com/7890/jack_tools\n\n");
		return(0);
	}

        //remote port
        if (argc >= 4)
        {
                osc_send_to_port=argv[3];
        }

	if (argc >= 3)
	{
		osc_send_to_host=argv[2];
	}

	//local port
	if (argc >= 2)
	{
		osc_my_server_port=argv[1];
	}
 
	//init osc
	st = lo_server_thread_new(osc_my_server_port, error);
	loa = lo_address_new(osc_send_to_host, osc_send_to_port);

	lo_server_thread_start(st);

	lo_message reply=lo_message_new();
	lo_send_message (loa, "/oscev/started", reply);
	lo_message_free (reply);

	jack_options_t options = JackNullOption;
	jack_status_t status;

	if ((client = jack_client_open ("oscev", options, &status, NULL)) == 0) {
		fprintf (stderr, "jack_client_open() failed, "
			 "status = 0x%2.0x\n", status);
		if (status & JackServerFailed) {
			fprintf (stderr, "Unable to connect to JACK server\n");
		}
		return 1;
	}
	
	if (jack_set_port_registration_callback (client, port_callback, NULL)) {
		fprintf (stderr, "cannot set port registration callback\n");
		return 1;
	}
	if (jack_set_port_connect_callback (client, connect_callback, NULL)) {
		fprintf (stderr, "cannot set port connect callback\n");
		return 1;
	}
	if (jack_set_client_registration_callback (client, client_callback, NULL)) {
		fprintf (stderr, "cannot set client registration callback\n");
		return 1;
	}
/*
	//don't register for now
	if (jack_set_graph_order_callback (client, graph_callback, NULL)) {
		fprintf (stderr, "cannot set graph order registration callback\n");
		return 1;
	}
*/
	if (jack_activate (client)) {
		fprintf (stderr, "cannot activate client");
		return 1;
	}
    
#ifndef WIN32
	signal(SIGINT, signal_handler);
	signal(SIGQUIT, signal_handler);
	signal(SIGHUP, signal_handler);
#endif
	signal(SIGABRT, signal_handler);
	signal(SIGTERM, signal_handler);

#ifdef WIN32
	Sleep(INFINITE);
#else
	sleep (-1);
#endif
	exit (0);
}
Example #7
0
void JACKInput::Init() {

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

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

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

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

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

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

	}

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

}
Example #8
0
    /*
        JackProxyDriver is wrapped in a JackWaitCallbackDriver decorator that behaves
        as a "dummy driver, until Initialize method returns.
    */
    bool JackProxyDriver::Initialize()
    {
        jack_log("JackProxyDriver::Initialize");

        // save existing local connections if needed
        if (fAutoSave) {
            SaveConnections(0);
        }

        // new loading, but existing client, restart the driver
        if (fClient) {
            jack_info("JackProxyDriver restarting...");
            jack_client_close(fClient);
        }
        FreePorts();

        // display some additional infos
        jack_info("JackProxyDriver started in %s mode.",
                    (fEngineControl->fSyncMode) ? "sync" : "async");

        do {
            jack_status_t status;
            char *old = NULL;

            if (fPromiscuous) {
                // as we are fiddling with the environment variable content, save it
                const char* tmp = getenv("JACK_PROMISCUOUS_SERVER");
                if (tmp) {
                    old = strdup(tmp);
                }
                // temporary enable promiscuous mode
                if (setenv("JACK_PROMISCUOUS_SERVER", fPromiscuous, 1) < 0) {
                    free(old);
                    jack_error("Error allocating memory.");
                    return false;
                }
            }

            jack_info("JackProxyDriver connecting to %s", fUpstream);
            fClient = jack_client_open(fClientName, static_cast<jack_options_t>(JackNoStartServer|JackServerName), &status, fUpstream);

            if (fPromiscuous) {
                // restore previous environment variable content
                if (old) {
                    if (setenv("JACK_PROMISCUOUS_SERVER", old, 1) < 0) {
                        free(old);
                        jack_error("Error allocating memory.");
                        return false;
                    }
                    free(old);
                } else {
                    unsetenv("JACK_PROMISCUOUS_SERVER");
                }
            }

            // the connection failed, try again later
            if (!fClient) {
                JackSleep(1000000);
            }

        } while (!fClient);
        jack_info("JackProxyDriver connected to %s", fUpstream);

        // we are connected, let's register some callbacks

        jack_on_shutdown(fClient, shutdown_callback, this);

        if (jack_set_process_callback(fClient, process_callback, this) != 0) {
            jack_error("Cannot set process callback.");
            return false;
        }

        if (jack_set_buffer_size_callback(fClient, bufsize_callback, this) != 0) {
            jack_error("Cannot set buffer size callback.");
            return false;
        }

        if (jack_set_sample_rate_callback(fClient, srate_callback, this) != 0) {
            jack_error("Cannot set sample rate callback.");
            return false;
        }

        if (jack_set_port_connect_callback(fClient, connect_callback, this) != 0) {
            jack_error("Cannot set port connect callback.");
            return false;
        }

        // detect upstream physical playback ports if needed
        if (fDetectPlaybackChannels) {
            fPlaybackChannels = CountIO(JACK_DEFAULT_AUDIO_TYPE, JackPortIsPhysical | JackPortIsOutput);
        }

        // detect upstream physical capture ports if needed
        if (fDetectCaptureChannels) {
            fCaptureChannels = CountIO(JACK_DEFAULT_AUDIO_TYPE, JackPortIsPhysical | JackPortIsInput);
        }

        if (AllocPorts() != 0) {
            jack_error("Can't allocate ports.");
            return false;
        }

        bufsize_callback(jack_get_buffer_size(fClient));
        srate_callback(jack_get_sample_rate(fClient));

        // restore local connections if needed
        if (fAutoSave) {
            LoadConnections(0);
        }

        // everything is ready, start upstream processing
        if (jack_activate(fClient) != 0) {
            jack_error("Cannot activate jack client.");
            return false;
        }

        // connect upstream ports if needed
        if (fAutoConnect) {
            ConnectPorts();
        }

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

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

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