void
gst_jack_audio_client_init (void)
{
  GST_DEBUG_CATEGORY_INIT (gst_jack_audio_client_debug, "jackclient", 0,
      "jackclient helpers");

  jack_set_error_function (jack_log_error);
  jack_set_info_function (jack_info_error);
}
Beispiel #2
0
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 ();
}
Beispiel #3
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;
	}
Beispiel #4
0
int soundio_jack_init(struct SoundIoPrivate *si) {
    SoundIoJack *sij = &si->backend_data.jack;
    SoundIo *soundio = &si->pub;

    if (!global_msg_callback_flag.test_and_set()) {
        if (soundio->jack_error_callback)
            jack_set_error_function(soundio->jack_error_callback);
        if (soundio->jack_info_callback)
            jack_set_info_function(soundio->jack_info_callback);
        global_msg_callback_flag.clear();
    }

    sij->mutex = soundio_os_mutex_create();
    if (!sij->mutex) {
        destroy_jack(si);
        return SoundIoErrorNoMem;
    }

    sij->cond = soundio_os_cond_create();
    if (!sij->cond) {
        destroy_jack(si);
        return SoundIoErrorNoMem;
    }

    // We pass JackNoStartServer due to
    // https://github.com/jackaudio/jack2/issues/138
    jack_status_t status;
    sij->client = jack_client_open(soundio->app_name, JackNoStartServer, &status);
    if (!sij->client) {
        destroy_jack(si);
        assert(!(status & JackInvalidOption));
        if (status & JackShmFailure)
            return SoundIoErrorSystemResources;
        if (status & JackNoSuchClient)
            return SoundIoErrorNoSuchClient;

        return SoundIoErrorInitAudioBackend;
    }

    int err;
    if ((err = jack_set_buffer_size_callback(sij->client, buffer_size_callback, si))) {
        destroy_jack(si);
        return SoundIoErrorInitAudioBackend;
    }
    if ((err = jack_set_sample_rate_callback(sij->client, sample_rate_callback, si))) {
        destroy_jack(si);
        return SoundIoErrorInitAudioBackend;
    }
    if ((err = jack_set_port_registration_callback(sij->client, port_registration_callback, si))) {
        destroy_jack(si);
        return SoundIoErrorInitAudioBackend;
    }
    if ((err = jack_set_port_rename_callback(sij->client, port_rename_calllback, si))) {
        destroy_jack(si);
        return SoundIoErrorInitAudioBackend;
    }
    jack_on_shutdown(sij->client, shutdown_callback, si);

    sij->refresh_devices_flag.clear();
    sij->period_size = jack_get_buffer_size(sij->client);
    sij->sample_rate = jack_get_sample_rate(sij->client);

    if ((err = jack_activate(sij->client))) {
        destroy_jack(si);
        return SoundIoErrorInitAudioBackend;
    }

    if ((err = refresh_devices(si))) {
        destroy_jack(si);
        return err;
    }

    si->destroy = destroy_jack;
    si->flush_events = flush_events_jack;
    si->wait_events = wait_events_jack;
    si->wakeup = wakeup_jack;
    si->force_device_scan = force_device_scan_jack;

    si->outstream_open = outstream_open_jack;
    si->outstream_destroy = outstream_destroy_jack;
    si->outstream_start = outstream_start_jack;
    si->outstream_begin_write = outstream_begin_write_jack;
    si->outstream_end_write = outstream_end_write_jack;
    si->outstream_clear_buffer = outstream_clear_buffer_jack;
    si->outstream_pause = outstream_pause_jack;
    si->outstream_get_latency = outstream_get_latency_jack;

    si->instream_open = instream_open_jack;
    si->instream_destroy = instream_destroy_jack;
    si->instream_start = instream_start_jack;
    si->instream_begin_read = instream_begin_read_jack;
    si->instream_end_read = instream_end_read_jack;
    si->instream_pause = instream_pause_jack;
    si->instream_get_latency = instream_get_latency_jack;

    return 0;
}
Beispiel #5
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;
}
Beispiel #6
0
mfp_context * 
mfp_jack_startup(char * client_name, int num_inputs, int num_outputs) 
{
    mfp_context * ctxt;
    jack_status_t status;
    jack_port_t * port;
    int i;

    char namebuf[16];

    ctxt = mfp_context_new(CTYPE_JACK);

    if ((ctxt->info.jack->client = jack_client_open(client_name, JackNullOption, &status, NULL)) == 0) {
        fprintf (stderr, "jack_client_open() failed.");
        return NULL;
    }
    
    /* callbacks */ 
    jack_set_process_callback(ctxt->info.jack->client, process_cb, ctxt);
    jack_set_graph_order_callback(ctxt->info.jack->client, reorder_cb, ctxt);

    /* no info logging to console */ 
    jack_set_info_function(info_cb);
    jack_set_error_function(info_cb);
    
    /* create application input and output ports */ 
    if (num_inputs > 0) {
        ctxt->info.jack->input_ports = g_array_new(TRUE, TRUE, sizeof(jack_port_t *));

        for(i=0; i<num_inputs; i++) {
            snprintf(namebuf, 16, "in_%d", i);
            port = jack_port_register (ctxt->info.jack->client, namebuf, JACK_DEFAULT_AUDIO_TYPE, 
                                       JackPortIsInput, i);
            g_array_append_val(ctxt->info.jack->input_ports, port);
        }
    }

    if (num_outputs > 0) {
        ctxt->info.jack->output_ports = g_array_new(TRUE, TRUE, sizeof(jack_port_t *));

        for(i=0; i<num_outputs; i++) {
            snprintf(namebuf, 16, "out_%d", i);
            port = jack_port_register (ctxt->info.jack->client, namebuf, JACK_DEFAULT_AUDIO_TYPE, 
                                       JackPortIsOutput, i);
            g_array_append_val(ctxt->info.jack->output_ports, port);
        }

    }
    
    /* find out sample rate */ 
    ctxt->samplerate = jack_get_sample_rate(ctxt->info.jack->client);
    ctxt->blocksize = jack_get_buffer_size(ctxt->info.jack->client);
    mfp_in_latency = 3000.0 * ctxt->blocksize / ctxt->samplerate; 
    mfp_out_latency = 3000.0 * ctxt->blocksize / ctxt->samplerate; 

    printf("jack_startup: samplerate=%d, blocksize=%d, in_latency=%.1f, out_latency = %.1f\n", 
            ctxt->samplerate, ctxt->blocksize, mfp_in_latency, mfp_out_latency); 

    /* tell the JACK server that we are ready to roll */
    if (jack_activate (ctxt->info.jack->client)) {
        fprintf (stderr, "cannot activate client");
        return NULL;
    }
    else {
        ctxt->activated = 1;
    }

    return ctxt;

}
Beispiel #7
0
int run(size_t port_count, const char** ports, const char* client_name,
	const char* file_path, jackoff_format_t* format, int bitrate,
	size_t channels, float buffer_duration, time_t recording_duration,
	jack_options_t options)
{
	jackoff_client_t* client;
	jackoff_encoder_t* encoder;
	jackoff_session_t* session;
	time_t stop_time = (time_t) 0;
	size_t i;
	long result;
	
	jack_set_error_function(handle_jack_error);
	jack_set_info_function(handle_jack_info);
	
	if (recording_duration) {
		stop_time = time(NULL) + recording_duration;
	}
	
	client = jackoff_create_client(client_name, options, channels, buffer_duration);
	
	if (jackoff_activate_client(client) != 0) {
		jackoff_destroy_client(client);
		jackoff_error("Failed to activate JACK client.");
	}
	
	signal(SIGTERM, handle_signal);
	signal(SIGINT, handle_signal);
	signal(SIGHUP, handle_signal);
	
	if (port_count == 0) {
		jackoff_auto_connect_client_ports(client);
	} else {
		for (i = 0; i < port_count; i++) {
			jackoff_connect_client_port(client, i, ports[i]);
		}
	}
	
	encoder = jackoff_create_encoder(client, format, bitrate);
	if (!encoder) {
		jackoff_destroy_client(client);
		return 1;
	}
	
	session = jackoff_open_session(client, encoder, file_path);
	if (!session) {
		jackoff_destroy_encoder(encoder);
		jackoff_destroy_client(client);
		return 2;
	}
	
	running = 1;
	jackoff_info("Recording.");
	while (running && (stop_time == 0 || time(NULL) < stop_time)) {
		if (client->ring_buffer_overflowed) {
			jackoff_warn("Ring buffer overflow; some audio was not written.");
			client->ring_buffer_overflowed = 0;
		}
		
		if (!client->status) {
			break;
		}
		
		result = jackoff_write_session(session);
		if (result == 0) {
			// Sleep for 1/4th the ring buffer duration.
			jackoff_debug("Sleeping for %.04fms.", (buffer_duration / 4));
			usleep(1000000 * (buffer_duration / 4));
		} else if (result == -1) {
			jackoff_close_session(session);
			jackoff_destroy_encoder(encoder);
			jackoff_destroy_client(client);
			jackoff_error("Encoding error. Shutting down.");
			return 3;
		}
	}
	
	jackoff_close_session(session);
	jackoff_destroy_encoder(encoder);
	jackoff_destroy_client(client);
	
	return 0;
}