diff options
| author | Piotr Pawlow <pp@siedziba.pl> | 2014-03-13 20:51:31 +0100 |
|---|---|---|
| committer | Piotr Pawlow <pp@siedziba.pl> | 2014-03-13 20:51:31 +0100 |
| commit | c04af18902322cea1bd05b6f01b7860ca7bfa432 (patch) | |
| tree | d8d3f812112c0cc835fd29e68d92e297e0164b52 /src/lingot-audio-jack.c | |
- import version 0.9.1 from upstream
Diffstat (limited to 'src/lingot-audio-jack.c')
| -rw-r--r-- | src/lingot-audio-jack.c | 349 |
1 files changed, 349 insertions, 0 deletions
diff --git a/src/lingot-audio-jack.c b/src/lingot-audio-jack.c new file mode 100644 index 0000000..5135c38 --- /dev/null +++ b/src/lingot-audio-jack.c @@ -0,0 +1,349 @@ +/* + * lingot, a musical instrument tuner. + * + * Copyright (C) 2004-2011 Ibán Cereijo Graña, Jairo Chapela Martínez. + * + * This file is part of lingot. + * + * lingot is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * lingot is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with lingot; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#include <stdio.h> + +#include "lingot-defs.h" +#include "lingot-audio-jack.h" +#include "lingot-i18n.h" +#include "lingot-msg.h" + +#ifdef JACK +#include <jack/jack.h> + +// persistent JACK client to obtain hardware parameters +jack_client_t* client = NULL; +pthread_mutex_t stop_mutex = PTHREAD_MUTEX_INITIALIZER; + +// this array allows us to reconnect the client to the last ports it was +// connected in a previous session +#define MAX_LAST_PORTS 10 +char last_ports[MAX_LAST_PORTS][80]; + +int lingot_audio_jack_process(jack_nframes_t nframes, void* param) { + LingotAudioHandler* audio = param; + audio->nframes = nframes; + + pthread_mutex_lock(&stop_mutex); + if (audio->running) { + lingot_audio_jack_read(audio); + audio->process_callback(audio->flt_read_buffer, + audio->read_buffer_size, audio->process_callback_arg); + } + pthread_mutex_unlock(&stop_mutex); + + return 0; +} + +// JACK calls this shutdown_callback if the server ever shuts down or +// decides to disconnect the client. +void lingot_audio_jack_shutdown(void* param) { + LingotAudioHandler* audio = param; + lingot_msg_add_error(_("Missing connection with JACK audio server")); + pthread_mutex_lock(&stop_mutex); + audio->interrupted = 1; + pthread_mutex_unlock(&stop_mutex); +} +#endif + +LingotAudioHandler* lingot_audio_jack_new(char* device, int sample_rate) { + + LingotAudioHandler* audio = NULL; + +# ifdef JACK + const char* exception; + const char **ports = NULL; + const char *client_name = "lingot"; + const char *server_name = NULL; + + jack_options_t options = JackNoStartServer; + jack_status_t status; + + audio = malloc(sizeof(LingotAudioHandler)); + strcpy(audio->device, ""); + + audio->audio_system = AUDIO_SYSTEM_JACK; + audio->jack_client = jack_client_open(client_name, options, &status, + server_name); + + try { + if (audio->jack_client == NULL) { + throw(_("Unable to connect to JACK server")); + } + + if (status & JackServerStarted) { + fprintf(stderr, "JACK server started\n"); + } + if (status & JackNameNotUnique) { + client_name = jack_get_client_name(audio->jack_client); + fprintf(stderr, "unique name `%s' assigned\n", client_name); + } + + jack_on_shutdown(audio->jack_client, lingot_audio_jack_shutdown, audio); + + audio->real_sample_rate = jack_get_sample_rate(audio->jack_client); + audio->read_buffer_size = jack_get_buffer_size(audio->jack_client); + + // printf("engine sample rate: %" PRIu32 "\n", jack_get_sample_rate( + // audio->jack_client)); + // printf("buffer size: %" PRIu32 "\n", jack_get_buffer_size( + // audio->jack_client)); + + audio->jack_input_port = jack_port_register(audio->jack_client, + "input", JACK_DEFAULT_AUDIO_TYPE, JackPortIsInput, 0); + + if ((audio->jack_input_port == NULL)) { + throw(_("No more JACK ports available")); + } + + } catch { + free(audio); + audio = NULL; + lingot_msg_add_error(exception); + } + + if (ports != NULL) + free(ports); + + if (audio != NULL) { + client = audio->jack_client; + } + +# else + lingot_msg_add_error( + _("The application has not been built with JACK support")); +# endif + return audio; +} + +void lingot_audio_jack_destroy(LingotAudioHandler* audio) { +# ifdef JACK + if (audio != NULL) { + //jack_cycle_wait(audio->jack_client); + // jack_deactivate(audio->jack_client); + jack_client_close(audio->jack_client); + client = NULL; + } +# endif +} + +int lingot_audio_jack_read(LingotAudioHandler* audio) { +# ifdef JACK + register int i; + float* in = jack_port_get_buffer(audio->jack_input_port, audio->nframes); + for (i = 0; i < audio->nframes; i++) + audio->flt_read_buffer[i] = in[i] * 32768; + return 0; +# else + return -1; +# endif +} + +LingotAudioSystemProperties* lingot_audio_jack_get_audio_system_properties( + audio_system_t audio_system) { + + LingotAudioSystemProperties* properties = NULL; +# ifdef JACK + properties = (LingotAudioSystemProperties*) malloc(1 + * sizeof(LingotAudioSystemProperties)); + + int sample_rate = -1; + + const char *client_name = "lingot-get-sample-rate"; + const char *server_name = NULL; + + jack_options_t options = JackNoStartServer; + jack_status_t status; + jack_client_t* jack_client = NULL; + const char **ports = NULL; + const char* exception; + + unsigned long int flags = JackPortIsOutput; + + try { + if (client != NULL) { + sample_rate = jack_get_sample_rate(client); + ports = jack_get_ports(client, NULL, NULL, flags); + } else { + jack_client = jack_client_open(client_name, options, &status, + server_name); + if (jack_client == NULL) { + throw(_("Unable to connect to JACK server")); + } + if (status & JackServerStarted) { + fprintf(stderr, "JACK server started\n"); + } + if (status & JackNameNotUnique) { + client_name = jack_get_client_name(jack_client); + fprintf(stderr, "unique name `%s' assigned\n", client_name); + } + + sample_rate = jack_get_sample_rate(jack_client); + + ports = jack_get_ports(jack_client, NULL, NULL, flags); + } + } catch { + // here I throw a warning message because we are only ontaining the + // audio properties + lingot_msg_add_warning(exception); + } + + properties->forced_sample_rate = 1; + properties->n_devices = 0; + properties->devices = NULL; + + if (ports != NULL) { + int i; + for (i = 0; ports[i] != NULL; i++) { + } + properties->n_devices = i; + + if (properties->n_devices != 0) { + properties->devices = malloc(properties->n_devices * sizeof(char*)); + for (i = 0; ports[i] != NULL; i++) { + properties->devices[i] = strdup(ports[i]); + } + } + + } + + if (sample_rate == -1) { + properties->n_sample_rates = 0; + properties->sample_rates = NULL; + } else { + properties->n_sample_rates = 1; + properties->sample_rates = malloc(properties->n_sample_rates + * sizeof(int)); + properties->sample_rates[0] = sample_rate; + } + + if (ports != NULL) + free(ports); + + if (jack_client != NULL) + jack_client_close(jack_client); + +# else + lingot_msg_add_error( + _("The application has not been built with JACK support")); +# endif + + return properties; +} + +int lingot_audio_jack_start(LingotAudioHandler* audio) { + int result = 0; + +# ifdef JACK + int index = 0; + const char **ports = NULL; + const char* exception; + jack_set_process_callback(audio->jack_client, lingot_audio_jack_process, + audio); + + try { + if (jack_activate(audio->jack_client)) { + throw(_("Cannot activate client")); + } + + ports + = jack_get_ports(audio->jack_client, NULL, NULL, + JackPortIsOutput); + if (ports == NULL) { + throw(_("No active capture ports")); + } + + // try to connect the client to the ports is was connected before + int j = 0; + int connections = 0; + for (j = 0; j < MAX_LAST_PORTS; j++) { + for (index = 0; ports[index]; index++) { + if (!strcmp(last_ports[j], ports[index])) { + if (jack_connect(audio->jack_client, ports[index], + jack_port_name(audio->jack_input_port))) { + throw(_("Cannot connect input ports")); + } else { + connections++; + } + } + } + } + + // if there wasn't connections before, we connect the client to the + // first physical port + if (!connections) { + free(ports); + ports = jack_get_ports(audio->jack_client, NULL, NULL, + JackPortIsPhysical | JackPortIsOutput); + if (ports == NULL) { + throw(_("No physical capture ports")); + } + + if (jack_connect(audio->jack_client, ports[0], jack_port_name( + audio->jack_input_port))) { + throw(_("Cannot connect input ports")); + } + } + + } catch { + lingot_msg_add_error(exception); + result = -1; + } + + free(ports); +# else + lingot_msg_add_error( + _("The application has not been built with JACK support")); +# endif + + return result; +} + +void lingot_audio_jack_stop(LingotAudioHandler* audio) { +# ifdef JACK + //jack_cycle_wait(audio->jack_client); + const char** ports = jack_get_ports(audio->jack_client, NULL, NULL, + JackPortIsOutput); + + if (ports != NULL) { + int i, j = 0; + + for (i = 0; i < MAX_LAST_PORTS; i++) { + strcpy(last_ports[i], ""); + } + + for (i = 0; ports[i]; i++) { + if (jack_port_connected(jack_port_by_name(audio->jack_client, + ports[i]))) { + strcpy(last_ports[j++], ports[i]); + } + } + } + + pthread_mutex_lock(&stop_mutex); + jack_deactivate(audio->jack_client); + pthread_mutex_unlock(&stop_mutex); +# else + lingot_msg_add_error( + _("The application has not been built with JACK support")); +# endif +} |
