@@ -0,0 +1,9 @@ | |||||
[submodule "jack"] | |||||
path = jack | |||||
url = git://github.com/jackaudio/headers.git | |||||
[submodule "tools"] | |||||
path = tools | |||||
url = git://github.com/jackaudio/tools.git | |||||
[submodule "example-clients"] | |||||
path = example-clients | |||||
url = git://github.com/jackaudio/example-clients.git |
@@ -0,0 +1 @@ | |||||
Subproject commit 4b9f2362b4a0d15f18bfce6056d3ca897db9b401 |
@@ -1,26 +0,0 @@ | |||||
.deps | |||||
.libs | |||||
Makefile | |||||
Makefile.in | |||||
jack_cache_killer | |||||
jack_connect | |||||
jack_disconnect | |||||
jack_freewheel | |||||
jack_impulse_grabber | |||||
jack_monitor_client | |||||
jack_simple_client | |||||
jackrec | |||||
jack_bufsize | |||||
jack_showtime | |||||
jack_lsp | |||||
jack_metro | |||||
jack_unload | |||||
jack_load | |||||
jack_transport | |||||
inprocess.la | |||||
inprocess.lo | |||||
intime.la | |||||
intime.lo | |||||
jack_alias | |||||
jack_evmon | |||||
jack_thread_wait |
@@ -1,92 +0,0 @@ | |||||
MAINTAINERCLEANFILES = Makefile.in | |||||
if HAVE_SNDFILE | |||||
JACKREC = jack_rec | |||||
dist-check-sndfile: | |||||
else | |||||
JACKREC = | |||||
dist-check-sndfile: | |||||
@echo | |||||
@echo ' ******' You need sndfile installed to make dist.' ******' | |||||
@echo | |||||
@false | |||||
endif | |||||
bin_PROGRAMS = jack_simple_client \ | |||||
jack_simple_session_client \ | |||||
jack_transport_client \ | |||||
jack_impulse_grabber \ | |||||
jack_metro \ | |||||
jack_showtime \ | |||||
jack_midisine \ | |||||
jack_midiseq \ | |||||
jack_latent_client \ | |||||
jack_server_control \ | |||||
$(JACKREC) | |||||
if HAVE_SNDFILE | |||||
# note! jackrec_CFLAGS syntax not supported by automake-1.4 | |||||
sndfile_cflags = @SNDFILE_CFLAGS@ | |||||
endif | |||||
AM_CFLAGS = -I.. $(JACK_CFLAGS) $(sndfile_cflags) | |||||
AM_CXXFLAGS = -I.. $(JACK_CFLAGS) $(sndfile_cflags) | |||||
jack_simple_client_SOURCES = simple_client.c | |||||
jack_simple_client_LDFLAGS = @OS_LDFLAGS@ | |||||
jack_simple_client_LDADD = $(top_builddir)/libjack/libjack.la | |||||
jack_simple_session_client_SOURCES = simple_session_client.c | |||||
jack_simple_session_client_LDFLAGS = @OS_LDFLAGS@ | |||||
jack_simple_session_client_LDADD = $(top_builddir)/libjack/libjack.la | |||||
jack_transport_client_SOURCES = transport_client.c | |||||
jack_transport_client_LDFLAGS = @OS_LDFLAGS@ | |||||
jack_transport_client_LDADD = $(top_builddir)/libjack/libjack.la | |||||
jack_metro_SOURCES = metro.c | |||||
jack_metro_LDFLAGS = @OS_LDFLAGS@ | |||||
jack_metro_LDADD = $(top_builddir)/libjack/libjack.la | |||||
jack_showtime_SOURCES = showtime.c | |||||
jack_showtime_LDFLAGS = @OS_LDFLAGS@ | |||||
jack_showtime_LDADD = $(top_builddir)/libjack/libjack.la | |||||
jack_impulse_grabber_SOURCES = impulse_grabber.c | |||||
jack_impulse_grabber_LDFLAGS = @OS_LDFLAGS@ | |||||
jack_impulse_grabber_LDADD = $(top_builddir)/libjack/libjack.la | |||||
jack_midiseq_SOURCES = midiseq.c | |||||
jack_midiseq_LDFLAGS = @OS_LDFLAGS@ | |||||
jack_midiseq_LDADD = $(top_builddir)/libjack/libjack.la | |||||
jack_midisine_SOURCES = midisine.c | |||||
jack_midisine_LDFLAGS = @OS_LDFLAGS@ | |||||
jack_midisine_LDADD = $(top_builddir)/libjack/libjack.la | |||||
jack_latent_client_SOURCES = latent_client.c | |||||
jack_latent_client_LDFLAGS = @OS_LDFLAGS@ | |||||
jack_latent_client_LDADD = $(top_builddir)/libjack/libjack.la | |||||
jack_server_control_SOURCES = server_control.c | |||||
jack_server_control_LDFLAGS = @OS_LDFLAGS@ | |||||
jack_server_control_LDADD = $(top_builddir)/jackd/libjackserver.la | |||||
if HAVE_SNDFILE | |||||
jack_rec_SOURCES = capture_client.c | |||||
jack_rec_LDFLAGS = @SNDFILE_LIBS@ @OS_LDFLAGS@ | |||||
jack_rec_LDADD = $(top_builddir)/libjack/libjack.la | |||||
endif | |||||
# | |||||
# sample in-process client(s) | |||||
# | |||||
ip_clientdir = $(ADDON_DIR) | |||||
ip_client_LTLIBRARIES = inprocess.la intime.la | |||||
inprocess_la_LDFLAGS = -module -avoid-version @OS_LDFLAGS@ | |||||
inprocess_la_SOURCES = inprocess.c | |||||
intime_la_LDFLAGS = -module -avoid-version @OS_LDFLAGS@ | |||||
intime_la_SOURCES = intime.c |
@@ -1,344 +0,0 @@ | |||||
/* | |||||
Copyright (C) 2001 Paul Davis | |||||
Copyright (C) 2003 Jack O'Quin | |||||
This program 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. | |||||
This program 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 this program; if not, write to the Free Software | |||||
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. | |||||
* 2002/08/23 - modify for libsndfile 1.0.0 <andy@alsaplayer.org> | |||||
* 2003/05/26 - use ringbuffers - joq | |||||
*/ | |||||
#include <stdio.h> | |||||
#include <stdlib.h> | |||||
#include <string.h> | |||||
#include <errno.h> | |||||
#include <unistd.h> | |||||
#include <sndfile.h> | |||||
#include <pthread.h> | |||||
#include <getopt.h> | |||||
#include <jack/jack.h> | |||||
#include <jack/ringbuffer.h> | |||||
typedef struct _thread_info { | |||||
pthread_t thread_id; | |||||
SNDFILE *sf; | |||||
jack_nframes_t duration; | |||||
jack_nframes_t rb_size; | |||||
jack_client_t *client; | |||||
unsigned int channels; | |||||
int bitdepth; | |||||
char *path; | |||||
volatile int can_capture; | |||||
volatile int can_process; | |||||
volatile int status; | |||||
} jack_thread_info_t; | |||||
/* JACK data */ | |||||
unsigned int nports; | |||||
jack_port_t **ports; | |||||
jack_default_audio_sample_t **in; | |||||
jack_nframes_t nframes; | |||||
const size_t sample_size = sizeof(jack_default_audio_sample_t); | |||||
/* Synchronization between process thread and disk thread. */ | |||||
#define DEFAULT_RB_SIZE 16384 /* ringbuffer size in frames */ | |||||
jack_ringbuffer_t *rb; | |||||
pthread_mutex_t disk_thread_lock = PTHREAD_MUTEX_INITIALIZER; | |||||
pthread_cond_t data_ready = PTHREAD_COND_INITIALIZER; | |||||
long overruns = 0; | |||||
void * | |||||
disk_thread (void *arg) | |||||
{ | |||||
jack_thread_info_t *info = (jack_thread_info_t *) arg; | |||||
static jack_nframes_t total_captured = 0; | |||||
jack_nframes_t samples_per_frame = info->channels; | |||||
size_t bytes_per_frame = samples_per_frame * sample_size; | |||||
void *framebuf = malloc (bytes_per_frame); | |||||
pthread_setcanceltype (PTHREAD_CANCEL_ASYNCHRONOUS, NULL); | |||||
pthread_mutex_lock (&disk_thread_lock); | |||||
info->status = 0; | |||||
while (1) { | |||||
/* Write the data one frame at a time. This is | |||||
* inefficient, but makes things simpler. */ | |||||
while (info->can_capture && | |||||
(jack_ringbuffer_read_space (rb) >= bytes_per_frame)) { | |||||
jack_ringbuffer_read (rb, framebuf, bytes_per_frame); | |||||
if (sf_writef_float (info->sf, framebuf, 1) != 1) { | |||||
char errstr[256]; | |||||
sf_error_str (0, errstr, sizeof (errstr) - 1); | |||||
fprintf (stderr, | |||||
"cannot write sndfile (%s)\n", | |||||
errstr); | |||||
info->status = EIO; /* write failed */ | |||||
goto done; | |||||
} | |||||
if (++total_captured >= info->duration) { | |||||
printf ("disk thread finished\n"); | |||||
goto done; | |||||
} | |||||
} | |||||
/* wait until process() signals more data */ | |||||
pthread_cond_wait (&data_ready, &disk_thread_lock); | |||||
} | |||||
done: | |||||
pthread_mutex_unlock (&disk_thread_lock); | |||||
free (framebuf); | |||||
return 0; | |||||
} | |||||
int | |||||
process (jack_nframes_t nframes, void *arg) | |||||
{ | |||||
int chn; | |||||
size_t i; | |||||
jack_thread_info_t *info = (jack_thread_info_t *) arg; | |||||
/* Do nothing until we're ready to begin. */ | |||||
if ((!info->can_process) || (!info->can_capture)) | |||||
return 0; | |||||
for (chn = 0; chn < nports; chn++) | |||||
in[chn] = jack_port_get_buffer (ports[chn], nframes); | |||||
/* Sndfile requires interleaved data. It is simpler here to | |||||
* just queue interleaved samples to a single ringbuffer. */ | |||||
for (i = 0; i < nframes; i++) { | |||||
for (chn = 0; chn < nports; chn++) { | |||||
if (jack_ringbuffer_write (rb, (void *) (in[chn]+i), | |||||
sample_size) | |||||
< sample_size) | |||||
overruns++; | |||||
} | |||||
} | |||||
/* Tell the disk thread there is work to do. If it is already | |||||
* running, the lock will not be available. We can't wait | |||||
* here in the process() thread, but we don't need to signal | |||||
* in that case, because the disk thread will read all the | |||||
* data queued before waiting again. */ | |||||
if (pthread_mutex_trylock (&disk_thread_lock) == 0) { | |||||
pthread_cond_signal (&data_ready); | |||||
pthread_mutex_unlock (&disk_thread_lock); | |||||
} | |||||
return 0; | |||||
} | |||||
void | |||||
jack_shutdown (void *arg) | |||||
{ | |||||
fprintf (stderr, "JACK shutdown\n"); | |||||
// exit (0); | |||||
abort(); | |||||
} | |||||
void | |||||
setup_disk_thread (jack_thread_info_t *info) | |||||
{ | |||||
SF_INFO sf_info; | |||||
int short_mask; | |||||
sf_info.samplerate = jack_get_sample_rate (info->client); | |||||
sf_info.channels = info->channels; | |||||
switch (info->bitdepth) { | |||||
case 8: short_mask = SF_FORMAT_PCM_U8; | |||||
break; | |||||
case 16: short_mask = SF_FORMAT_PCM_16; | |||||
break; | |||||
case 24: short_mask = SF_FORMAT_PCM_24; | |||||
break; | |||||
case 32: short_mask = SF_FORMAT_PCM_32; | |||||
break; | |||||
default: short_mask = SF_FORMAT_PCM_16; | |||||
break; | |||||
} | |||||
sf_info.format = SF_FORMAT_WAV|short_mask; | |||||
if ((info->sf = sf_open (info->path, SFM_WRITE, &sf_info)) == NULL) { | |||||
char errstr[256]; | |||||
sf_error_str (0, errstr, sizeof (errstr) - 1); | |||||
fprintf (stderr, "cannot open sndfile \"%s\" for output (%s)\n", info->path, errstr); | |||||
jack_client_close (info->client); | |||||
exit (1); | |||||
} | |||||
if (info->duration == 0) { | |||||
info->duration = JACK_MAX_FRAMES; | |||||
} else { | |||||
info->duration *= sf_info.samplerate; | |||||
} | |||||
info->can_capture = 0; | |||||
pthread_create (&info->thread_id, NULL, disk_thread, info); | |||||
} | |||||
void | |||||
run_disk_thread (jack_thread_info_t *info) | |||||
{ | |||||
info->can_capture = 1; | |||||
pthread_join (info->thread_id, NULL); | |||||
sf_close (info->sf); | |||||
if (overruns > 0) { | |||||
fprintf (stderr, | |||||
"jackrec failed with %ld overruns.\n", overruns); | |||||
fprintf (stderr, " try a bigger buffer than -B %" | |||||
PRIu32 ".\n", info->rb_size); | |||||
info->status = EPIPE; | |||||
} | |||||
} | |||||
void | |||||
setup_ports (int sources, char *source_names[], jack_thread_info_t *info) | |||||
{ | |||||
unsigned int i; | |||||
size_t in_size; | |||||
/* Allocate data structures that depend on the number of ports. */ | |||||
nports = sources; | |||||
ports = (jack_port_t **) malloc (sizeof (jack_port_t *) * nports); | |||||
in_size = nports * sizeof (jack_default_audio_sample_t *); | |||||
in = (jack_default_audio_sample_t **) malloc (in_size); | |||||
rb = jack_ringbuffer_create (nports * sample_size * info->rb_size); | |||||
/* When JACK is running realtime, jack_activate() will have | |||||
* called mlockall() to lock our pages into memory. But, we | |||||
* still need to touch any newly allocated pages before | |||||
* process() starts using them. Otherwise, a page fault could | |||||
* create a delay that would force JACK to shut us down. */ | |||||
memset(in, 0, in_size); | |||||
memset(rb->buf, 0, rb->size); | |||||
for (i = 0; i < nports; i++) { | |||||
char name[64]; | |||||
sprintf (name, "input%d", i+1); | |||||
if ((ports[i] = jack_port_register (info->client, name, JACK_DEFAULT_AUDIO_TYPE, JackPortIsInput, 0)) == 0) { | |||||
fprintf (stderr, "cannot register input port \"%s\"!\n", name); | |||||
jack_client_close (info->client); | |||||
exit (1); | |||||
} | |||||
} | |||||
for (i = 0; i < nports; i++) { | |||||
if (jack_connect (info->client, source_names[i], jack_port_name (ports[i]))) { | |||||
fprintf (stderr, "cannot connect input port %s to %s\n", jack_port_name (ports[i]), source_names[i]); | |||||
jack_client_close (info->client); | |||||
exit (1); | |||||
} | |||||
} | |||||
info->can_process = 1; /* process() can start, now */ | |||||
} | |||||
int | |||||
main (int argc, char *argv[]) | |||||
{ | |||||
jack_client_t *client; | |||||
jack_thread_info_t thread_info; | |||||
int c; | |||||
int longopt_index = 0; | |||||
extern int optind, opterr; | |||||
int show_usage = 0; | |||||
char *optstring = "d:f:b:B:h"; | |||||
struct option long_options[] = { | |||||
{ "help", 0, 0, 'h' }, | |||||
{ "duration", 1, 0, 'd' }, | |||||
{ "file", 1, 0, 'f' }, | |||||
{ "bitdepth", 1, 0, 'b' }, | |||||
{ "bufsize", 1, 0, 'B' }, | |||||
{ 0, 0, 0, 0 } | |||||
}; | |||||
memset (&thread_info, 0, sizeof (thread_info)); | |||||
thread_info.rb_size = DEFAULT_RB_SIZE; | |||||
opterr = 0; | |||||
while ((c = getopt_long (argc, argv, optstring, long_options, &longopt_index)) != -1) { | |||||
switch (c) { | |||||
case 1: | |||||
/* getopt signals end of '-' options */ | |||||
break; | |||||
case 'h': | |||||
show_usage++; | |||||
break; | |||||
case 'd': | |||||
thread_info.duration = atoi (optarg); | |||||
break; | |||||
case 'f': | |||||
thread_info.path = optarg; | |||||
break; | |||||
case 'b': | |||||
thread_info.bitdepth = atoi (optarg); | |||||
break; | |||||
case 'B': | |||||
thread_info.rb_size = atoi (optarg); | |||||
break; | |||||
default: | |||||
fprintf (stderr, "error\n"); | |||||
show_usage++; | |||||
break; | |||||
} | |||||
} | |||||
if (show_usage || thread_info.path == NULL || optind == argc) { | |||||
fprintf (stderr, "usage: jackrec -f filename [ -d second ] [ -b bitdepth ] [ -B bufsize ] port1 [ port2 ... ]\n"); | |||||
exit (1); | |||||
} | |||||
if ((client = jack_client_open ("jackrec", JackNullOption, NULL)) == 0) { | |||||
fprintf (stderr, "jack server not running?\n"); | |||||
exit (1); | |||||
} | |||||
thread_info.client = client; | |||||
thread_info.channels = argc - optind; | |||||
thread_info.can_process = 0; | |||||
setup_disk_thread (&thread_info); | |||||
jack_set_process_callback (client, process, &thread_info); | |||||
jack_on_shutdown (client, jack_shutdown, &thread_info); | |||||
if (jack_activate (client)) { | |||||
fprintf (stderr, "cannot activate client"); | |||||
} | |||||
setup_ports (argc - optind, &argv[optind], &thread_info); | |||||
run_disk_thread (&thread_info); | |||||
jack_client_close (client); | |||||
jack_ringbuffer_free (rb); | |||||
exit (0); | |||||
} |
@@ -1,233 +0,0 @@ | |||||
/* | |||||
* Copyright (C) 2001 Steve Harris | |||||
* | |||||
* This program 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. | |||||
* | |||||
* This program 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 this program; if not, write to the Free Software | |||||
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. | |||||
* | |||||
*/ | |||||
#include <stdio.h> | |||||
#include <errno.h> | |||||
#include <unistd.h> | |||||
#include <stdlib.h> | |||||
#include <math.h> | |||||
#include <getopt.h> | |||||
#include <jack/jack.h> | |||||
jack_port_t *input_port; | |||||
jack_port_t *output_port; | |||||
unsigned int impulse_sent = 0; | |||||
float *response; | |||||
unsigned long response_duration; | |||||
unsigned long response_pos; | |||||
int grab_finished = 0; | |||||
int | |||||
process (jack_nframes_t nframes, void *arg) | |||||
{ | |||||
jack_default_audio_sample_t *out = (jack_default_audio_sample_t *) jack_port_get_buffer (output_port, nframes); | |||||
jack_default_audio_sample_t *in = (jack_default_audio_sample_t *) jack_port_get_buffer (input_port, nframes); | |||||
unsigned int i; | |||||
if (grab_finished) { | |||||
return 0; | |||||
} else if (impulse_sent) { | |||||
for(i=0; i<nframes && response_pos < response_duration; i++) { | |||||
response[response_pos++] = in[i]; | |||||
} | |||||
if (response_pos >= response_duration) { | |||||
grab_finished = 1; | |||||
} | |||||
for (i=0; i<nframes; i++) { | |||||
out[i] = 0.0f;; | |||||
} | |||||
} else { | |||||
out[0] = 1.0f; | |||||
for (i=1; i<nframes; i++) { | |||||
out[i] = 0.0f; | |||||
} | |||||
impulse_sent = 1; | |||||
} | |||||
return 0; | |||||
} | |||||
void | |||||
jack_shutdown (void *arg) | |||||
{ | |||||
exit (1); | |||||
} | |||||
int | |||||
main (int argc, char *argv[]) | |||||
{ | |||||
jack_client_t *client; | |||||
const char **ports; | |||||
float fs; // The sample rate | |||||
float peak; | |||||
unsigned long peak_sample; | |||||
unsigned int i; | |||||
float duration = 0.0f; | |||||
unsigned int c_format = 0; | |||||
int longopt_index = 0; | |||||
int c; | |||||
extern int optind, opterr; | |||||
int show_usage = 0; | |||||
char *optstring = "d:f:h"; | |||||
struct option long_options[] = { | |||||
{ "help", 1, 0, 'h' }, | |||||
{ "duration", 1, 0, 'd' }, | |||||
{ "format", 1, 0, 'f' }, | |||||
{ 0, 0, 0, 0 } | |||||
}; | |||||
while ((c = getopt_long (argc, argv, optstring, long_options, &longopt_index)) != -1) { | |||||
switch (c) { | |||||
case 1: | |||||
// end of opts, but don't care | |||||
break; | |||||
case 'h': | |||||
show_usage++; | |||||
break; | |||||
case 'd': | |||||
duration = (float)atof(optarg); | |||||
break; | |||||
case 'f': | |||||
if (*optarg == 'c' || *optarg == 'C') { | |||||
c_format = 1; | |||||
} | |||||
break; | |||||
default: | |||||
show_usage++; | |||||
break; | |||||
} | |||||
} | |||||
if (show_usage || duration <= 0.0f) { | |||||
fprintf(stderr, "usage: jack_impulse_grab -d duration [-f (C|gnuplot)]\n"); | |||||
exit(1); | |||||
} | |||||
/* try to become a client of the JACK server */ | |||||
if ((client = jack_client_open("impulse_grabber", JackNullOption, NULL)) == 0) { | |||||
fprintf (stderr, "jack server not running?\n"); | |||||
return 1; | |||||
} | |||||
/* tell the JACK server to call `process()' whenever | |||||
there is work to be done. | |||||
*/ | |||||
jack_set_process_callback (client, process, 0); | |||||
/* tell the JACK server to call `jack_shutdown()' if | |||||
it ever shuts down, either entirely, or if it | |||||
just decides to stop calling us. | |||||
*/ | |||||
jack_on_shutdown (client, jack_shutdown, 0); | |||||
/* display the current sample rate. once the client is activated | |||||
(see below), you should rely on your own sample rate | |||||
callback (see above) for this value. | |||||
*/ | |||||
fs = jack_get_sample_rate(client); | |||||
response_duration = (unsigned long) (fs * duration); | |||||
response = malloc(response_duration * sizeof(float)); | |||||
fprintf(stderr, | |||||
"Grabbing %f seconds (%lu samples) of impulse response\n", | |||||
duration, response_duration); | |||||
/* create two ports */ | |||||
input_port = jack_port_register (client, "input", JACK_DEFAULT_AUDIO_TYPE, JackPortIsInput, 0); | |||||
output_port = jack_port_register (client, "output", JACK_DEFAULT_AUDIO_TYPE, JackPortIsOutput, 0); | |||||
/* tell the JACK server that we are ready to roll */ | |||||
if (jack_activate (client)) { | |||||
fprintf (stderr, "cannot activate client"); | |||||
return 1; | |||||
} | |||||
/* connect the ports. Note: you can't do this before | |||||
the client is activated (this may change in the future). | |||||
*/ | |||||
if ((ports = jack_get_ports (client, NULL, NULL, JackPortIsPhysical|JackPortIsOutput)) == NULL) { | |||||
fprintf(stderr, "Cannot find any physical capture ports"); | |||||
exit(1); | |||||
} | |||||
if (jack_connect (client, ports[0], jack_port_name (input_port))) { | |||||
fprintf (stderr, "cannot connect input ports\n"); | |||||
} | |||||
free (ports); | |||||
if ((ports = jack_get_ports (client, NULL, NULL, JackPortIsPhysical|JackPortIsInput)) == NULL) { | |||||
fprintf(stderr, "Cannot find any physical playback ports"); | |||||
exit(1); | |||||
} | |||||
if (jack_connect (client, jack_port_name (output_port), ports[0])) { | |||||
fprintf (stderr, "cannot connect output ports\n"); | |||||
} | |||||
free (ports); | |||||
/* Wait for grab to finish */ | |||||
while (!grab_finished) { | |||||
sleep (1); | |||||
} | |||||
jack_client_close (client); | |||||
peak = response[0]; | |||||
peak_sample = 0; | |||||
if (c_format) { | |||||
printf("impulse[%lu] = {", response_duration); | |||||
for (i=0; i<response_duration; i++) { | |||||
if (i % 4 != 0) { | |||||
printf(" "); | |||||
} else { | |||||
printf("\n\t"); | |||||
} | |||||
printf("\"%+1.10f\"", response[i]); | |||||
if (i < response_duration - 1) { | |||||
printf(","); | |||||
} | |||||
if (fabs(response[i]) > peak) { | |||||
peak = fabs(response[i]); | |||||
peak_sample = i; | |||||
} | |||||
} | |||||
printf("\n};\n"); | |||||
} else { | |||||
for (i=0; i<response_duration; i++) { | |||||
printf("%1.12f\n", response[i]); | |||||
if (fabs(response[i]) > peak) { | |||||
peak = fabs(response[i]); | |||||
peak_sample = i; | |||||
} | |||||
} | |||||
} | |||||
fprintf(stderr, "Peak value was %f at sample %lu\n", peak, peak_sample); | |||||
exit (0); | |||||
} |
@@ -1,110 +0,0 @@ | |||||
/** @file inprocess.c | |||||
* | |||||
* @brief This demonstrates the basic concepts for writing a client | |||||
* that runs within the JACK server process. | |||||
* | |||||
* For the sake of example, a port_pair_t is allocated in | |||||
* jack_initialize(), passed to inprocess() as an argument, then freed | |||||
* in jack_finish(). | |||||
*/ | |||||
#include <stdlib.h> | |||||
#include <stdio.h> | |||||
#include <memory.h> | |||||
#include <jack/jack.h> | |||||
/** | |||||
* For the sake of example, an instance of this struct is allocated in | |||||
* jack_initialize(), passed to inprocess() as an argument, then freed | |||||
* in jack_finish(). | |||||
*/ | |||||
typedef struct { | |||||
jack_port_t *input_port; | |||||
jack_port_t *output_port; | |||||
} port_pair_t; | |||||
/** | |||||
* Called in the realtime thread on every process cycle. The entry | |||||
* point name was passed to jack_set_process_callback() from | |||||
* jack_initialize(). Although this is an internal client, its | |||||
* process() interface is identical to @ref simple_client.c. | |||||
* | |||||
* @return 0 if successful; otherwise jack_finish() will be called and | |||||
* the client terminated immediately. | |||||
*/ | |||||
int | |||||
inprocess (jack_nframes_t nframes, void *arg) | |||||
{ | |||||
port_pair_t *pp = arg; | |||||
jack_default_audio_sample_t *out = | |||||
jack_port_get_buffer (pp->output_port, nframes); | |||||
jack_default_audio_sample_t *in = | |||||
jack_port_get_buffer (pp->input_port, nframes); | |||||
memcpy (out, in, sizeof (jack_default_audio_sample_t) * nframes); | |||||
return 0; /* continue */ | |||||
} | |||||
/** | |||||
* This required entry point is called after the client is loaded by | |||||
* jack_internal_client_load(). | |||||
* | |||||
* @param client pointer to JACK client structure. | |||||
* @param load_init character string passed to the load operation. | |||||
* | |||||
* @return 0 if successful; otherwise jack_finish() will be called and | |||||
* the client terminated immediately. | |||||
*/ | |||||
int | |||||
jack_initialize (jack_client_t *client, const char *load_init) | |||||
{ | |||||
port_pair_t *pp = malloc (sizeof (port_pair_t)); | |||||
if (pp == NULL) | |||||
return 1; /* heap exhausted */ | |||||
jack_set_process_callback (client, inprocess, pp); | |||||
/* create a pair of ports */ | |||||
pp->input_port = jack_port_register (client, "input", | |||||
JACK_DEFAULT_AUDIO_TYPE, | |||||
JackPortIsInput, 0); | |||||
pp->output_port = jack_port_register (client, "output", | |||||
JACK_DEFAULT_AUDIO_TYPE, | |||||
JackPortIsOutput, 0); | |||||
/* join the process() cycle */ | |||||
jack_activate (client); | |||||
/* try to connect to the first physical input & output ports */ | |||||
if (jack_connect (client, "system:capture_1", | |||||
jack_port_name (pp->input_port))) { | |||||
fprintf (stderr, "cannot connect input port\n"); | |||||
return 1; /* terminate client */ | |||||
} | |||||
if (jack_connect (client, jack_port_name (pp->output_port), | |||||
"system:playback_1")) { | |||||
fprintf (stderr, "cannot connect output port\n"); | |||||
return 1; /* terminate client */ | |||||
} | |||||
return 0; /* success */ | |||||
} | |||||
/** | |||||
* This required entry point is called immediately before the client | |||||
* is unloaded, which could happen due to a call to | |||||
* jack_internal_client_unload(), or a nonzero return from either | |||||
* jack_initialize() or inprocess(). | |||||
* | |||||
* @param arg the same parameter provided to inprocess(). | |||||
*/ | |||||
void | |||||
jack_finish (void *arg) | |||||
{ | |||||
if (arg) | |||||
free ((port_pair_t *) arg); | |||||
} |
@@ -1,157 +0,0 @@ | |||||
/* | |||||
* intime.c -- JACK internal timebase master example client. | |||||
* | |||||
* To run: first start `jackd', then `jack_load intime intime 6/8,180bpm'. | |||||
*/ | |||||
/* Copyright (C) 2003 Jack O'Quin. | |||||
* | |||||
* This program 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. | |||||
* | |||||
* This program 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 this program; if not, write to the Free Software | |||||
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. | |||||
*/ | |||||
#include <stdio.h> | |||||
#include <string.h> | |||||
#include <jack/jack.h> | |||||
/* Time and tempo variables, global to the entire transport timeline. | |||||
* There is no attempt to keep a true tempo map. The default time | |||||
* signature is "march time": 4/4, 120bpm | |||||
*/ | |||||
float time_beats_per_bar = 4.0; | |||||
float time_beat_type = 4.0; | |||||
double time_ticks_per_beat = 1920.0; | |||||
double time_beats_per_minute = 120.0; | |||||
/* BBT timebase callback. | |||||
* | |||||
* Runs in the process thread. Realtime, must not wait. | |||||
*/ | |||||
void | |||||
timebbt (jack_transport_state_t state, jack_nframes_t nframes, | |||||
jack_position_t *pos, int new_pos, void *arg) | |||||
{ | |||||
double min; /* minutes since frame 0 */ | |||||
long abs_tick; /* ticks since frame 0 */ | |||||
long abs_beat; /* beats since frame 0 */ | |||||
if (new_pos) { | |||||
pos->valid = JackPositionBBT; | |||||
pos->beats_per_bar = time_beats_per_bar; | |||||
pos->beat_type = time_beat_type; | |||||
pos->ticks_per_beat = time_ticks_per_beat; | |||||
pos->beats_per_minute = time_beats_per_minute; | |||||
/* Compute BBT info from frame number. This is | |||||
* relatively simple here, but would become complex if | |||||
* we supported tempo or time signature changes at | |||||
* specific locations in the transport timeline. I | |||||
* make no claims for the numerical accuracy or | |||||
* efficiency of these calculations. */ | |||||
min = pos->frame / ((double) pos->frame_rate * 60.0); | |||||
abs_tick = min * pos->beats_per_minute * pos->ticks_per_beat; | |||||
abs_beat = abs_tick / pos->ticks_per_beat; | |||||
pos->bar = abs_beat / pos->beats_per_bar; | |||||
pos->beat = abs_beat - (pos->bar * pos->beats_per_bar) + 1; | |||||
pos->tick = abs_tick - (abs_beat * pos->ticks_per_beat); | |||||
pos->bar_start_tick = pos->bar * pos->beats_per_bar * | |||||
pos->ticks_per_beat; | |||||
pos->bar++; /* adjust start to bar 1 */ | |||||
/* some debug code... */ | |||||
fprintf(stderr, "\nnew position: %" PRIu32 "\tBBT: %3" | |||||
PRIi32 "|%" PRIi32 "|%04" PRIi32 "\n", | |||||
pos->frame, pos->bar, pos->beat, pos->tick); | |||||
} else { | |||||
/* Compute BBT info based on previous period. */ | |||||
pos->tick += (nframes * pos->ticks_per_beat * | |||||
pos->beats_per_minute / (pos->frame_rate * 60)); | |||||
while (pos->tick >= pos->ticks_per_beat) { | |||||
pos->tick -= pos->ticks_per_beat; | |||||
if (++pos->beat > pos->beats_per_bar) { | |||||
pos->beat = 1; | |||||
++pos->bar; | |||||
pos->bar_start_tick += (pos->beats_per_bar * | |||||
pos->ticks_per_beat); | |||||
} | |||||
} | |||||
} | |||||
} | |||||
/* experimental timecode callback | |||||
* | |||||
* Fill in extended timecode fields using the trivial assumption that | |||||
* we are running at nominal speed, hence with no drift. | |||||
* | |||||
* It would probably be faster to compute frame_time without the | |||||
* conditional expression. But, this demonstrates the invariant: | |||||
* next_time[i] == frame_time[i+1], unless a reposition occurs. | |||||
* | |||||
* Runs in the process thread. Realtime, must not wait. | |||||
*/ | |||||
void | |||||
timecode (jack_transport_state_t state, jack_nframes_t nframes, | |||||
jack_position_t *pos, int new_pos, void *arg) | |||||
{ | |||||
/* nominal transport speed */ | |||||
double seconds_per_frame = 1.0 / (double) pos->frame_rate; | |||||
pos->valid = JackPositionTimecode; | |||||
pos->frame_time = (new_pos? | |||||
pos->frame * seconds_per_frame: | |||||
pos->next_time); | |||||
pos->next_time = (pos->frame + nframes) * seconds_per_frame; | |||||
} | |||||
/* after internal client loaded */ | |||||
int | |||||
jack_initialize (jack_client_t *client, const char *load_init) | |||||
{ | |||||
JackTimebaseCallback callback = timebbt; | |||||
int rc = sscanf(load_init, " %f/%f, %lf bpm ", &time_beats_per_bar, | |||||
&time_beat_type, &time_beats_per_minute); | |||||
if (rc > 0) { | |||||
fprintf (stderr, "counting %.1f/%.1f at %.2f bpm\n", | |||||
time_beats_per_bar, time_beat_type, | |||||
time_beats_per_minute); | |||||
} else { | |||||
int len = strlen(load_init); | |||||
if ((len > 0) && (strncmp(load_init, "timecode", len) == 0)) | |||||
callback = timecode; | |||||
} | |||||
if (jack_set_timebase_callback(client, 0, callback, NULL) != 0) { | |||||
fprintf (stderr, "Unable to take over timebase.\n"); | |||||
return 1; /* terminate */ | |||||
} | |||||
fprintf (stderr, "Internal timebase master defined.\n"); | |||||
jack_activate (client); | |||||
return 0; /* success */ | |||||
} | |||||
/* before unloading */ | |||||
void | |||||
jack_finish (void *arg) | |||||
{ | |||||
fprintf (stderr, "Internal timebase client exiting.\n"); | |||||
} |
@@ -1,208 +0,0 @@ | |||||
/** @file simple_client.c | |||||
* | |||||
* @brief This simple client demonstrates the most basic features of JACK | |||||
* as they would be used by many applications. | |||||
*/ | |||||
#include <stdio.h> | |||||
#include <errno.h> | |||||
#include <unistd.h> | |||||
#include <stdlib.h> | |||||
#include <string.h> | |||||
#include <jack/jack.h> | |||||
jack_port_t *input_port; | |||||
jack_port_t *output_port; | |||||
jack_client_t *client; | |||||
jack_default_audio_sample_t *delay_line; | |||||
jack_nframes_t delay_index; | |||||
jack_nframes_t latency = 1024; | |||||
/** | |||||
* The process callback for this JACK application is called in a | |||||
* special realtime thread once for each audio cycle. | |||||
* | |||||
* This client does nothing more than copy data from its input | |||||
* port to its output port. It will exit when stopped by | |||||
* the user (e.g. using Ctrl-C on a unix-ish operating system) | |||||
*/ | |||||
int | |||||
process (jack_nframes_t nframes, void *arg) | |||||
{ | |||||
jack_default_audio_sample_t *in, *out; | |||||
int k; | |||||
in = jack_port_get_buffer (input_port, nframes); | |||||
out = jack_port_get_buffer (output_port, nframes); | |||||
for (k=0; k<nframes; k++) { | |||||
out[k] = delay_line[delay_index]; | |||||
delay_line[delay_index] = in[k]; | |||||
delay_index = (delay_index + 1) % latency; | |||||
} | |||||
return 0; | |||||
} | |||||
void | |||||
latency_cb (jack_latency_callback_mode_t mode, void *arg) | |||||
{ | |||||
jack_latency_range_t range; | |||||
if (mode == JackCaptureLatency) { | |||||
jack_port_get_latency_range (input_port, mode, &range); | |||||
range.min += latency; | |||||
range.max += latency; | |||||
jack_port_set_latency_range (output_port, mode, &range); | |||||
} else { | |||||
jack_port_get_latency_range (output_port, mode, &range); | |||||
range.min += latency; | |||||
range.max += latency; | |||||
jack_port_set_latency_range (input_port, mode, &range); | |||||
} | |||||
} | |||||
/** | |||||
* JACK calls this shutdown_callback if the server ever shuts down or | |||||
* decides to disconnect the client. | |||||
*/ | |||||
void | |||||
jack_shutdown (void *arg) | |||||
{ | |||||
exit (1); | |||||
} | |||||
int | |||||
main (int argc, char *argv[]) | |||||
{ | |||||
const char **ports; | |||||
const char *client_name = "latent"; | |||||
const char *server_name = NULL; | |||||
jack_options_t options = JackNullOption; | |||||
jack_status_t status; | |||||
if (argc == 2) | |||||
latency = atoi(argv[1]); | |||||
delay_line = malloc( latency * sizeof(jack_default_audio_sample_t)); | |||||
if (delay_line == NULL) { | |||||
fprintf (stderr, "no memory"); | |||||
exit(1); | |||||
} | |||||
memset (delay_line, 0, latency * sizeof(jack_default_audio_sample_t)); | |||||
/* open a client connection to 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", status); | |||||
if (status & JackServerFailed) { | |||||
fprintf (stderr, "Unable to connect to JACK server\n"); | |||||
} | |||||
exit (1); | |||||
} | |||||
if (status & JackServerStarted) { | |||||
fprintf (stderr, "JACK server started\n"); | |||||
} | |||||
if (status & JackNameNotUnique) { | |||||
client_name = jack_get_client_name(client); | |||||
fprintf (stderr, "unique name `%s' assigned\n", client_name); | |||||
} | |||||
/* tell the JACK server to call `process()' whenever | |||||
there is work to be done. | |||||
*/ | |||||
jack_set_process_callback (client, process, 0); | |||||
/* tell the JACK server to call `latency()' whenever | |||||
the latency needs to be recalculated. | |||||
*/ | |||||
if (jack_set_latency_callback) | |||||
jack_set_latency_callback (client, latency_cb, 0); | |||||
/* tell the JACK server to call `jack_shutdown()' if | |||||
it ever shuts down, either entirely, or if it | |||||
just decides to stop calling us. | |||||
*/ | |||||
jack_on_shutdown (client, jack_shutdown, 0); | |||||
/* display the current sample rate. | |||||
*/ | |||||
printf ("engine sample rate: %" PRIu32 "\n", | |||||
jack_get_sample_rate (client)); | |||||
/* create two ports */ | |||||
input_port = jack_port_register (client, "input", | |||||
JACK_DEFAULT_AUDIO_TYPE, | |||||
JackPortIsInput, 0); | |||||
output_port = jack_port_register (client, "output", | |||||
JACK_DEFAULT_AUDIO_TYPE, | |||||
JackPortIsOutput, 0); | |||||
if ((input_port == NULL) || (output_port == NULL)) { | |||||
fprintf(stderr, "no more JACK ports available\n"); | |||||
exit (1); | |||||
} | |||||
/* Tell the JACK server that we are ready to roll. Our | |||||
* process() callback will start running now. */ | |||||
if (jack_activate (client)) { | |||||
fprintf (stderr, "cannot activate client"); | |||||
exit (1); | |||||
} | |||||
/* Connect the ports. You can't do this before the client is | |||||
* activated, because we can't make connections to clients | |||||
* that aren't running. Note the confusing (but necessary) | |||||
* orientation of the driver backend ports: playback ports are | |||||
* "input" to the backend, and capture ports are "output" from | |||||
* it. | |||||
*/ | |||||
ports = jack_get_ports (client, NULL, NULL, | |||||
JackPortIsPhysical|JackPortIsOutput); | |||||
if (ports == NULL) { | |||||
fprintf(stderr, "no physical capture ports\n"); | |||||
exit (1); | |||||
} | |||||
if (jack_connect (client, ports[0], jack_port_name (input_port))) { | |||||
fprintf (stderr, "cannot connect input ports\n"); | |||||
} | |||||
free (ports); | |||||
ports = jack_get_ports (client, NULL, NULL, | |||||
JackPortIsPhysical|JackPortIsInput); | |||||
if (ports == NULL) { | |||||
fprintf(stderr, "no physical playback ports\n"); | |||||
exit (1); | |||||
} | |||||
if (jack_connect (client, jack_port_name (output_port), ports[0])) { | |||||
fprintf (stderr, "cannot connect output ports\n"); | |||||
} | |||||
free (ports); | |||||
/* keep running until stopped by the user */ | |||||
sleep (-1); | |||||
/* this is never reached but if the program | |||||
had some other way to exit besides being killed, | |||||
they would be important to call. | |||||
*/ | |||||
jack_client_close (client); | |||||
exit (0); | |||||
} |
@@ -1,268 +0,0 @@ | |||||
/* | |||||
Copyright (C) 2002 Anthony Van Groningen | |||||
This program 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. | |||||
This program 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 this program; if not, write to the Free Software | |||||
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. | |||||
*/ | |||||
#include <stdlib.h> | |||||
#include <stdio.h> | |||||
#include <errno.h> | |||||
#include <unistd.h> | |||||
#include <math.h> | |||||
#include <getopt.h> | |||||
#include <string.h> | |||||
#include <jack/jack.h> | |||||
#include <jack/transport.h> | |||||
typedef jack_default_audio_sample_t sample_t; | |||||
const double PI = 3.14; | |||||
jack_client_t *client; | |||||
jack_port_t *output_port; | |||||
unsigned long sr; | |||||
int freq = 880; | |||||
int bpm; | |||||
jack_nframes_t tone_length, wave_length; | |||||
sample_t *wave; | |||||
long offset = 0; | |||||
int transport_aware = 0; | |||||
jack_transport_state_t transport_state; | |||||
void | |||||
usage () | |||||
{ | |||||
fprintf (stderr, "\n" | |||||
"usage: jack_metro \n" | |||||
" [ --frequency OR -f frequency (in Hz) ]\n" | |||||
" [ --amplitude OR -A maximum amplitude (between 0 and 1) ]\n" | |||||
" [ --duration OR -D duration (in ms) ]\n" | |||||
" [ --attack OR -a attack (in percent of duration) ]\n" | |||||
" [ --decay OR -d decay (in percent of duration) ]\n" | |||||
" [ --name OR -n jack name for metronome client ]\n" | |||||
" [ --transport OR -t transport aware ]\n" | |||||
" --bpm OR -b beats per minute\n" | |||||
); | |||||
} | |||||
void | |||||
process_silence (jack_nframes_t nframes) | |||||
{ | |||||
sample_t *buffer = (sample_t *) jack_port_get_buffer (output_port, nframes); | |||||
memset (buffer, 0, sizeof (jack_default_audio_sample_t) * nframes); | |||||
} | |||||
void | |||||
process_audio (jack_nframes_t nframes) | |||||
{ | |||||
sample_t *buffer = (sample_t *) jack_port_get_buffer (output_port, nframes); | |||||
jack_nframes_t frames_left = nframes; | |||||
while (wave_length - offset < frames_left) { | |||||
memcpy (buffer + (nframes - frames_left), wave + offset, sizeof (sample_t) * (wave_length - offset)); | |||||
frames_left -= wave_length - offset; | |||||
offset = 0; | |||||
} | |||||
if (frames_left > 0) { | |||||
memcpy (buffer + (nframes - frames_left), wave + offset, sizeof (sample_t) * frames_left); | |||||
offset += frames_left; | |||||
} | |||||
} | |||||
int | |||||
process (jack_nframes_t nframes, void *arg) | |||||
{ | |||||
if (transport_aware) { | |||||
jack_position_t pos; | |||||
if (jack_transport_query (client, &pos) | |||||
!= JackTransportRolling) { | |||||
process_silence (nframes); | |||||
return 0; | |||||
} | |||||
offset = pos.frame % wave_length; | |||||
} | |||||
process_audio (nframes); | |||||
return 0; | |||||
} | |||||
int | |||||
sample_rate_change () { | |||||
printf("Sample rate has changed! Exiting...\n"); | |||||
exit(-1); | |||||
} | |||||
int | |||||
main (int argc, char *argv[]) | |||||
{ | |||||
sample_t scale; | |||||
int i, attack_length, decay_length; | |||||
double *amp; | |||||
double max_amp = 0.5; | |||||
int option_index; | |||||
int opt; | |||||
int got_bpm = 0; | |||||
int attack_percent = 1, decay_percent = 10, dur_arg = 100; | |||||
char *client_name = 0; | |||||
char *bpm_string = "bpm"; | |||||
int verbose = 0; | |||||
jack_status_t status; | |||||
const char *options = "f:A:D:a:d:b:n:thv"; | |||||
struct option long_options[] = | |||||
{ | |||||
{"frequency", 1, 0, 'f'}, | |||||
{"amplitude", 1, 0, 'A'}, | |||||
{"duration", 1, 0, 'D'}, | |||||
{"attack", 1, 0, 'a'}, | |||||
{"decay", 1, 0, 'd'}, | |||||
{"bpm", 1, 0, 'b'}, | |||||
{"name", 1, 0, 'n'}, | |||||
{"transport", 0, 0, 't'}, | |||||
{"help", 0, 0, 'h'}, | |||||
{"verbose", 0, 0, 'v'}, | |||||
{0, 0, 0, 0} | |||||
}; | |||||
while ((opt = getopt_long (argc, argv, options, long_options, &option_index)) != EOF) { | |||||
switch (opt) { | |||||
case 'f': | |||||
if ((freq = atoi (optarg)) <= 0) { | |||||
fprintf (stderr, "invalid frequency\n"); | |||||
return -1; | |||||
} | |||||
break; | |||||
case 'A': | |||||
if (((max_amp = atof (optarg)) <= 0)|| (max_amp > 1)) { | |||||
fprintf (stderr, "invalid amplitude\n"); | |||||
return -1; | |||||
} | |||||
break; | |||||
case 'D': | |||||
dur_arg = atoi (optarg); | |||||
fprintf (stderr, "durarg = %u\n", dur_arg); | |||||
break; | |||||
case 'a': | |||||
if (((attack_percent = atoi (optarg)) < 0) || (attack_percent > 100)) { | |||||
fprintf (stderr, "invalid attack percent\n"); | |||||
return -1; | |||||
} | |||||
break; | |||||
case 'd': | |||||
if (((decay_percent = atoi (optarg)) < 0) || (decay_percent > 100)) { | |||||
fprintf (stderr, "invalid decay percent\n"); | |||||
return -1; | |||||
} | |||||
break; | |||||
case 'b': | |||||
got_bpm = 1; | |||||
if ((bpm = atoi (optarg)) < 0) { | |||||
fprintf (stderr, "invalid bpm\n"); | |||||
return -1; | |||||
} | |||||
bpm_string = (char *) malloc ((strlen (optarg) + 4) * sizeof (char)); | |||||
strcpy (bpm_string, optarg); | |||||
strcat (bpm_string, "_bpm"); | |||||
break; | |||||
case 'n': | |||||
client_name = (char *) malloc (strlen (optarg) * sizeof (char)); | |||||
strcpy (client_name, optarg); | |||||
break; | |||||
case 'v': | |||||
verbose = 1; | |||||
break; | |||||
case 't': | |||||
transport_aware = 1; | |||||
break; | |||||
default: | |||||
fprintf (stderr, "unknown option %c\n", opt); | |||||
case 'h': | |||||
usage (); | |||||
return -1; | |||||
} | |||||
} | |||||
if (!got_bpm) { | |||||
fprintf (stderr, "bpm not specified\n"); | |||||
usage (); | |||||
return -1; | |||||
} | |||||
/* Initial Jack setup, get sample rate */ | |||||
if (!client_name) { | |||||
client_name = (char *) malloc (9 * sizeof (char)); | |||||
strcpy (client_name, "metro"); | |||||
} | |||||
if ((client = jack_client_open (client_name, JackNoStartServer, &status)) == 0) { | |||||
fprintf (stderr, "jack server not running?\n"); | |||||
return 1; | |||||
} | |||||
jack_set_process_callback (client, process, 0); | |||||
output_port = jack_port_register (client, bpm_string, JACK_DEFAULT_AUDIO_TYPE, JackPortIsOutput, 0); | |||||
sr = jack_get_sample_rate (client); | |||||
/* setup wave table parameters */ | |||||
wave_length = 60 * sr / bpm; | |||||
tone_length = sr * dur_arg / 1000; | |||||
attack_length = tone_length * attack_percent / 100; | |||||
decay_length = tone_length * decay_percent / 100; | |||||
scale = 2 * PI * freq / sr; | |||||
if (tone_length >= wave_length) { | |||||
fprintf (stderr, "invalid duration (tone length = %" PRIu32 | |||||
", wave length = %" PRIu32 "\n", tone_length, | |||||
wave_length); | |||||
return -1; | |||||
} | |||||
if (attack_length + decay_length > (int)tone_length) { | |||||
fprintf (stderr, "invalid attack/decay\n"); | |||||
return -1; | |||||
} | |||||
/* Build the wave table */ | |||||
wave = (sample_t *) malloc (wave_length * sizeof(sample_t)); | |||||
amp = (double *) malloc (tone_length * sizeof(double)); | |||||
for (i = 0; i < attack_length; i++) { | |||||
amp[i] = max_amp * i / ((double) attack_length); | |||||
} | |||||
for (i = attack_length; i < (int)tone_length - decay_length; i++) { | |||||
amp[i] = max_amp; | |||||
} | |||||
for (i = (int)tone_length - decay_length; i < (int)tone_length; i++) { | |||||
amp[i] = - max_amp * (i - (double) tone_length) / ((double) decay_length); | |||||
} | |||||
for (i = 0; i < (int)tone_length; i++) { | |||||
wave[i] = amp[i] * sin (scale * i); | |||||
} | |||||
for (i = tone_length; i < (int)wave_length; i++) { | |||||
wave[i] = 0; | |||||
} | |||||
if (jack_activate (client)) { | |||||
fprintf (stderr, "cannot activate client"); | |||||
return 1; | |||||
} | |||||
while (1) { | |||||
sleep(1); | |||||
}; | |||||
} |
@@ -1,118 +0,0 @@ | |||||
/* | |||||
Copyright (C) 2004 Ian Esten | |||||
This program 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. | |||||
This program 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 this program; if not, write to the Free Software | |||||
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. | |||||
*/ | |||||
#include <jack/jack.h> | |||||
#include <jack/midiport.h> | |||||
#include <stdio.h> | |||||
#include <stdlib.h> | |||||
#include <unistd.h> | |||||
jack_client_t *client; | |||||
jack_port_t *output_port; | |||||
unsigned char* note_frqs; | |||||
jack_nframes_t* note_starts; | |||||
jack_nframes_t* note_lengths; | |||||
jack_nframes_t num_notes; | |||||
jack_nframes_t loop_nsamp; | |||||
jack_nframes_t loop_index; | |||||
void usage() | |||||
{ | |||||
fprintf(stderr, "usage: jack_midiseq name nsamp [startindex note nsamp] ...... [startindex note nsamp]\n"); | |||||
fprintf(stderr, "eg: jack_midiseq Sequencer 24000 0 60 8000 12000 63 8000\n"); | |||||
fprintf(stderr, "will play a 1/2 sec loop (if srate is 48khz) with a c4 note at the start of the loop\n"); | |||||
fprintf(stderr, "that lasts for 12000 samples, then a d4# that starts at 1/4 sec that lasts for 800 samples\n"); | |||||
} | |||||
int process(jack_nframes_t nframes, void *arg) | |||||
{ | |||||
int i,j; | |||||
void* port_buf = jack_port_get_buffer(output_port, nframes); | |||||
unsigned char* buffer; | |||||
jack_midi_clear_buffer(port_buf); | |||||
/*memset(buffer, 0, nframes*sizeof(jack_default_audio_sample_t));*/ | |||||
for(i=0; i<nframes; i++) | |||||
{ | |||||
for(j=0; j<num_notes; j++) | |||||
{ | |||||
if(note_starts[j] == loop_index) | |||||
{ | |||||
buffer = jack_midi_event_reserve(port_buf, i, 3); | |||||
/* printf("wrote a note on, port buffer = 0x%x, event buffer = 0x%x\n", port_buf, buffer);*/ | |||||
buffer[2] = 64; /* velocity */ | |||||
buffer[1] = note_frqs[j]; | |||||
buffer[0] = 0x90; /* note on */ | |||||
} | |||||
else if(note_starts[j] + note_lengths[j] == loop_index) | |||||
{ | |||||
buffer = jack_midi_event_reserve(port_buf, i, 3); | |||||
/* printf("wrote a note off, port buffer = 0x%x, event buffer = 0x%x\n", port_buf, buffer);*/ | |||||
buffer[2] = 64; /* velocity */ | |||||
buffer[1] = note_frqs[j]; | |||||
buffer[0] = 0x80; /* note off */ | |||||
} | |||||
} | |||||
loop_index = loop_index+1 >= loop_nsamp ? 0 : loop_index+1; | |||||
} | |||||
return 0; | |||||
} | |||||
int main(int narg, char **args) | |||||
{ | |||||
int i; | |||||
jack_nframes_t nframes; | |||||
if((narg<6) || ((narg-3)%3 !=0)) | |||||
{ | |||||
usage(); | |||||
exit(1); | |||||
} | |||||
if((client = jack_client_open (args[1], JackNullOption, NULL)) == 0) | |||||
{ | |||||
fprintf (stderr, "jack server not running?\n"); | |||||
return 1; | |||||
} | |||||
jack_set_process_callback (client, process, 0); | |||||
output_port = jack_port_register (client, "out", JACK_DEFAULT_MIDI_TYPE, JackPortIsOutput, 0); | |||||
nframes = jack_get_buffer_size(client); | |||||
loop_index = 0; | |||||
num_notes = (narg - 3)/3; | |||||
note_frqs = malloc(num_notes*sizeof(unsigned char)); | |||||
note_starts = malloc(num_notes*sizeof(unsigned char)); | |||||
note_lengths = malloc(num_notes*sizeof(jack_nframes_t)); | |||||
loop_nsamp = atoi(args[2]); | |||||
for(i=0; i<num_notes; i++) | |||||
{ | |||||
note_starts[i] = atoi(args[3 + 3*i]); | |||||
note_frqs[i] = atoi(args[4 + 3*i]); | |||||
note_lengths[i] = atoi(args[5 + 3*i]); | |||||
} | |||||
if (jack_activate(client)) | |||||
{ | |||||
fprintf (stderr, "cannot activate client"); | |||||
return 1; | |||||
} | |||||
while (1) | |||||
{ | |||||
sleep(1); | |||||
}; | |||||
} |
@@ -1,138 +0,0 @@ | |||||
/* | |||||
Copyright (C) 2004 Ian Esten | |||||
This program 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. | |||||
This program 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 this program; if not, write to the Free Software | |||||
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. | |||||
*/ | |||||
#include <stdio.h> | |||||
#include <errno.h> | |||||
#include <unistd.h> | |||||
#include <stdlib.h> | |||||
#include <string.h> | |||||
#include <math.h> | |||||
#include <jack/jack.h> | |||||
#include <jack/midiport.h> | |||||
jack_port_t *input_port; | |||||
jack_port_t *output_port; | |||||
jack_default_audio_sample_t ramp=0.0; | |||||
jack_default_audio_sample_t note_on; | |||||
unsigned char note = 0; | |||||
jack_default_audio_sample_t note_frqs[128]; | |||||
void calc_note_frqs(jack_default_audio_sample_t srate) | |||||
{ | |||||
int i; | |||||
for(i=0; i<128; i++) | |||||
{ | |||||
note_frqs[i] = (2.0 * 440.0 / 32.0) * pow(2, (((jack_default_audio_sample_t)i - 9.0) / 12.0)) / srate; | |||||
} | |||||
} | |||||
int process(jack_nframes_t nframes, void *arg) | |||||
{ | |||||
int i; | |||||
void* port_buf = jack_port_get_buffer(input_port, nframes); | |||||
jack_default_audio_sample_t *out = (jack_default_audio_sample_t *) jack_port_get_buffer (output_port, nframes); | |||||
jack_midi_event_t in_event; | |||||
jack_nframes_t event_index = 0; | |||||
jack_nframes_t event_count = jack_midi_get_event_count(port_buf); | |||||
if(event_count > 1) | |||||
{ | |||||
printf(" midisine: have %d events\n", event_count); | |||||
for(i=0; i<event_count; i++) | |||||
{ | |||||
jack_midi_event_get(&in_event, port_buf, i); | |||||
printf(" event %d time is %d. 1st byte is 0x%x\n", i, in_event.time, *(in_event.buffer)); | |||||
} | |||||
/* printf("1st byte of 1st event addr is %p\n", in_events[0].buffer);*/ | |||||
} | |||||
jack_midi_event_get(&in_event, port_buf, 0); | |||||
for(i=0; i<nframes; i++) | |||||
{ | |||||
if((in_event.time == i) && (event_index < event_count)) | |||||
{ | |||||
if( ((*(in_event.buffer) & 0xf0)) == 0x90 ) | |||||
{ | |||||
/* note on */ | |||||
note = *(in_event.buffer + 1); | |||||
note_on = 1.0; | |||||
} | |||||
else if( ((*(in_event.buffer)) & 0xf0) == 0x80 ) | |||||
{ | |||||
/* note off */ | |||||
note = *(in_event.buffer + 1); | |||||
note_on = 0.0; | |||||
} | |||||
event_index++; | |||||
if(event_index < event_count) | |||||
jack_midi_event_get(&in_event, port_buf, event_index); | |||||
} | |||||
ramp += note_frqs[note]; | |||||
ramp = (ramp > 1.0) ? ramp - 2.0 : ramp; | |||||
out[i] = note_on*sin(2*M_PI*ramp); | |||||
} | |||||
return 0; | |||||
} | |||||
int srate(jack_nframes_t nframes, void *arg) | |||||
{ | |||||
printf("the sample rate is now %" PRIu32 "/sec\n", nframes); | |||||
calc_note_frqs((jack_default_audio_sample_t)nframes); | |||||
return 0; | |||||
} | |||||
void jack_shutdown(void *arg) | |||||
{ | |||||
exit(1); | |||||
} | |||||
int main(int narg, char **args) | |||||
{ | |||||
jack_client_t *client; | |||||
if ((client = jack_client_open ("midisine", JackNullOption, NULL)) == 0) | |||||
{ | |||||
fprintf(stderr, "jack server not running?\n"); | |||||
return 1; | |||||
} | |||||
calc_note_frqs(jack_get_sample_rate (client)); | |||||
jack_set_process_callback (client, process, 0); | |||||
jack_set_sample_rate_callback (client, srate, 0); | |||||
jack_on_shutdown (client, jack_shutdown, 0); | |||||
input_port = jack_port_register (client, "midi_in", JACK_DEFAULT_MIDI_TYPE, JackPortIsInput, 0); | |||||
output_port = jack_port_register (client, "audio_out", JACK_DEFAULT_AUDIO_TYPE, JackPortIsOutput, 0); | |||||
if (jack_activate (client)) | |||||
{ | |||||
fprintf(stderr, "cannot activate client"); | |||||
return 1; | |||||
} | |||||
/* run until interrupted */ | |||||
while(1) | |||||
{ | |||||
sleep(1); | |||||
} | |||||
jack_client_close(client); | |||||
exit (0); | |||||
} | |||||
@@ -1,237 +0,0 @@ | |||||
/* | |||||
Copyright (C) 2008 Grame | |||||
This program 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. | |||||
This program 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 this program; if not, write to the Free Software | |||||
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. | |||||
*/ | |||||
#include <stdio.h> | |||||
#include <errno.h> | |||||
#include <unistd.h> | |||||
#include <stdlib.h> | |||||
#include <string.h> | |||||
#include <getopt.h> | |||||
#include <jack/jack.h> | |||||
#include <jack/control.h> | |||||
static jackctl_driver_t * jackctl_server_get_driver(jackctl_server_t *server, const char *driver_name) | |||||
{ | |||||
const JSList * node_ptr = jackctl_server_get_drivers_list(server); | |||||
while (node_ptr) { | |||||
if (strcmp(jackctl_driver_get_name((jackctl_driver_t *)node_ptr->data), driver_name) == 0) { | |||||
return (jackctl_driver_t *)node_ptr->data; | |||||
} | |||||
node_ptr = jack_slist_next(node_ptr); | |||||
} | |||||
return NULL; | |||||
} | |||||
static jackctl_internal_t * jackctl_server_get_internal(jackctl_server_t *server, const char *internal_name) | |||||
{ | |||||
const JSList * node_ptr = jackctl_server_get_internals_list(server); | |||||
while (node_ptr) { | |||||
if (strcmp(jackctl_internal_get_name((jackctl_internal_t *)node_ptr->data), internal_name) == 0) { | |||||
return (jackctl_internal_t *)node_ptr->data; | |||||
} | |||||
node_ptr = jack_slist_next(node_ptr); | |||||
} | |||||
return NULL; | |||||
} | |||||
static jackctl_parameter_t * | |||||
jackctl_get_parameter( | |||||
const JSList * parameters_list, | |||||
const char * parameter_name) | |||||
{ | |||||
while (parameters_list) | |||||
{ | |||||
if (strcmp(jackctl_parameter_get_name((jackctl_parameter_t *)parameters_list->data), parameter_name) == 0) | |||||
{ | |||||
return (jackctl_parameter_t *)parameters_list->data; | |||||
} | |||||
parameters_list = jack_slist_next(parameters_list); | |||||
} | |||||
return NULL; | |||||
} | |||||
static void print_value(union jackctl_parameter_value value, jackctl_param_type_t type) | |||||
{ | |||||
switch (type) { | |||||
case JackParamInt: | |||||
printf("parameter value = %d\n", value.i); | |||||
break; | |||||
case JackParamUInt: | |||||
printf("parameter value = %u\n", value.ui); | |||||
break; | |||||
case JackParamChar: | |||||
printf("parameter value = %c\n", value.c); | |||||
break; | |||||
case JackParamString: | |||||
printf("parameter value = %s\n", value.str); | |||||
break; | |||||
case JackParamBool: | |||||
printf("parameter value = %d\n", value.b); | |||||
break; | |||||
} | |||||
} | |||||
static void print_parameters(const JSList * node_ptr) | |||||
{ | |||||
while (node_ptr != NULL) { | |||||
jackctl_parameter_t * parameter = (jackctl_parameter_t *)node_ptr->data; | |||||
printf("\nparameter name = %s\n", jackctl_parameter_get_name(parameter)); | |||||
printf("parameter id = %c\n", jackctl_parameter_get_id(parameter)); | |||||
printf("parameter short decs = %s\n", jackctl_parameter_get_short_description(parameter)); | |||||
printf("parameter long decs = %s\n", jackctl_parameter_get_long_description(parameter)); | |||||
print_value(jackctl_parameter_get_default_value(parameter), jackctl_parameter_get_type(parameter)); | |||||
node_ptr = jack_slist_next(node_ptr); | |||||
} | |||||
} | |||||
static void print_driver(jackctl_driver_t * driver) | |||||
{ | |||||
printf("\n--------------------------\n"); | |||||
printf("driver = %s\n", jackctl_driver_get_name(driver)); | |||||
printf("-------------------------- \n"); | |||||
print_parameters(jackctl_driver_get_parameters(driver)); | |||||
} | |||||
static void print_internal(jackctl_internal_t * internal) | |||||
{ | |||||
printf("\n-------------------------- \n"); | |||||
printf("internal = %s\n", jackctl_internal_get_name(internal)); | |||||
printf("-------------------------- \n"); | |||||
print_parameters(jackctl_internal_get_parameters(internal)); | |||||
} | |||||
static void usage() | |||||
{ | |||||
fprintf (stderr, "\n" | |||||
"usage: jack_server_control \n" | |||||
" [ --driver OR -d driver_name ]\n" | |||||
" [ --client OR -c client_name ]\n" | |||||
); | |||||
} | |||||
int main(int argc, char *argv[]) | |||||
{ | |||||
jackctl_server_t * server; | |||||
const JSList * parameters; | |||||
const JSList * drivers; | |||||
const JSList * internals; | |||||
const JSList * node_ptr; | |||||
sigset_t signals; | |||||
int opt, option_index; | |||||
const char* driver_name = "dummy"; | |||||
const char* client_name = "audioadapter"; | |||||
const char *options = "d:c:"; | |||||
struct option long_options[] = { | |||||
{"driver", 1, 0, 'd'}, | |||||
{"client", 1, 0, 'c'}, | |||||
}; | |||||
while ((opt = getopt_long (argc, argv, options, long_options, &option_index)) != EOF) { | |||||
switch (opt) { | |||||
case 'd': | |||||
driver_name = optarg; | |||||
break; | |||||
case 'c': | |||||
client_name = optarg; | |||||
break; | |||||
default: | |||||
usage(); | |||||
exit(0); | |||||
} | |||||
} | |||||
server = jackctl_server_create(NULL, NULL); | |||||
parameters = jackctl_server_get_parameters(server); | |||||
/* | |||||
jackctl_parameter_t* param; | |||||
union jackctl_parameter_value value; | |||||
param = jackctl_get_parameter(parameters, "verbose"); | |||||
if (param != NULL) { | |||||
value.b = true; | |||||
jackctl_parameter_set_value(param, &value); | |||||
} | |||||
*/ | |||||
printf("\n========================== \n"); | |||||
printf("List of server parameters \n"); | |||||
printf("========================== \n"); | |||||
print_parameters(parameters); | |||||
printf("\n========================== \n"); | |||||
printf("List of drivers \n"); | |||||
printf("========================== \n"); | |||||
drivers = jackctl_server_get_drivers_list(server); | |||||
node_ptr = drivers; | |||||
while (node_ptr != NULL) { | |||||
print_driver((jackctl_driver_t *)node_ptr->data); | |||||
node_ptr = jack_slist_next(node_ptr); | |||||
} | |||||
printf("\n========================== \n"); | |||||
printf("List of internal clients \n"); | |||||
printf("========================== \n"); | |||||
internals = jackctl_server_get_internals_list(server); | |||||
node_ptr = internals; | |||||
while (node_ptr != NULL) { | |||||
print_internal((jackctl_internal_t *)node_ptr->data); | |||||
node_ptr = jack_slist_next(node_ptr); | |||||
} | |||||
signals = jackctl_setup_signals(0); | |||||
jackctl_server_start(server, jackctl_server_get_driver(server, driver_name)); | |||||
jackctl_server_load_internal(server, jackctl_server_get_internal(server, client_name)); | |||||
/* | |||||
// Switch master test | |||||
jackctl_driver_t* master; | |||||
usleep(5000000); | |||||
printf("jackctl_server_load_master\n"); | |||||
master = jackctl_server_get_driver(server, "coreaudio"); | |||||
jackctl_server_switch_master(server, master); | |||||
usleep(5000000); | |||||
printf("jackctl_server_load_master\n"); | |||||
master = jackctl_server_get_driver(server, "dummy"); | |||||
jackctl_server_switch_master(server, master); | |||||
*/ | |||||
jackctl_wait_signals(signals); | |||||
jackctl_server_destroy(server); | |||||
return 0; | |||||
} |
@@ -1,117 +0,0 @@ | |||||
#include <stdio.h> | |||||
#include <errno.h> | |||||
#include <unistd.h> | |||||
#include <signal.h> | |||||
#include <stdlib.h> | |||||
#include <jack/jack.h> | |||||
#include <jack/transport.h> | |||||
jack_client_t *client; | |||||
void | |||||
showtime () | |||||
{ | |||||
jack_position_t current; | |||||
jack_transport_state_t transport_state; | |||||
jack_nframes_t frame_time; | |||||
transport_state = jack_transport_query (client, ¤t); | |||||
frame_time = jack_frame_time (client); | |||||
printf ("frame: %7" PRIu32 " @ %" PRIu32 "\t", current.frame, frame_time); | |||||
switch (transport_state) { | |||||
case JackTransportStopped: | |||||
printf ("state: Stopped"); | |||||
break; | |||||
case JackTransportRolling: | |||||
printf ("state: Rolling"); | |||||
break; | |||||
case JackTransportStarting: | |||||
printf ("state: Starting"); | |||||
break; | |||||
default: | |||||
printf ("state: [unknown]"); | |||||
} | |||||
if (current.valid & JackPositionBBT) | |||||
printf ("\tBBT: %3" PRIi32 "|%" PRIi32 "|%04" | |||||
PRIi32, current.bar, current.beat, current.tick); | |||||
if (current.valid & JackPositionTimecode) | |||||
printf ("\tTC: (%.6f, %.6f)", | |||||
current.frame_time, current.next_time); | |||||
if (current.valid & JackBBTFrameOffset) | |||||
printf ("\tBBT offset: (%" PRIi32 ")", | |||||
current.bbt_offset); | |||||
if (current.valid & JackAudioVideoRatio) | |||||
printf ("\taudio/video: (%f)", | |||||
current.audio_frames_per_video_frame); | |||||
if (current.valid & JackVideoFrameOffset) { | |||||
if (current.video_offset) { | |||||
printf ("\t video@: (%" PRIi32 ")", current.video_offset); | |||||
} else { | |||||
printf ("\t no video"); | |||||
} | |||||
} | |||||
printf ("\n"); | |||||
} | |||||
void | |||||
jack_shutdown (void *arg) | |||||
{ | |||||
exit (1); | |||||
} | |||||
void | |||||
signal_handler (int sig) | |||||
{ | |||||
jack_client_close (client); | |||||
fprintf (stderr, "signal received, exiting ...\n"); | |||||
exit (0); | |||||
} | |||||
int | |||||
main (int argc, char *argv[]) | |||||
{ | |||||
/* try to become a client of the JACK server */ | |||||
if ((client = jack_client_open ("showtime", JackNullOption, NULL)) == 0) { | |||||
fprintf (stderr, "jack server not running?\n"); | |||||
return 1; | |||||
} | |||||
signal (SIGQUIT, signal_handler); | |||||
signal (SIGTERM, signal_handler); | |||||
signal (SIGHUP, signal_handler); | |||||
signal (SIGINT, signal_handler); | |||||
/* tell the JACK server to call `jack_shutdown()' if | |||||
it ever shuts down, either entirely, or if it | |||||
just decides to stop calling us. | |||||
*/ | |||||
jack_on_shutdown (client, jack_shutdown, 0); | |||||
/* tell the JACK server that we are ready to roll */ | |||||
if (jack_activate (client)) { | |||||
fprintf (stderr, "cannot activate client"); | |||||
return 1; | |||||
} | |||||
while (1) { | |||||
usleep (20); | |||||
showtime (); | |||||
} | |||||
jack_client_close (client); | |||||
exit (0); | |||||
} |
@@ -1,164 +0,0 @@ | |||||
/** @file simple_client.c | |||||
* | |||||
* @brief This simple client demonstrates the most basic features of JACK | |||||
* as they would be used by many applications. | |||||
*/ | |||||
#include <stdio.h> | |||||
#include <errno.h> | |||||
#include <unistd.h> | |||||
#include <stdlib.h> | |||||
#include <string.h> | |||||
#include <jack/jack.h> | |||||
jack_port_t *input_port; | |||||
jack_port_t *output_port; | |||||
jack_client_t *client; | |||||
/** | |||||
* The process callback for this JACK application is called in a | |||||
* special realtime thread once for each audio cycle. | |||||
* | |||||
* This client does nothing more than copy data from its input | |||||
* port to its output port. It will exit when stopped by | |||||
* the user (e.g. using Ctrl-C on a unix-ish operating system) | |||||
*/ | |||||
int | |||||
process (jack_nframes_t nframes, void *arg) | |||||
{ | |||||
jack_default_audio_sample_t *in, *out; | |||||
in = jack_port_get_buffer (input_port, nframes); | |||||
out = jack_port_get_buffer (output_port, nframes); | |||||
memcpy (out, in, | |||||
sizeof (jack_default_audio_sample_t) * nframes); | |||||
return 0; | |||||
} | |||||
/** | |||||
* JACK calls this shutdown_callback if the server ever shuts down or | |||||
* decides to disconnect the client. | |||||
*/ | |||||
void | |||||
jack_shutdown (void *arg) | |||||
{ | |||||
exit (1); | |||||
} | |||||
int | |||||
main (int argc, char *argv[]) | |||||
{ | |||||
const char **ports; | |||||
const char *client_name = "simple"; | |||||
const char *server_name = NULL; | |||||
jack_options_t options = JackNullOption; | |||||
jack_status_t status; | |||||
/* open a client connection to 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", status); | |||||
if (status & JackServerFailed) { | |||||
fprintf (stderr, "Unable to connect to JACK server\n"); | |||||
} | |||||
exit (1); | |||||
} | |||||
if (status & JackServerStarted) { | |||||
fprintf (stderr, "JACK server started\n"); | |||||
} | |||||
if (status & JackNameNotUnique) { | |||||
client_name = jack_get_client_name(client); | |||||
fprintf (stderr, "unique name `%s' assigned\n", client_name); | |||||
} | |||||
/* tell the JACK server to call `process()' whenever | |||||
there is work to be done. | |||||
*/ | |||||
jack_set_process_callback (client, process, 0); | |||||
/* tell the JACK server to call `jack_shutdown()' if | |||||
it ever shuts down, either entirely, or if it | |||||
just decides to stop calling us. | |||||
*/ | |||||
jack_on_shutdown (client, jack_shutdown, 0); | |||||
/* display the current sample rate. | |||||
*/ | |||||
printf ("engine sample rate: %" PRIu32 "\n", | |||||
jack_get_sample_rate (client)); | |||||
/* create two ports */ | |||||
input_port = jack_port_register (client, "input", | |||||
JACK_DEFAULT_AUDIO_TYPE, | |||||
JackPortIsInput, 0); | |||||
output_port = jack_port_register (client, "output", | |||||
JACK_DEFAULT_AUDIO_TYPE, | |||||
JackPortIsOutput, 0); | |||||
if ((input_port == NULL) || (output_port == NULL)) { | |||||
fprintf(stderr, "no more JACK ports available\n"); | |||||
exit (1); | |||||
} | |||||
/* Tell the JACK server that we are ready to roll. Our | |||||
* process() callback will start running now. */ | |||||
if (jack_activate (client)) { | |||||
fprintf (stderr, "cannot activate client"); | |||||
exit (1); | |||||
} | |||||
/* Connect the ports. You can't do this before the client is | |||||
* activated, because we can't make connections to clients | |||||
* that aren't running. Note the confusing (but necessary) | |||||
* orientation of the driver backend ports: playback ports are | |||||
* "input" to the backend, and capture ports are "output" from | |||||
* it. | |||||
*/ | |||||
ports = jack_get_ports (client, NULL, NULL, | |||||
JackPortIsPhysical|JackPortIsOutput); | |||||
if (ports == NULL) { | |||||
fprintf(stderr, "no physical capture ports\n"); | |||||
exit (1); | |||||
} | |||||
if (jack_connect (client, ports[0], jack_port_name (input_port))) { | |||||
fprintf (stderr, "cannot connect input ports\n"); | |||||
} | |||||
free (ports); | |||||
ports = jack_get_ports (client, NULL, NULL, | |||||
JackPortIsPhysical|JackPortIsInput); | |||||
if (ports == NULL) { | |||||
fprintf(stderr, "no physical playback ports\n"); | |||||
exit (1); | |||||
} | |||||
if (jack_connect (client, jack_port_name (output_port), ports[0])) { | |||||
fprintf (stderr, "cannot connect output ports\n"); | |||||
} | |||||
free (ports); | |||||
/* keep running until stopped by the user */ | |||||
sleep (-1); | |||||
/* this is never reached but if the program | |||||
had some other way to exit besides being killed, | |||||
they would be important to call. | |||||
*/ | |||||
jack_client_close (client); | |||||
exit (0); | |||||
} |
@@ -1,201 +0,0 @@ | |||||
/** @file simple_session_client.c | |||||
* | |||||
* @brief This simple client demonstrates the most basic features of JACK | |||||
* as they would be used by many applications. | |||||
* this version also adds session manager functionality. | |||||
*/ | |||||
#include <stdio.h> | |||||
#include <errno.h> | |||||
#include <unistd.h> | |||||
#include <stdlib.h> | |||||
#include <string.h> | |||||
#include <jack/jack.h> | |||||
#include <jack/session.h> | |||||
jack_port_t *input_port; | |||||
jack_port_t *output_port; | |||||
jack_client_t *client; | |||||
int simple_quit = 0; | |||||
/** | |||||
* The process callback for this JACK application is called in a | |||||
* special realtime thread once for each audio cycle. | |||||
* | |||||
* This client does nothing more than copy data from its input | |||||
* port to its output port. It will exit when stopped by | |||||
* the user (e.g. using Ctrl-C on a unix-ish operating system) | |||||
*/ | |||||
int | |||||
process (jack_nframes_t nframes, void *arg) | |||||
{ | |||||
jack_default_audio_sample_t *in, *out; | |||||
in = jack_port_get_buffer (input_port, nframes); | |||||
out = jack_port_get_buffer (output_port, nframes); | |||||
memcpy (out, in, | |||||
sizeof (jack_default_audio_sample_t) * nframes); | |||||
return 0; | |||||
} | |||||
void | |||||
session_callback (jack_session_event_t *event, void *arg) | |||||
{ | |||||
char retval[100]; | |||||
printf ("session notification\n"); | |||||
printf ("path %s, uuid %s, type: %s\n", event->session_dir, event->client_uuid, event->type == JackSessionSave ? "save" : "quit"); | |||||
snprintf (retval, 100, "jack_simple_session_client %s", event->client_uuid); | |||||
event->command_line = strdup (retval); | |||||
jack_session_reply( client, event ); | |||||
if (event->type == JackSessionSaveAndQuit) { | |||||
simple_quit = 1; | |||||
} | |||||
jack_session_event_free (event); | |||||
} | |||||
/** | |||||
* JACK calls this shutdown_callback if the server ever shuts down or | |||||
* decides to disconnect the client. | |||||
*/ | |||||
void | |||||
jack_shutdown (void *arg) | |||||
{ | |||||
exit (1); | |||||
} | |||||
int | |||||
main (int argc, char *argv[]) | |||||
{ | |||||
const char **ports; | |||||
const char *client_name = "simple"; | |||||
jack_status_t status; | |||||
/* open a client connection to the JACK server */ | |||||
if( argc == 1 ) | |||||
client = jack_client_open (client_name, JackNullOption, &status ); | |||||
else if( argc == 2 ) | |||||
client = jack_client_open (client_name, JackSessionID, &status, argv[1] ); | |||||
if (client == NULL) { | |||||
fprintf (stderr, "jack_client_open() failed, " | |||||
"status = 0x%2.0x\n", status); | |||||
if (status & JackServerFailed) { | |||||
fprintf (stderr, "Unable to connect to JACK server\n"); | |||||
} | |||||
exit (1); | |||||
} | |||||
if (status & JackServerStarted) { | |||||
fprintf (stderr, "JACK server started\n"); | |||||
} | |||||
if (status & JackNameNotUnique) { | |||||
client_name = jack_get_client_name(client); | |||||
fprintf (stderr, "unique name `%s' assigned\n", client_name); | |||||
} | |||||
/* tell the JACK server to call `process()' whenever | |||||
there is work to be done. | |||||
*/ | |||||
jack_set_process_callback (client, process, 0); | |||||
/* tell the JACK server to call `jack_shutdown()' if | |||||
it ever shuts down, either entirely, or if it | |||||
just decides to stop calling us. | |||||
*/ | |||||
jack_on_shutdown (client, jack_shutdown, 0); | |||||
/* tell the JACK server to call `session_callback()' if | |||||
the session is saved. | |||||
*/ | |||||
jack_set_session_callback (client, session_callback, NULL); | |||||
/* display the current sample rate. | |||||
*/ | |||||
printf ("engine sample rate: %" PRIu32 "\n", | |||||
jack_get_sample_rate (client)); | |||||
/* create two ports */ | |||||
input_port = jack_port_register (client, "input", | |||||
JACK_DEFAULT_AUDIO_TYPE, | |||||
JackPortIsInput, 0); | |||||
output_port = jack_port_register (client, "output", | |||||
JACK_DEFAULT_AUDIO_TYPE, | |||||
JackPortIsOutput, 0); | |||||
if ((input_port == NULL) || (output_port == NULL)) { | |||||
fprintf(stderr, "no more JACK ports available\n"); | |||||
exit (1); | |||||
} | |||||
/* Tell the JACK server that we are ready to roll. Our | |||||
* process() callback will start running now. */ | |||||
if (jack_activate (client)) { | |||||
fprintf (stderr, "cannot activate client"); | |||||
exit (1); | |||||
} | |||||
/* Connect the ports. You can't do this before the client is | |||||
* activated, because we can't make connections to clients | |||||
* that aren't running. Note the confusing (but necessary) | |||||
* orientation of the driver backend ports: playback ports are | |||||
* "input" to the backend, and capture ports are "output" from | |||||
* it. | |||||
*/ | |||||
/* only do the autoconnect when not reloading from a session. | |||||
* in case of a session reload, the SM will restore our connections | |||||
*/ | |||||
if (argc==1) { | |||||
ports = jack_get_ports (client, NULL, NULL, | |||||
JackPortIsPhysical|JackPortIsOutput); | |||||
if (ports == NULL) { | |||||
fprintf(stderr, "no physical capture ports\n"); | |||||
exit (1); | |||||
} | |||||
if (jack_connect (client, ports[0], jack_port_name (input_port))) { | |||||
fprintf (stderr, "cannot connect input ports\n"); | |||||
} | |||||
free (ports); | |||||
ports = jack_get_ports (client, NULL, NULL, | |||||
JackPortIsPhysical|JackPortIsInput); | |||||
if (ports == NULL) { | |||||
fprintf(stderr, "no physical playback ports\n"); | |||||
exit (1); | |||||
} | |||||
if (jack_connect (client, jack_port_name (output_port), ports[0])) { | |||||
fprintf (stderr, "cannot connect output ports\n"); | |||||
} | |||||
free (ports); | |||||
} | |||||
/* keep running until until we get a quit event */ | |||||
while (!simple_quit) | |||||
sleep(1); | |||||
jack_client_close (client); | |||||
exit (0); | |||||
} |
@@ -1,197 +0,0 @@ | |||||
/** @file transport_client.c | |||||
* | |||||
* @brief This client demonstrates very simple use of the JACK | |||||
* transport API. Compare it with the simple_client example, | |||||
* which is even simpler. It also demonstrates taking a client | |||||
* name and optionally server name from the command line, rather | |||||
* than hard-coding either of these names. | |||||
*/ | |||||
#include <stdio.h> | |||||
#include <errno.h> | |||||
#include <unistd.h> | |||||
#include <stdlib.h> | |||||
#include <string.h> | |||||
#include <jack/jack.h> | |||||
jack_port_t *input_port; | |||||
jack_port_t *output_port; | |||||
jack_client_t *client; | |||||
/* a simple state machine for this client */ | |||||
volatile enum { | |||||
Init, | |||||
Run, | |||||
Exit | |||||
} client_state = Init; | |||||
/** | |||||
* The process callback for this JACK application is called in a | |||||
* special realtime thread once for each audio cycle. | |||||
* | |||||
* This client follows a simple rule: when the JACK transport is | |||||
* running, copy the input port to the output. When it stops, exit. | |||||
*/ | |||||
int | |||||
process (jack_nframes_t nframes, void *arg) | |||||
{ | |||||
jack_default_audio_sample_t *in, *out; | |||||
jack_transport_state_t ts = jack_transport_query(client, NULL); | |||||
if (ts == JackTransportRolling) { | |||||
if (client_state == Init) | |||||
client_state = Run; | |||||
in = jack_port_get_buffer (input_port, nframes); | |||||
out = jack_port_get_buffer (output_port, nframes); | |||||
memcpy (out, in, | |||||
sizeof (jack_default_audio_sample_t) * nframes); | |||||
} else if (ts == JackTransportStopped) { | |||||
if (client_state == Run) | |||||
client_state = Exit; | |||||
} | |||||
return 0; | |||||
} | |||||
/** | |||||
* JACK calls this shutdown_callback if the server ever shuts down or | |||||
* decides to disconnect the client. | |||||
*/ | |||||
void | |||||
jack_shutdown (void *arg) | |||||
{ | |||||
exit (1); | |||||
} | |||||
int | |||||
main (int argc, char *argv[]) | |||||
{ | |||||
const char **ports; | |||||
const char *client_name; | |||||
const char *server_name = NULL; | |||||
jack_options_t options = JackNullOption; | |||||
jack_status_t status; | |||||
if (argc >= 2) { /* client name specified? */ | |||||
client_name = argv[1]; | |||||
if (argc >= 3) { /* server name specified? */ | |||||
server_name = argv[2]; | |||||
options |= JackServerName; | |||||
} | |||||
} else { /* use basename of argv[0] */ | |||||
client_name = strrchr(argv[0], '/'); | |||||
if (client_name == 0) { | |||||
client_name = argv[0]; | |||||
} else { | |||||
client_name++; | |||||
} | |||||
} | |||||
/* open a client connection to 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", status); | |||||
if (status & JackServerFailed) { | |||||
fprintf (stderr, "Unable to connect to JACK server\n"); | |||||
} | |||||
exit (1); | |||||
} | |||||
if (status & JackServerStarted) { | |||||
fprintf (stderr, "JACK server started\n"); | |||||
} | |||||
if (status & JackNameNotUnique) { | |||||
client_name = jack_get_client_name(client); | |||||
fprintf (stderr, "unique name `%s' assigned\n", client_name); | |||||
} | |||||
/* tell the JACK server to call `process()' whenever | |||||
there is work to be done. | |||||
*/ | |||||
jack_set_process_callback (client, process, 0); | |||||
/* tell the JACK server to call `jack_shutdown()' if | |||||
it ever shuts down, either entirely, or if it | |||||
just decides to stop calling us. | |||||
*/ | |||||
jack_on_shutdown (client, jack_shutdown, 0); | |||||
/* display the current sample rate. | |||||
*/ | |||||
printf ("engine sample rate: %" PRIu32 "\n", | |||||
jack_get_sample_rate (client)); | |||||
/* create two ports */ | |||||
input_port = jack_port_register (client, "input", | |||||
JACK_DEFAULT_AUDIO_TYPE, | |||||
JackPortIsInput, 0); | |||||
output_port = jack_port_register (client, "output", | |||||
JACK_DEFAULT_AUDIO_TYPE, | |||||
JackPortIsOutput, 0); | |||||
if ((input_port == NULL) || (output_port == NULL)) { | |||||
fprintf(stderr, "no more JACK ports available\n"); | |||||
exit (1); | |||||
} | |||||
/* Tell the JACK server that we are ready to roll. Our | |||||
* process() callback will start running now. */ | |||||
if (jack_activate (client)) { | |||||
fprintf (stderr, "cannot activate client"); | |||||
exit (1); | |||||
} | |||||
/* Connect the ports. You can't do this before the client is | |||||
* activated, because we can't make connections to clients | |||||
* that aren't running. Note the confusing (but necessary) | |||||
* orientation of the driver backend ports: playback ports are | |||||
* "input" to the backend, and capture ports are "output" from | |||||
* it. | |||||
*/ | |||||
ports = jack_get_ports (client, NULL, NULL, | |||||
JackPortIsPhysical|JackPortIsOutput); | |||||
if (ports == NULL) { | |||||
fprintf(stderr, "no physical capture ports\n"); | |||||
exit (1); | |||||
} | |||||
if (jack_connect (client, ports[0], jack_port_name (input_port))) { | |||||
fprintf (stderr, "cannot connect input ports\n"); | |||||
} | |||||
free (ports); | |||||
ports = jack_get_ports (client, NULL, NULL, | |||||
JackPortIsPhysical|JackPortIsInput); | |||||
if (ports == NULL) { | |||||
fprintf(stderr, "no physical playback ports\n"); | |||||
exit (1); | |||||
} | |||||
if (jack_connect (client, jack_port_name (output_port), ports[0])) { | |||||
fprintf (stderr, "cannot connect output ports\n"); | |||||
} | |||||
free (ports); | |||||
/* keep running until the transport stops */ | |||||
while (client_state != Exit) { | |||||
sleep (1); | |||||
} | |||||
jack_client_close (client); | |||||
exit (0); | |||||
} |
@@ -0,0 +1 @@ | |||||
Subproject commit 2476dca8c1ff620d043c9ad603d7ebddc51c1807 |
@@ -1,3 +0,0 @@ | |||||
Makefile | |||||
Makefile.in | |||||
version.h |
@@ -1,42 +0,0 @@ | |||||
MAINTAINERCLEANFILES = Makefile.in version.h | |||||
libjackincludedir = $(includedir)/jack | |||||
libjackinclude_HEADERS = \ | |||||
intclient.h \ | |||||
jack.h \ | |||||
ringbuffer.h \ | |||||
statistics.h \ | |||||
session.h \ | |||||
thread.h \ | |||||
timestamps.h \ | |||||
transport.h \ | |||||
types.h \ | |||||
midiport.h \ | |||||
weakmacros.h \ | |||||
weakjack.h \ | |||||
control.h \ | |||||
jslist.h | |||||
noinst_HEADERS = \ | |||||
atomicity.h \ | |||||
bitset.h \ | |||||
driver.h \ | |||||
driver_interface.h \ | |||||
driver_parse.h \ | |||||
engine.h \ | |||||
hardware.h \ | |||||
internal.h \ | |||||
intsimd.h \ | |||||
memops.h \ | |||||
messagebuffer.h \ | |||||
pool.h \ | |||||
port.h \ | |||||
ringbuffer.h \ | |||||
sanitycheck.h \ | |||||
shm.h \ | |||||
start.h \ | |||||
systemtest.h \ | |||||
unlock.h \ | |||||
varargs.h \ | |||||
version.h |
@@ -1,38 +0,0 @@ | |||||
/* | |||||
Copyright (C) 2004 Jack O'Quin | |||||
This program 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. | |||||
This program 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 this program; if not, write to the Free Software | |||||
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. | |||||
*/ | |||||
#ifndef __jack_atomicity_h__ | |||||
#define __jack_atomicity_h__ | |||||
/* | |||||
* Interface with various machine-dependent headers derived from the | |||||
* gcc/libstdc++.v3 sources. We try to modify the GCC sources as | |||||
* little as possible. The following include is resolved using the | |||||
* config/configure.hosts mechanism. It will use an OS-dependent | |||||
* version if available, otherwise the one for this CPU. Some of | |||||
* these files might not work with older GCC compilers. | |||||
*/ | |||||
#include <sysdeps/atomicity.h> | |||||
/* These functions are defined for each platform. The C++ library | |||||
* function names start with "__" to avoid namespace pollution. */ | |||||
#define exchange_and_add __exchange_and_add | |||||
#define atomic_add __atomic_add | |||||
#endif /* __jack_atomicity_h__ */ |
@@ -1,111 +0,0 @@ | |||||
/* | |||||
* bitset.h -- some simple bit vector set operations. | |||||
* | |||||
* This is useful for sets of small non-negative integers. There are | |||||
* some obvious set operations that are not implemented because I | |||||
* don't need them right now. | |||||
* | |||||
* These functions represent sets as arrays of unsigned 32-bit | |||||
* integers allocated on the heap. The first entry contains the set | |||||
* cardinality (number of elements allowed), followed by one or more | |||||
* words containing bit vectors. | |||||
* | |||||
*/ | |||||
/* | |||||
* Copyright (C) 2005 Jack O'Quin | |||||
* | |||||
* This program 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. | |||||
* | |||||
* This program 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 this program; if not, write to the Free Software | |||||
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. | |||||
*/ | |||||
#ifndef __bitset_h__ | |||||
#define __bitset_h__ | |||||
#include <inttypes.h> /* POSIX standard fixed-size types */ | |||||
#include <assert.h> /* `#define NDEBUG' to disable */ | |||||
/* On some 64-bit machines, this implementation may be slightly | |||||
* inefficient, depending on how compilers allocate space for | |||||
* uint32_t. For the set sizes I currently need, this is acceptable. | |||||
* It should not be hard to pack the bits better, if that becomes | |||||
* worthwhile. | |||||
*/ | |||||
typedef uint32_t _bitset_word_t; | |||||
typedef _bitset_word_t *bitset_t; | |||||
#define WORD_SIZE(cardinality) (1+((cardinality)+31)/32) | |||||
#define BYTE_SIZE(cardinality) (WORD_SIZE(cardinality)*sizeof(_bitset_word_t)) | |||||
#define WORD_INDEX(element) (1+(element)/32) | |||||
#define BIT_INDEX(element) ((element)&037) | |||||
static inline void | |||||
bitset_add(bitset_t set, unsigned int element) | |||||
{ | |||||
assert(element < set[0]); | |||||
set[WORD_INDEX(element)] |= (1 << BIT_INDEX(element)); | |||||
} | |||||
static inline void | |||||
bitset_copy(bitset_t to_set, bitset_t from_set) | |||||
{ | |||||
assert(to_set[0] == from_set[0]); | |||||
memcpy(to_set, from_set, BYTE_SIZE(to_set[0])); | |||||
} | |||||
static inline void | |||||
bitset_create(bitset_t *set, unsigned int cardinality) | |||||
{ | |||||
*set = (bitset_t) calloc(WORD_SIZE(cardinality), | |||||
sizeof(_bitset_word_t)); | |||||
assert(*set); | |||||
*set[0] = cardinality; | |||||
} | |||||
static inline void | |||||
bitset_destroy(bitset_t *set) | |||||
{ | |||||
if (*set) { | |||||
free(*set); | |||||
*set = (bitset_t) 0; | |||||
} | |||||
} | |||||
static inline int | |||||
bitset_empty(bitset_t set) | |||||
{ | |||||
int i; | |||||
_bitset_word_t result = 0; | |||||
int nwords = WORD_SIZE(set[0]); | |||||
for (i = 1; i < nwords; i++) { | |||||
result |= set[i]; | |||||
} | |||||
return (result == 0); | |||||
} | |||||
static inline int | |||||
bitset_contains(bitset_t set, unsigned int element) | |||||
{ | |||||
assert(element < set[0]); | |||||
return (0 != (set[WORD_INDEX(element)] & (1<<BIT_INDEX(element)))); | |||||
} | |||||
static inline void | |||||
bitset_remove(bitset_t set, unsigned int element) | |||||
{ | |||||
assert(element < set[0]); | |||||
set[WORD_INDEX(element)] &= ~(1<<BIT_INDEX(element)); | |||||
} | |||||
#endif /* __bitset_h__ */ |
@@ -1,565 +0,0 @@ | |||||
/* -*- Mode: C ; c-basic-offset: 4 -*- */ | |||||
/* | |||||
JACK control API | |||||
Copyright (C) 2008 Nedko Arnaudov | |||||
Copyright (C) 2008 GRAME | |||||
This program 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; version 2 of the License. | |||||
This program 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 this program; if not, write to the Free Software | |||||
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. | |||||
*/ | |||||
/** | |||||
* @file jack/control.h | |||||
* @ingroup publicheader | |||||
* @brief JACK control API | |||||
* | |||||
*/ | |||||
#ifndef JACKCTL_H__2EEDAD78_DF4C_4B26_83B7_4FF1A446A47E__INCLUDED | |||||
#define JACKCTL_H__2EEDAD78_DF4C_4B26_83B7_4FF1A446A47E__INCLUDED | |||||
#include <jack/jslist.h> | |||||
#if !defined (__sun__) | |||||
#include <stdbool.h> | |||||
#endif | |||||
/** Parameter types, intentionally similar to jack_driver_param_type_t */ | |||||
typedef enum | |||||
{ | |||||
JackParamInt = 1, /**< @brief value type is a signed integer */ | |||||
JackParamUInt, /**< @brief value type is an unsigned integer */ | |||||
JackParamChar, /**< @brief value type is a char */ | |||||
JackParamString, /**< @brief value type is a string with max size of ::JACK_PARAM_STRING_MAX+1 chars */ | |||||
JackParamBool, /**< @brief value type is a boolean */ | |||||
} jackctl_param_type_t; | |||||
/** @brief Max value that jackctl_param_type_t type can have */ | |||||
#define JACK_PARAM_MAX (JackParamBool + 1) | |||||
/** @brief Max length of string parameter value, excluding terminating null char */ | |||||
#define JACK_PARAM_STRING_MAX 127 | |||||
/** @brief Type for parameter value */ | |||||
/* intentionally similar to jack_driver_param_value_t */ | |||||
union jackctl_parameter_value | |||||
{ | |||||
uint32_t ui; /**< @brief member used for ::JackParamUInt */ | |||||
int32_t i; /**< @brief member used for ::JackParamInt */ | |||||
char c; /**< @brief member used for ::JackParamChar */ | |||||
char str[JACK_PARAM_STRING_MAX + 1]; /**< @brief member used for ::JackParamString */ | |||||
bool b; /**< @brief member used for ::JackParamBool */ | |||||
}; | |||||
/** opaque type for server object */ | |||||
typedef struct jackctl_server jackctl_server_t; | |||||
/** opaque type for driver object */ | |||||
typedef struct jackctl_driver jackctl_driver_t; | |||||
/** opaque type for internal client object */ | |||||
typedef struct jackctl_internal jackctl_internal_t; | |||||
/** opaque type for parameter object */ | |||||
typedef struct jackctl_parameter jackctl_parameter_t; | |||||
#ifdef __cplusplus | |||||
extern "C" { | |||||
#endif | |||||
#if 0 | |||||
} /* Adjust editor indent */ | |||||
#endif | |||||
/** | |||||
* @defgroup ControlAPI the API for starting and controlling a JACK server | |||||
* @{ | |||||
*/ | |||||
/** | |||||
* Call this function to setup process signal handling. As a general | |||||
* rule, it is required for proper operation for the server object. | |||||
* | |||||
* @param flags signals setup flags, use 0 for none. Currently no | |||||
* flags are defined | |||||
* | |||||
* @return the configurated signal set. | |||||
*/ | |||||
sigset_t | |||||
jackctl_setup_signals( | |||||
unsigned int flags); | |||||
/** | |||||
* Call this function to wait on a signal set. | |||||
* | |||||
* @param signals signals set to wait on | |||||
*/ | |||||
void | |||||
jackctl_wait_signals( | |||||
sigset_t signals); | |||||
/** | |||||
* Call this function to create server object. | |||||
* | |||||
* @param on_device_acquire - Optional callback to be called before device is acquired. If false is returned, device usage will fail | |||||
* @param on_device_release - Optional callback to be called after device is released. | |||||
* | |||||
* @return server object handle, NULL if creation of server object | |||||
* failed. Successfully created server object must be destroyed with | |||||
* paired call to ::jackctl_server_destroy | |||||
*/ | |||||
jackctl_server_t * | |||||
jackctl_server_create( | |||||
bool (* on_device_acquire)(const char * device_name), | |||||
void (* on_device_release)(const char * device_name)); | |||||
/** | |||||
* Call this function to destroy server object. | |||||
* | |||||
* @param server server object handle to destroy | |||||
*/ | |||||
void | |||||
jackctl_server_destroy( | |||||
jackctl_server_t * server); | |||||
/** | |||||
* Call this function to start JACK server | |||||
* | |||||
* @param server server object handle | |||||
* @param driver driver to use | |||||
* | |||||
* @return success status: true - success, false - fail | |||||
*/ | |||||
bool | |||||
jackctl_server_start( | |||||
jackctl_server_t * server, | |||||
jackctl_driver_t * driver); | |||||
/** | |||||
* Call this function to stop JACK server | |||||
* | |||||
* @param server server object handle | |||||
* | |||||
* @return success status: true - success, false - fail | |||||
*/ | |||||
bool | |||||
jackctl_server_stop( | |||||
jackctl_server_t * server); | |||||
/** | |||||
* Call this function to get list of available drivers. List node data | |||||
* pointers is a driver object handle (::jackctl_driver_t). | |||||
* | |||||
* @param server server object handle to get drivers for | |||||
* | |||||
* @return Single linked list of driver object handles. Must not be | |||||
* modified. Always same for same server object. | |||||
*/ | |||||
const JSList * | |||||
jackctl_server_get_drivers_list( | |||||
jackctl_server_t * server); | |||||
/** | |||||
* Call this function to get list of server parameters. List node data | |||||
* pointers is a parameter object handle (::jackctl_parameter_t). | |||||
* | |||||
* @param server server object handle to get parameters for | |||||
* | |||||
* @return Single linked list of parameter object handles. Must not be | |||||
* modified. Always same for same server object. | |||||
*/ | |||||
const JSList * | |||||
jackctl_server_get_parameters( | |||||
jackctl_server_t * server); | |||||
/** | |||||
* Call this function to get list of available internal clients. List node data | |||||
* pointers is a internal client object handle (::jackctl_internal_t). | |||||
* | |||||
* @param server server object handle to get internal clients for | |||||
* | |||||
* @return Single linked list of internal client object handles. Must not be | |||||
* modified. Always same for same server object. | |||||
*/ | |||||
const JSList * | |||||
jackctl_server_get_internals_list( | |||||
jackctl_server_t * server); | |||||
/** | |||||
* Call this function to load one internal client. | |||||
* | |||||
* @param server server object handle | |||||
* @param internal internal to use | |||||
* | |||||
* @return success status: true - success, false - fail | |||||
*/ | |||||
bool | |||||
jackctl_server_load_internal( | |||||
jackctl_server_t * server, | |||||
jackctl_internal_t * internal); | |||||
/** | |||||
* Call this function to unload one internal client. | |||||
* | |||||
* @param server server object handle | |||||
* @param internal internal to unload | |||||
* | |||||
* @return success status: true - success, false - fail | |||||
*/ | |||||
bool | |||||
jackctl_server_unload_internal( | |||||
jackctl_server_t * server, | |||||
jackctl_internal_t * internal); | |||||
/** | |||||
* Call this function to add a slave in the driver slave list. | |||||
* | |||||
* @param server server object handle | |||||
* @param driver driver to add in the driver slave list. | |||||
* | |||||
* @return success status: true - success, false - fail | |||||
*/ | |||||
bool | |||||
jackctl_server_add_slave(jackctl_server_t * server, | |||||
jackctl_driver_t * driver); | |||||
/** | |||||
* Call this function to remove a slave from the driver slave list. | |||||
* | |||||
* @param server server object handle | |||||
* @param driver driver to remove from the driver slave list. | |||||
* | |||||
* @return success status: true - success, false - fail | |||||
*/ | |||||
bool | |||||
jackctl_server_remove_slave(jackctl_server_t * server, | |||||
jackctl_driver_t * driver); | |||||
/** | |||||
* Call this function to switch master driver. | |||||
* | |||||
* @param server server object handle | |||||
* @param driver driver to switch to | |||||
* | |||||
* @return success status: true - success, false - fail | |||||
*/ | |||||
bool | |||||
jackctl_server_switch_master(jackctl_server_t * server, | |||||
jackctl_driver_t * driver); | |||||
/** | |||||
* Call this function to get name of driver. | |||||
* | |||||
* @param driver driver object handle to get name of | |||||
* | |||||
* @return driver name. Must not be modified. Always same for same | |||||
* driver object. | |||||
*/ | |||||
const char * | |||||
jackctl_driver_get_name( | |||||
jackctl_driver_t * driver); | |||||
/** | |||||
* Call this function to get list of driver parameters. List node data | |||||
* pointers is a parameter object handle (::jackctl_parameter_t). | |||||
* | |||||
* @param driver driver object handle to get parameters for | |||||
* | |||||
* @return Single linked list of parameter object handles. Must not be | |||||
* modified. Always same for same driver object. | |||||
*/ | |||||
const JSList * | |||||
jackctl_driver_get_parameters( | |||||
jackctl_driver_t * driver); | |||||
/** | |||||
* Call this function to get name of internal client. | |||||
* | |||||
* @param internal internal object handle to get name of | |||||
* | |||||
* @return internal name. Must not be modified. Always same for same | |||||
* internal object. | |||||
*/ | |||||
const char * | |||||
jackctl_internal_get_name( | |||||
jackctl_internal_t * internal); | |||||
/** | |||||
* Call this function to get list of internal parameters. List node data | |||||
* pointers is a parameter object handle (::jackctl_parameter_t). | |||||
* | |||||
* @param internal internal object handle to get parameters for | |||||
* | |||||
* @return Single linked list of parameter object handles. Must not be | |||||
* modified. Always same for same internal object. | |||||
*/ | |||||
const JSList * | |||||
jackctl_internal_get_parameters( | |||||
jackctl_internal_t * internal); | |||||
/** | |||||
* Call this function to get parameter name. | |||||
* | |||||
* @param parameter parameter object handle to get name of | |||||
* | |||||
* @return parameter name. Must not be modified. Always same for same | |||||
* parameter object. | |||||
*/ | |||||
const char * | |||||
jackctl_parameter_get_name( | |||||
jackctl_parameter_t * parameter); | |||||
/** | |||||
* Call this function to get parameter short description. | |||||
* | |||||
* @param parameter parameter object handle to get short description of | |||||
* | |||||
* @return parameter short description. Must not be modified. Always | |||||
* same for same parameter object. | |||||
*/ | |||||
const char * | |||||
jackctl_parameter_get_short_description( | |||||
jackctl_parameter_t * parameter); | |||||
/** | |||||
* Call this function to get parameter long description. | |||||
* | |||||
* @param parameter parameter object handle to get long description of | |||||
* | |||||
* @return parameter long description. Must not be modified. Always | |||||
* same for same parameter object. | |||||
*/ | |||||
const char * | |||||
jackctl_parameter_get_long_description( | |||||
jackctl_parameter_t * parameter); | |||||
/** | |||||
* Call this function to get parameter type. | |||||
* | |||||
* @param parameter parameter object handle to get type of | |||||
* | |||||
* @return parameter type. Always same for same parameter object. | |||||
*/ | |||||
jackctl_param_type_t | |||||
jackctl_parameter_get_type( | |||||
jackctl_parameter_t * parameter); | |||||
/** | |||||
* Call this function to get parameter character. | |||||
* | |||||
* @param parameter parameter object handle to get character of | |||||
* | |||||
* @return character. | |||||
*/ | |||||
char | |||||
jackctl_parameter_get_id( | |||||
jackctl_parameter_t * parameter); | |||||
/** | |||||
* Call this function to check whether parameter has been set, or its | |||||
* default value is being used. | |||||
* | |||||
* @param parameter parameter object handle to check | |||||
* | |||||
* @return true - parameter is set, false - parameter is using default | |||||
* value. | |||||
*/ | |||||
bool | |||||
jackctl_parameter_is_set( | |||||
jackctl_parameter_t * parameter); | |||||
/** | |||||
* Call this function to reset parameter to its default value. | |||||
* | |||||
* @param parameter parameter object handle to reset value of | |||||
* | |||||
* @return success status: true - success, false - fail | |||||
*/ | |||||
bool | |||||
jackctl_parameter_reset( | |||||
jackctl_parameter_t * parameter); | |||||
/** | |||||
* Call this function to get parameter value. | |||||
* | |||||
* @param parameter parameter object handle to get value of | |||||
* | |||||
* @return parameter value. | |||||
*/ | |||||
union jackctl_parameter_value | |||||
jackctl_parameter_get_value( | |||||
jackctl_parameter_t * parameter); | |||||
/** | |||||
* Call this function to set parameter value. | |||||
* | |||||
* @param parameter parameter object handle to get value of | |||||
* @param value_ptr pointer to variable containing parameter value | |||||
* | |||||
* @return success status: true - success, false - fail | |||||
*/ | |||||
bool | |||||
jackctl_parameter_set_value( | |||||
jackctl_parameter_t * parameter, | |||||
const union jackctl_parameter_value * value_ptr); | |||||
/** | |||||
* Call this function to get parameter default value. | |||||
* | |||||
* @param parameter parameter object handle to get default value of | |||||
* | |||||
* @return parameter default value. | |||||
*/ | |||||
union jackctl_parameter_value | |||||
jackctl_parameter_get_default_value( | |||||
jackctl_parameter_t * parameter); | |||||
/** | |||||
* Call this function check whether parameter has range constraint. | |||||
* | |||||
* @param parameter object handle of parameter to check | |||||
* | |||||
* @return whether parameter has range constraint. | |||||
*/ | |||||
bool | |||||
jackctl_parameter_has_range_constraint( | |||||
jackctl_parameter_t * parameter); | |||||
/** | |||||
* Call this function check whether parameter has enumeration constraint. | |||||
* | |||||
* @param parameter object handle of parameter to check | |||||
* | |||||
* @return whether parameter has enumeration constraint. | |||||
*/ | |||||
bool | |||||
jackctl_parameter_has_enum_constraint( | |||||
jackctl_parameter_t * parameter); | |||||
/** | |||||
* Call this function get how many enumeration values parameter has. | |||||
* | |||||
* @param parameter object handle of parameter | |||||
* | |||||
* @return number of enumeration values | |||||
*/ | |||||
uint32_t | |||||
jackctl_parameter_get_enum_constraints_count( | |||||
jackctl_parameter_t * parameter); | |||||
/** | |||||
* Call this function to get parameter enumeration value. | |||||
* | |||||
* @param parameter object handle of parameter | |||||
* @param index index of parameter enumeration value | |||||
* | |||||
* @return enumeration value. | |||||
*/ | |||||
union jackctl_parameter_value | |||||
jackctl_parameter_get_enum_constraint_value( | |||||
jackctl_parameter_t * parameter, | |||||
uint32_t index); | |||||
/** | |||||
* Call this function to get parameter enumeration value description. | |||||
* | |||||
* @param parameter object handle of parameter | |||||
* @param index index of parameter enumeration value | |||||
* | |||||
* @return enumeration value description. | |||||
*/ | |||||
const char * | |||||
jackctl_parameter_get_enum_constraint_description( | |||||
jackctl_parameter_t * parameter, | |||||
uint32_t index); | |||||
/** | |||||
* Call this function to get parameter range. | |||||
* | |||||
* @param parameter object handle of parameter | |||||
* @param min_ptr pointer to variable receiving parameter minimum value | |||||
* @param max_ptr pointer to variable receiving parameter maximum value | |||||
*/ | |||||
void | |||||
jackctl_parameter_get_range_constraint( | |||||
jackctl_parameter_t * parameter, | |||||
union jackctl_parameter_value * min_ptr, | |||||
union jackctl_parameter_value * max_ptr); | |||||
/** | |||||
* Call this function to check whether parameter constraint is strict, | |||||
* i.e. whether supplying non-matching value will not work for sure. | |||||
* | |||||
* @param parameter parameter object handle to check | |||||
* | |||||
* @return whether parameter constraint is strict. | |||||
*/ | |||||
bool | |||||
jackctl_parameter_constraint_is_strict( | |||||
jackctl_parameter_t * parameter); | |||||
/** | |||||
* Call this function to check whether parameter has fake values, | |||||
* i.e. values have no user meaningful meaning and only value | |||||
* description is meaningful to user. | |||||
* | |||||
* @param parameter parameter object handle to check | |||||
* | |||||
* @return whether parameter constraint is strict. | |||||
*/ | |||||
bool | |||||
jackctl_parameter_constraint_is_fake_value( | |||||
jackctl_parameter_t * parameter); | |||||
/** | |||||
* Call this function to log an error message. | |||||
* | |||||
* @param format string | |||||
*/ | |||||
void | |||||
jack_error( | |||||
const char *format, | |||||
...); | |||||
/** | |||||
* Call this function to log an information message. | |||||
* | |||||
* @param format string | |||||
*/ | |||||
void | |||||
jack_info( | |||||
const char *format, | |||||
...); | |||||
/** | |||||
* Call this function to log an information message but only when | |||||
* verbose mode is enabled. | |||||
* | |||||
* @param format string | |||||
*/ | |||||
void | |||||
jack_log( | |||||
const char *format, | |||||
...); | |||||
/* @} */ | |||||
#if 0 | |||||
{ /* Adjust editor indent */ | |||||
#endif | |||||
#ifdef __cplusplus | |||||
} /* extern "C" */ | |||||
#endif | |||||
#endif /* #ifndef JACKCTL_H__2EEDAD78_DF4C_4B26_83B7_4FF1A446A47E__INCLUDED */ |
@@ -1,304 +0,0 @@ | |||||
/* | |||||
Copyright (C) 2001 Paul Davis | |||||
This program 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. | |||||
This program 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 this program; if not, write to the Free Software | |||||
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. | |||||
*/ | |||||
#ifndef __jack_driver_h__ | |||||
#define __jack_driver_h__ | |||||
#include <pthread.h> | |||||
#include <jack/types.h> | |||||
#include <jack/port.h> | |||||
#include <jack/driver_interface.h> | |||||
typedef float gain_t; | |||||
typedef unsigned long channel_t; | |||||
typedef enum { | |||||
Lock = 0x1, | |||||
NoLock = 0x2, | |||||
Sync = 0x4, | |||||
NoSync = 0x8 | |||||
} ClockSyncStatus; | |||||
typedef void (*ClockSyncListenerFunction)(channel_t,ClockSyncStatus,void*); | |||||
typedef struct { | |||||
unsigned long id; | |||||
ClockSyncListenerFunction function; | |||||
void *arg; | |||||
} ClockSyncListener; | |||||
struct _jack_engine; | |||||
struct _jack_driver; | |||||
typedef int (*JackDriverAttachFunction)(struct _jack_driver *, | |||||
struct _jack_engine *); | |||||
typedef int (*JackDriverDetachFunction)(struct _jack_driver *, | |||||
struct _jack_engine *); | |||||
typedef int (*JackDriverReadFunction)(struct _jack_driver *, | |||||
jack_nframes_t nframes); | |||||
typedef int (*JackDriverWriteFunction)(struct _jack_driver *, | |||||
jack_nframes_t nframes); | |||||
typedef int (*JackDriverNullCycleFunction)(struct _jack_driver *, | |||||
jack_nframes_t nframes); | |||||
typedef int (*JackDriverStopFunction)(struct _jack_driver *); | |||||
typedef int (*JackDriverStartFunction)(struct _jack_driver *); | |||||
typedef int (*JackDriverBufSizeFunction)(struct _jack_driver *, | |||||
jack_nframes_t nframes); | |||||
/* | |||||
Call sequence summary: | |||||
1) engine loads driver via runtime dynamic linking | |||||
- calls jack_driver_load | |||||
- we call dlsym for "driver_initialize" and execute it | |||||
2) engine attaches to driver | |||||
3) engine starts driver | |||||
4) driver runs its own thread, calling | |||||
while () { | |||||
driver->wait (); | |||||
driver->engine->run_cycle () | |||||
} | |||||
5) engine stops driver | |||||
6) engine detaches from driver | |||||
7) engine calls driver `finish' routine | |||||
Note that stop/start may be called multiple times in the event of an | |||||
error return from the `wait' function. | |||||
*/ | |||||
typedef struct _jack_driver { | |||||
/* The _jack_driver structure fields are included at the beginning of | |||||
each driver-specific structure using the JACK_DRIVER_DECL macro, | |||||
which is defined below. The comments that follow describe each | |||||
common field. | |||||
The driver should set this to be the interval it expects to elapse | |||||
between returning from the `wait' function. if set to zero, it | |||||
implies that the driver does not expect regular periodic wakeups. | |||||
jack_time_t period_usecs; | |||||
The driver should set this within its "wait" function to indicate | |||||
the UST of the most recent determination that the engine cycle | |||||
should run. it should not be set if the "extra_fd" argument of | |||||
the wait function is set to a non-zero value. | |||||
jack_time_t last_wait_ust; | |||||
These are not used by the driver. They should not be written to or | |||||
modified in any way | |||||
void *handle; | |||||
struct _jack_internal_client *internal_client; | |||||
This should perform any cleanup associated with the driver. it will | |||||
be called when jack server process decides to get rid of the | |||||
driver. in some systems, it may not be called at all, so the driver | |||||
should never rely on a call to this. it can set it to NULL if | |||||
it has nothing do do. | |||||
void (*finish)(struct _jack_driver *); | |||||
The JACK engine will call this when it wishes to attach itself to | |||||
the driver. the engine will pass a pointer to itself, which the driver | |||||
may use in anyway it wishes to. the driver may assume that this | |||||
is the same engine object that will make `wait' calls until a | |||||
`detach' call is made. | |||||
JackDriverAttachFunction attach; | |||||
The JACK engine will call this when it is finished using a driver. | |||||
JackDriverDetachFunction detach; | |||||
The JACK engine will call this when it wants to wait until the | |||||
driver decides that its time to process some data. the driver returns | |||||
a count of the number of audioframes that can be processed. | |||||
it should set the variable pointed to by `status' as follows: | |||||
zero: the wait completed normally, processing may begin | |||||
negative: the wait failed, and recovery is not possible | |||||
positive: the wait failed, and the driver stopped itself. | |||||
a call to `start' will return the driver to | |||||
a correct and known state. | |||||
the driver should also fill out the `delayed_usecs' variable to | |||||
indicate any delay in its expected periodic execution. for example, | |||||
if it discovers that its return from poll(2) is later than it | |||||
expects it to be, it would place an estimate of the delay | |||||
in this variable. the engine will use this to decide if it | |||||
plans to continue execution. | |||||
JackDriverWaitFunction wait; | |||||
The JACK engine will call this to ask the driver to move | |||||
data from its inputs to its output port buffers. it should | |||||
return 0 to indicate successful completion, negative otherwise. | |||||
This function will always be called after the wait function (above). | |||||
JackDriverReadFunction read; | |||||
The JACK engine will call this to ask the driver to move | |||||
data from its input port buffers to its outputs. it should | |||||
return 0 to indicate successful completion, negative otherwise. | |||||
this function will always be called after the read function (above). | |||||
JackDriverWriteFunction write; | |||||
The JACK engine will call this after the wait function (above) has | |||||
been called, but for some reason the engine is unable to execute | |||||
a full "cycle". the driver should do whatever is necessary to | |||||
keep itself running correctly, but cannot reference ports | |||||
or other JACK data structures in any way. | |||||
JackDriverNullCycleFunction null_cycle; | |||||
The engine will call this when it plans to stop calling the `wait' | |||||
function for some period of time. the driver should take | |||||
appropriate steps to handle this (possibly no steps at all). | |||||
NOTE: the driver must silence its capture buffers (if any) | |||||
from within this function or the function that actually | |||||
implements the change in state. | |||||
JackDriverStopFunction stop; | |||||
The engine will call this to let the driver know that it plans | |||||
to start calling the `wait' function on a regular basis. the driver | |||||
should take any appropriate steps to handle this (possibly no steps | |||||
at all). NOTE: The driver may wish to silence its playback buffers | |||||
(if any) from within this function or the function that actually | |||||
implements the change in state. | |||||
JackDriverStartFunction start; | |||||
The engine will call this to let the driver know that some client | |||||
has requested a new buffer size. The stop function will be called | |||||
prior to this, and the start function after this one has returned. | |||||
JackDriverBufSizeFunction bufsize; | |||||
*/ | |||||
/* define the fields here... */ | |||||
#define JACK_DRIVER_DECL \ | |||||
jack_time_t period_usecs; \ | |||||
jack_time_t last_wait_ust; \ | |||||
void *handle; \ | |||||
struct _jack_client_internal * internal_client; \ | |||||
void (*finish)(struct _jack_driver *);\ | |||||
JackDriverAttachFunction attach; \ | |||||
JackDriverDetachFunction detach; \ | |||||
JackDriverReadFunction read; \ | |||||
JackDriverWriteFunction write; \ | |||||
JackDriverNullCycleFunction null_cycle; \ | |||||
JackDriverStopFunction stop; \ | |||||
JackDriverStartFunction start; \ | |||||
JackDriverBufSizeFunction bufsize; | |||||
JACK_DRIVER_DECL /* expand the macro */ | |||||
} jack_driver_t; | |||||
typedef jack_driver_desc_t * (*JackDriverDescFunction) (); | |||||
void jack_driver_init (jack_driver_t *); | |||||
void jack_driver_release (jack_driver_t *); | |||||
jack_driver_t *jack_driver_load (int argc, char **argv); | |||||
void jack_driver_unload (jack_driver_t *); | |||||
/**************************** | |||||
*** Non-Threaded Drivers *** | |||||
****************************/ | |||||
/* | |||||
Call sequence summary: | |||||
1) engine loads driver via runtime dynamic linking | |||||
- calls jack_driver_load | |||||
- we call dlsym for "driver_initialize" and execute it | |||||
- driver_initialize calls jack_driver_nt_init | |||||
2) nt layer attaches to driver | |||||
3) nt layer starts driver | |||||
4) nt layer runs a thread, calling | |||||
while () { | |||||
driver->nt_run_ctcle(); | |||||
} | |||||
5) nt layer stops driver | |||||
6) nt layer detaches driver | |||||
7) engine calls driver `finish' routine which calls jack_driver_nt_finish | |||||
Note that stop/start may be called multiple times in the event of an | |||||
error return from the `wait' function. | |||||
*/ | |||||
struct _jack_driver_nt; | |||||
typedef int (*JackDriverNTAttachFunction)(struct _jack_driver_nt *); | |||||
typedef int (*JackDriverNTDetachFunction)(struct _jack_driver_nt *); | |||||
typedef int (*JackDriverNTStopFunction)(struct _jack_driver_nt *); | |||||
typedef int (*JackDriverNTStartFunction)(struct _jack_driver_nt *); | |||||
typedef int (*JackDriverNTBufSizeFunction)(struct _jack_driver_nt *, | |||||
jack_nframes_t nframes); | |||||
typedef int (*JackDriverNTRunCycleFunction)(struct _jack_driver_nt *); | |||||
typedef struct _jack_driver_nt { | |||||
#define JACK_DRIVER_NT_DECL \ | |||||
JACK_DRIVER_DECL \ | |||||
struct _jack_engine * engine; \ | |||||
volatile int nt_run; \ | |||||
pthread_t nt_thread; \ | |||||
pthread_mutex_t nt_run_lock; \ | |||||
JackDriverNTAttachFunction nt_attach; \ | |||||
JackDriverNTDetachFunction nt_detach; \ | |||||
JackDriverNTStopFunction nt_stop; \ | |||||
JackDriverNTStartFunction nt_start; \ | |||||
JackDriverNTBufSizeFunction nt_bufsize; \ | |||||
JackDriverNTRunCycleFunction nt_run_cycle; | |||||
#define nt_read read | |||||
#define nt_write write | |||||
#define nt_null_cycle null_cycle | |||||
JACK_DRIVER_NT_DECL | |||||
} jack_driver_nt_t; | |||||
void jack_driver_nt_init (jack_driver_nt_t * driver); | |||||
void jack_driver_nt_finish (jack_driver_nt_t * driver); | |||||
#endif /* __jack_driver_h__ */ |
@@ -1,123 +0,0 @@ | |||||
/* | |||||
Copyright (C) 2003 Bob Ham <rah@bash.sh> | |||||
This program is free software; you can redistribute it and/or modify | |||||
it under the terms of the GNU Lesser General Public License as published by | |||||
the Free Software Foundation; either version 2.1 of the License, or | |||||
(at your option) any later version. | |||||
This program 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 Lesser General Public License for more details. | |||||
You should have received a copy of the GNU Lesser General Public License | |||||
along with this program; if not, write to the Free Software | |||||
Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. | |||||
*/ | |||||
#ifndef __jack_driver_interface_h__ | |||||
#define __jack_driver_interface_h__ | |||||
#ifdef __cplusplus | |||||
extern "C" { | |||||
#endif | |||||
#include <limits.h> | |||||
#include <jack/jack.h> | |||||
#include <jack/internal.h> | |||||
#define JACK_DRIVER_NAME_MAX 15 | |||||
#define JACK_DRIVER_PARAM_NAME_MAX 15 | |||||
#define JACK_DRIVER_PARAM_STRING_MAX 63 | |||||
#define JACK_CONSTRAINT_FLAG_RANGE ((uint32_t)1) /**< if set, constraint is a range (min-max) */ | |||||
#define JACK_CONSTRAINT_FLAG_STRICT ((uint32_t)2) /**< if set, constraint is strict, i.e. supplying non-matching value will not work */ | |||||
#define JACK_CONSTRAINT_FLAG_FAKE_VALUE ((uint32_t)4) /**< if set, values have no user meaningful meaning */ | |||||
/** Driver parameter types */ | |||||
typedef enum | |||||
{ | |||||
JackDriverParamInt = 1, | |||||
JackDriverParamUInt, | |||||
JackDriverParamChar, | |||||
JackDriverParamString, | |||||
JackDriverParamBool | |||||
} jack_driver_param_type_t; | |||||
/** Driver parameter value */ | |||||
typedef union | |||||
{ | |||||
uint32_t ui; | |||||
int32_t i; | |||||
char c; | |||||
char str[JACK_DRIVER_PARAM_STRING_MAX+1]; | |||||
} jack_driver_param_value_t; | |||||
typedef struct { | |||||
jack_driver_param_value_t value; | |||||
char short_desc[64]; /**< A short (~30 chars) description for the user */ | |||||
} jack_driver_param_value_enum_t; | |||||
typedef struct { | |||||
uint32_t flags; /**< JACK_CONSTRAINT_FLAG_XXX */ | |||||
union { | |||||
struct { | |||||
jack_driver_param_value_t min; | |||||
jack_driver_param_value_t max; | |||||
} range; /**< valid when JACK_CONSTRAINT_FLAG_RANGE flag is set */ | |||||
struct { | |||||
uint32_t count; | |||||
jack_driver_param_value_enum_t * possible_values_array; | |||||
} enumeration; /**< valid when JACK_CONSTRAINT_FLAG_RANGE flag is not set */ | |||||
} constraint; | |||||
} jack_driver_param_constraint_desc_t; | |||||
/** A driver parameter descriptor */ | |||||
typedef struct | |||||
{ | |||||
char name[JACK_DRIVER_NAME_MAX+1]; /**< The parameter's name */ | |||||
char character; /**< The parameter's character (for getopt, etc) */ | |||||
jack_driver_param_type_t type; /**< The parameter's type */ | |||||
jack_driver_param_value_t value; /**< The parameter's (default) value */ | |||||
jack_driver_param_constraint_desc_t * constraint; /**< Pointer to parameter constraint descriptor. NULL if there is no constraint */ | |||||
char short_desc[64]; /**< A short (~30 chars) description for the user */ | |||||
char long_desc[1024]; /**< A longer description for the user */ | |||||
} jack_driver_param_desc_t; | |||||
/** A driver parameter */ | |||||
typedef struct | |||||
{ | |||||
char character; | |||||
jack_driver_param_value_t value; | |||||
} jack_driver_param_t; | |||||
/** A struct for describing a jack driver */ | |||||
typedef struct | |||||
{ | |||||
char name[JACK_DRIVER_NAME_MAX+1]; /**< The driver's canonical name */ | |||||
char file[PATH_MAX+1]; /**< The filename of the driver's shared object file */ | |||||
uint32_t nparams; /**< The number of parameters the driver has */ | |||||
jack_driver_param_desc_t * params; /**< An array of parameter descriptors */ | |||||
} jack_driver_desc_t; | |||||
#ifdef __cplusplus | |||||
} | |||||
#endif | |||||
#endif /* __jack_driver_interface_h__ */ | |||||
@@ -1,212 +0,0 @@ | |||||
/* -*- mode: c; c-file-style: "linux"; -*- */ | |||||
/* | |||||
Copyright (C) 2003 Bob Ham <rah@bash.sh | |||||
This program 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. | |||||
This program 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 this program; if not, write to the Free Software | |||||
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. | |||||
*/ | |||||
#ifndef __jack_driver_parse_h__ | |||||
#define __jack_driver_parse_h__ | |||||
#include <jack/jslist.h> | |||||
#include <jack/driver_interface.h> | |||||
static void | |||||
jack_print_driver_options (jack_driver_desc_t * desc, FILE *file) | |||||
{ | |||||
unsigned long i; | |||||
char arg_default[JACK_DRIVER_PARAM_STRING_MAX + 1]; | |||||
for (i = 0; i < desc->nparams; i++) { | |||||
switch (desc->params[i].type) { | |||||
case JackDriverParamInt: | |||||
sprintf (arg_default, "%" PRId32, desc->params[i].value.i); | |||||
break; | |||||
case JackDriverParamUInt: | |||||
sprintf (arg_default, "%" PRIu32, desc->params[i].value.ui); | |||||
break; | |||||
case JackDriverParamChar: | |||||
sprintf (arg_default, "%c", desc->params[i].value.c); | |||||
break; | |||||
case JackDriverParamString: | |||||
if (desc->params[i].value.str && | |||||
strcmp (desc->params[i].value.str, "") != 0) | |||||
sprintf (arg_default, "%s", desc->params[i].value.str); | |||||
else | |||||
sprintf (arg_default, "none"); | |||||
break; | |||||
case JackDriverParamBool: | |||||
sprintf (arg_default, "%s", desc->params[i].value.i ? "true" : "false"); | |||||
break; | |||||
} | |||||
fprintf (file, "\t-%c, --%s \t%s (default: %s)\n", | |||||
desc->params[i].character, | |||||
desc->params[i].name, | |||||
desc->params[i].short_desc, | |||||
arg_default); | |||||
} | |||||
} | |||||
static void | |||||
jack_print_driver_param_usage (jack_driver_desc_t * desc, unsigned long param, FILE *file) | |||||
{ | |||||
fprintf (file, "Usage information for the '%s' parameter for driver '%s':\n", | |||||
desc->params[param].name, desc->name); | |||||
fprintf (file, "%s\n", desc->params[param].long_desc); | |||||
} | |||||
static int | |||||
jack_parse_driver_params (jack_driver_desc_t * desc, int argc, char **argv, JSList ** param_ptr) | |||||
{ | |||||
struct option * long_options; | |||||
char * options, * options_ptr; | |||||
unsigned long i; | |||||
int opt, param_index; | |||||
JSList * params = NULL; | |||||
jack_driver_param_t * driver_param; | |||||
if (argc <= 1) { | |||||
*param_ptr = NULL; | |||||
return 0; | |||||
} | |||||
/* check for help */ | |||||
if (strcmp (argv[1], "-h") == 0 || strcmp (argv[1], "--help") == 0) { | |||||
if (argc > 2) { | |||||
for (i = 0; i < desc->nparams; i++) { | |||||
if (strcmp (desc->params[i].name, argv[2]) == 0) { | |||||
jack_print_driver_param_usage (desc, i, stdout); | |||||
return 1; | |||||
} | |||||
} | |||||
fprintf (stderr, "jackd: unknown option '%s' " | |||||
"for driver '%s'\n", argv[2], | |||||
desc->name); | |||||
} | |||||
printf ("Parameters for driver '%s' (all parameters are optional):\n", desc->name); | |||||
jack_print_driver_options (desc, stdout); | |||||
return 1; | |||||
} | |||||
/* set up the stuff for getopt */ | |||||
options = calloc (desc->nparams*3 + 1, sizeof (char)); | |||||
long_options = calloc (desc->nparams + 1, sizeof (struct option)); | |||||
options_ptr = options; | |||||
for (i = 0; i < desc->nparams; i++) { | |||||
sprintf (options_ptr, "%c::", desc->params[i].character); | |||||
options_ptr += 3; | |||||
long_options[i].name = desc->params[i].name; | |||||
long_options[i].flag = NULL; | |||||
long_options[i].val = desc->params[i].character; | |||||
long_options[i].has_arg = optional_argument; | |||||
} | |||||
/* create the params */ | |||||
optind = 0; | |||||
opterr = 0; | |||||
while ((opt = getopt_long(argc, argv, options, long_options, NULL)) != -1) { | |||||
if (opt == ':' || opt == '?') { | |||||
if (opt == ':') { | |||||
fprintf (stderr, "Missing option to argument '%c'\n", optopt); | |||||
} else { | |||||
fprintf (stderr, "Unknownage with option '%c'\n", optopt); | |||||
} | |||||
fprintf (stderr, "Options for driver '%s':\n", desc->name); | |||||
jack_print_driver_options (desc, stderr); | |||||
exit (1); | |||||
} | |||||
for (param_index = 0; param_index < desc->nparams; param_index++) { | |||||
if (opt == desc->params[param_index].character) { | |||||
break; | |||||
} | |||||
} | |||||
driver_param = calloc (1, sizeof (jack_driver_param_t)); | |||||
driver_param->character = desc->params[param_index].character; | |||||
if (!optarg && optind < argc && | |||||
strlen(argv[optind]) && | |||||
argv[optind][0] != '-') { | |||||
optarg = argv[optind]; | |||||
} | |||||
if (optarg) { | |||||
switch (desc->params[param_index].type) { | |||||
case JackDriverParamInt: | |||||
driver_param->value.i = atoi (optarg); | |||||
break; | |||||
case JackDriverParamUInt: | |||||
driver_param->value.ui = strtoul (optarg, NULL, 10); | |||||
break; | |||||
case JackDriverParamChar: | |||||
driver_param->value.c = optarg[0]; | |||||
break; | |||||
case JackDriverParamString: | |||||
strncpy (driver_param->value.str, optarg, JACK_DRIVER_PARAM_STRING_MAX); | |||||
break; | |||||
case JackDriverParamBool: | |||||
if (strcasecmp ("false", optarg) == 0 || | |||||
strcasecmp ("off", optarg) == 0 || | |||||
strcasecmp ("no", optarg) == 0 || | |||||
strcasecmp ("0", optarg) == 0 || | |||||
strcasecmp ("(null)", optarg) == 0 ) { | |||||
driver_param->value.i = FALSE; | |||||
} else { | |||||
driver_param->value.i = TRUE; | |||||
} | |||||
break; | |||||
} | |||||
} else { | |||||
if (desc->params[param_index].type == JackDriverParamBool) { | |||||
driver_param->value.i = TRUE; | |||||
} else { | |||||
driver_param->value = desc->params[param_index].value; | |||||
} | |||||
} | |||||
params = jack_slist_append (params, driver_param); | |||||
} | |||||
free (options); | |||||
free (long_options); | |||||
if (param_ptr) | |||||
*param_ptr = params; | |||||
return 0; | |||||
} | |||||
#endif /* __jack_driver_parse_h__ */ | |||||
@@ -1,272 +0,0 @@ | |||||
/* -*- mode: c; c-file-style: "bsd"; -*- */ | |||||
/* | |||||
Copyright (C) 2001-2003 Paul Davis | |||||
This program 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. | |||||
This program 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 this program; if not, write to the Free Software | |||||
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. | |||||
*/ | |||||
#ifndef __jack_engine_h__ | |||||
#define __jack_engine_h__ | |||||
#include <jack/jack.h> | |||||
#include <jack/internal.h> | |||||
#include <jack/driver_interface.h> | |||||
struct _jack_driver; | |||||
struct _jack_client_internal; | |||||
struct _jack_port_internal; | |||||
/* Structures is allocated by the engine in local memory to keep track | |||||
* of port buffers and connections. | |||||
*/ | |||||
typedef struct { | |||||
jack_shm_info_t* shm_info; | |||||
jack_shmsize_t offset; | |||||
} jack_port_buffer_info_t; | |||||
/* The engine keeps an array of these in its local memory. */ | |||||
typedef struct _jack_port_internal { | |||||
struct _jack_port_shared *shared; | |||||
JSList *connections; | |||||
jack_port_buffer_info_t *buffer_info; | |||||
} jack_port_internal_t; | |||||
/* The engine's internal port type structure. */ | |||||
typedef struct _jack_port_buffer_list { | |||||
pthread_mutex_t lock; /* only lock within server */ | |||||
JSList *freelist; /* list of free buffers */ | |||||
jack_port_buffer_info_t *info; /* jack_buffer_info_t array */ | |||||
} jack_port_buffer_list_t; | |||||
typedef struct _jack_reserved_name { | |||||
jack_client_id_t uuid; | |||||
char name[JACK_CLIENT_NAME_SIZE]; | |||||
} jack_reserved_name_t; | |||||
#define JACKD_WATCHDOG_TIMEOUT 10000 | |||||
#define JACKD_CLIENT_EVENT_TIMEOUT 2000 | |||||
/* The main engine structure in local memory. */ | |||||
struct _jack_engine { | |||||
jack_control_t *control; | |||||
JSList *drivers; | |||||
struct _jack_driver *driver; | |||||
jack_driver_desc_t *driver_desc; | |||||
JSList *driver_params; | |||||
JSList *slave_drivers; | |||||
/* these are "callbacks" made by the driver backend */ | |||||
int (*set_buffer_size) (struct _jack_engine *, jack_nframes_t frames); | |||||
int (*set_sample_rate) (struct _jack_engine *, jack_nframes_t frames); | |||||
int (*run_cycle) (struct _jack_engine *, jack_nframes_t nframes, | |||||
float delayed_usecs); | |||||
void (*delay) (struct _jack_engine *, float delayed_usecs); | |||||
void (*transport_cycle_start) (struct _jack_engine *, jack_time_t time); | |||||
void (*driver_exit) (struct _jack_engine *); | |||||
jack_time_t (*get_microseconds)(void); | |||||
/* "private" sections starts here */ | |||||
/* engine serialization -- use precedence for deadlock avoidance */ | |||||
pthread_mutex_t request_lock; /* precedes client_lock */ | |||||
pthread_rwlock_t client_lock; | |||||
pthread_mutex_t port_lock; | |||||
pthread_mutex_t problem_lock; /* must hold write lock on client_lock */ | |||||
int process_errors; | |||||
int period_msecs; | |||||
/* Time to wait for clients in msecs. Used when jackd is run | |||||
* without realtime priority enabled. */ | |||||
int client_timeout_msecs; | |||||
/* info on the shm segment containing this->control */ | |||||
jack_shm_info_t control_shm; | |||||
/* address-space local port buffer and segment info, | |||||
indexed by the port type_id | |||||
*/ | |||||
jack_port_buffer_list_t port_buffers[JACK_MAX_PORT_TYPES]; | |||||
jack_shm_info_t port_segment[JACK_MAX_PORT_TYPES]; | |||||
unsigned int port_max; | |||||
pthread_t server_thread; | |||||
pthread_t watchdog_thread; | |||||
int fds[2]; | |||||
int cleanup_fifo[2]; | |||||
jack_client_id_t next_client_id; | |||||
size_t pfd_size; | |||||
size_t pfd_max; | |||||
struct pollfd *pfd; | |||||
char fifo_prefix[PATH_MAX+1]; | |||||
int *fifo; | |||||
unsigned long fifo_size; | |||||
/* session handling */ | |||||
int session_reply_fd; | |||||
int session_pending_replies; | |||||
unsigned long external_client_cnt; | |||||
int rtpriority; | |||||
volatile char freewheeling; | |||||
volatile char stop_freewheeling; | |||||
jack_client_id_t fwclient; | |||||
pthread_t freewheel_thread; | |||||
char verbose; | |||||
char do_munlock; | |||||
const char *server_name; | |||||
char temporary; | |||||
int reordered; | |||||
int watchdog_check; | |||||
int feedbackcount; | |||||
int removing_clients; | |||||
pid_t wait_pid; | |||||
int nozombies; | |||||
int timeout_count_threshold; | |||||
volatile int problems; | |||||
volatile int timeout_count; | |||||
volatile int new_clients_allowed; | |||||
/* these lists are protected by `client_lock' */ | |||||
JSList *clients; | |||||
JSList *clients_waiting; | |||||
JSList *reserved_client_names; | |||||
jack_port_internal_t *internal_ports; | |||||
jack_client_internal_t *timebase_client; | |||||
jack_port_buffer_info_t *silent_buffer; | |||||
jack_client_internal_t *current_client; | |||||
#define JACK_ENGINE_ROLLING_COUNT 32 | |||||
#define JACK_ENGINE_ROLLING_INTERVAL 1024 | |||||
jack_time_t rolling_client_usecs[JACK_ENGINE_ROLLING_COUNT]; | |||||
int rolling_client_usecs_cnt; | |||||
int rolling_client_usecs_index; | |||||
int rolling_interval; | |||||
float max_usecs; | |||||
float spare_usecs; | |||||
int first_wakeup; | |||||
#ifdef JACK_USE_MACH_THREADS | |||||
/* specific resources for server/client real-time thread communication */ | |||||
mach_port_t servertask, bp; | |||||
int portnum; | |||||
#endif | |||||
/* used for port names munging */ | |||||
int audio_out_cnt; | |||||
int audio_in_cnt; | |||||
int midi_out_cnt; | |||||
int midi_in_cnt; | |||||
}; | |||||
/* public functions */ | |||||
jack_engine_t *jack_engine_new (int real_time, int real_time_priority, | |||||
int do_mlock, int do_unlock, | |||||
const char *server_name, int temporary, | |||||
int verbose, int client_timeout, | |||||
unsigned int port_max, | |||||
pid_t waitpid, jack_nframes_t frame_time_offset, int nozombies, | |||||
int timeout_count_threshold, | |||||
JSList *drivers); | |||||
void jack_engine_delete (jack_engine_t *); | |||||
int jack_run (jack_engine_t *engine); | |||||
int jack_wait (jack_engine_t *engine); | |||||
int jack_engine_load_driver (jack_engine_t *engine, | |||||
jack_driver_desc_t * driver_desc, | |||||
JSList * driver_params); | |||||
int jack_engine_load_slave_driver (jack_engine_t *engine, | |||||
jack_driver_desc_t * driver_desc, | |||||
JSList * driver_params); | |||||
void jack_dump_configuration(jack_engine_t *engine, int take_lock); | |||||
/* private engine functions */ | |||||
void jack_engine_reset_rolling_usecs (jack_engine_t *engine); | |||||
int internal_client_request (void* ptr, jack_request_t *request); | |||||
int jack_get_fifo_fd (jack_engine_t *engine, | |||||
unsigned int which_fifo); | |||||
extern jack_timer_type_t clock_source; | |||||
extern jack_client_internal_t * | |||||
jack_client_internal_by_id (jack_engine_t *engine, jack_client_id_t id); | |||||
#define jack_rdlock_graph(e) { DEBUG ("acquiring graph read lock"); if (pthread_rwlock_rdlock (&e->client_lock)) abort(); } | |||||
#define jack_lock_graph(e) { DEBUG ("acquiring graph write lock"); if (pthread_rwlock_wrlock (&e->client_lock)) abort(); } | |||||
#define jack_try_rdlock_graph(e) pthread_rwlock_tryrdlock (&e->client_lock) | |||||
#define jack_unlock_graph(e) { DEBUG ("release graph lock"); if (pthread_rwlock_unlock (&e->client_lock)) abort(); } | |||||
#define jack_trylock_problems(e) pthread_mutex_trylock (&e->problem_lock) | |||||
#define jack_lock_problems(e) { DEBUG ("acquiring problem lock"); if (pthread_mutex_lock (&e->problem_lock)) abort(); } | |||||
#define jack_unlock_problems(e) { DEBUG ("release problem lock"); if (pthread_mutex_unlock (&e->problem_lock)) abort(); } | |||||
#if 0 | |||||
static inline void jack_rdlock_graph (jack_engine_t* engine) { | |||||
DEBUG ("acquiring graph read lock"); | |||||
pthread_rwlock_rdlock (&engine->client_lock); | |||||
} | |||||
static inline void jack_lock_graph (jack_engine_t* engine) { | |||||
DEBUG ("acquiring graph lock"); | |||||
pthread_rwlock_wrlock (&engine->client_lock); | |||||
} | |||||
static inline int jack_try_rdlock_graph (jack_engine_t *engine) | |||||
{ | |||||
DEBUG ("TRYING to acquiring graph read lock"); | |||||
return pthread_rwlock_tryrdlock (&engine->client_lock); | |||||
} | |||||
static inline void jack_unlock_graph (jack_engine_t* engine) | |||||
{ | |||||
DEBUG ("releasing graph lock"); | |||||
pthread_rwlock_unlock (&engine->client_lock); | |||||
} | |||||
#endif | |||||
static inline unsigned int jack_power_of_two (unsigned int n) | |||||
{ | |||||
return !(n & (n - 1)); | |||||
} | |||||
/* Internal port handling interfaces for JACK engine. */ | |||||
void jack_port_clear_connections (jack_engine_t *engine, | |||||
jack_port_internal_t *port); | |||||
void jack_port_registration_notify (jack_engine_t *, jack_port_id_t, int); | |||||
void jack_port_release (jack_engine_t *engine, jack_port_internal_t *); | |||||
void jack_sort_graph (jack_engine_t *engine); | |||||
int jack_stop_freewheeling (jack_engine_t* engine, int engine_exiting); | |||||
jack_client_internal_t * | |||||
jack_client_by_name (jack_engine_t *engine, const char *name); | |||||
int jack_deliver_event (jack_engine_t *, jack_client_internal_t *, jack_event_t *); | |||||
void jack_stop_watchdog (jack_engine_t * ); | |||||
void | |||||
jack_engine_signal_problems (jack_engine_t* engine); | |||||
int | |||||
jack_use_driver (jack_engine_t *engine, struct _jack_driver *driver); | |||||
int | |||||
jack_drivers_start (jack_engine_t *engine); | |||||
int | |||||
jack_add_slave_driver (jack_engine_t *engine, struct _jack_driver *driver); | |||||
#endif /* __jack_engine_h__ */ |
@@ -1,65 +0,0 @@ | |||||
/* | |||||
Copyright (C) 2001 Paul Davis | |||||
This program 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. | |||||
This program 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 this program; if not, write to the Free Software | |||||
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. | |||||
*/ | |||||
#ifndef __jack_hardware_h__ | |||||
#define __jack_hardware_h__ | |||||
#include <jack/types.h> | |||||
typedef enum { | |||||
AutoSync, | |||||
WordClock, | |||||
ClockMaster | |||||
} SampleClockMode; | |||||
typedef enum { | |||||
Cap_HardwareMonitoring = 0x1, | |||||
Cap_AutoSync = 0x2, | |||||
Cap_WordClock = 0x4, | |||||
Cap_ClockMaster = 0x8, | |||||
Cap_ClockLockReporting = 0x10, | |||||
Cap_HardwareMetering = 0x20 | |||||
} Capabilities; | |||||
struct _jack_hardware; | |||||
typedef void (*JackHardwareReleaseFunction)(struct _jack_hardware *); | |||||
typedef int (*JackHardwareSetInputMonitorMaskFunction)(struct _jack_hardware *, unsigned long); | |||||
typedef int (*JackHardwareChangeSampleClockFunction)(struct _jack_hardware *, SampleClockMode); | |||||
typedef double (*JackHardwareGetHardwarePeak)(jack_port_t *port, jack_nframes_t frames); | |||||
typedef double (*JackHardwareGetHardwarePower)(jack_port_t *port, jack_nframes_t frames); | |||||
typedef struct _jack_hardware { | |||||
unsigned long capabilities; | |||||
unsigned long input_monitor_mask; | |||||
JackHardwareChangeSampleClockFunction change_sample_clock; | |||||
JackHardwareSetInputMonitorMaskFunction set_input_monitor_mask; | |||||
JackHardwareReleaseFunction release; | |||||
JackHardwareGetHardwarePeak get_hardware_peak; | |||||
JackHardwareGetHardwarePower get_hardware_power; | |||||
void *private; | |||||
} jack_hardware_t; | |||||
jack_hardware_t * jack_hardware_new (); | |||||
#endif /* __jack_hardware_h__ */ |
@@ -1,129 +0,0 @@ | |||||
/* | |||||
* Copyright (C) 2004 Jack O'Quin | |||||
* | |||||
* This program is free software; you can redistribute it and/or modify | |||||
* it under the terms of the GNU Lesser General Public License as published by | |||||
* the Free Software Foundation; either version 2.1 of the License, or | |||||
* (at your option) any later version. | |||||
* | |||||
* This program 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 Lesser General Public License for more details. | |||||
* | |||||
* You should have received a copy of the GNU Lesser General Public License | |||||
* along with this program; if not, write to the Free Software | |||||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. | |||||
* | |||||
*/ | |||||
#ifndef __jack_intclient_h__ | |||||
#define __jack_intclient_h__ | |||||
#ifdef __cplusplus | |||||
extern "C" { | |||||
#endif | |||||
#include <jack/types.h> | |||||
/** | |||||
* Get an internal client's name. This is useful when @ref | |||||
* JackUseExactName was not specified on jack_internal_client_load() | |||||
* and @ref JackNameNotUnique status was returned. In that case, the | |||||
* actual name will differ from the @a client_name requested. | |||||
* | |||||
* @param client requesting JACK client's handle. | |||||
* | |||||
* @param intclient handle returned from jack_internal_client_load() | |||||
* or jack_internal_client_handle(). | |||||
* | |||||
* @return NULL if unsuccessful, otherwise pointer to the internal | |||||
* client name obtained from the heap via malloc(). The caller should | |||||
* free() this storage when no longer needed. | |||||
*/ | |||||
char *jack_get_internal_client_name (jack_client_t *client, | |||||
jack_intclient_t intclient); | |||||
/** | |||||
* Return the @ref jack_intclient_t handle for an internal client | |||||
* running in the JACK server. | |||||
* | |||||
* @param client requesting JACK client's handle. | |||||
* | |||||
* @param client_name for the internal client of no more than | |||||
* jack_client_name_size() characters. The name scope is local to the | |||||
* current server. | |||||
* | |||||
* @param status (if non-NULL) an address for JACK to return | |||||
* information from this operation. This status word is formed by | |||||
* OR-ing together the relevant @ref JackStatus bits. | |||||
* | |||||
* @return Opaque internal client handle if successful. If 0, the | |||||
* internal client was not found, and @a *status includes the @ref | |||||
* JackNoSuchClient and @ref JackFailure bits. | |||||
*/ | |||||
jack_intclient_t jack_internal_client_handle (jack_client_t *client, | |||||
const char *client_name, | |||||
jack_status_t *status); | |||||
/** | |||||
* Load an internal client into the JACK server. | |||||
* | |||||
* Internal clients run inside the JACK server process. They can use | |||||
* most of the same functions as external clients. Each internal | |||||
* client is built as a shared object module, which must declare | |||||
* jack_initialize() and jack_finish() entry points called at load and | |||||
* unload times. See @ref inprocess.c for an example. | |||||
* | |||||
* @param client loading JACK client's handle. | |||||
* | |||||
* @param client_name of at most jack_client_name_size() characters | |||||
* for the internal client to load. The name scope is local to the | |||||
* current server. | |||||
* | |||||
* @param options formed by OR-ing together @ref JackOptions bits. | |||||
* Only the @ref JackLoadOptions bits are valid. | |||||
* | |||||
* @param status (if non-NULL) an address for JACK to return | |||||
* information from the load operation. This status word is formed by | |||||
* OR-ing together the relevant @ref JackStatus bits. | |||||
* | |||||
* <b>Optional parameters:</b> depending on corresponding [@a options | |||||
* bits] additional parameters may follow @a status (in this order). | |||||
* | |||||
* @arg [@ref JackLoadName] <em>(char *) load_name</em> is the shared | |||||
* object file from which to load the new internal client (otherwise | |||||
* use the @a client_name). | |||||
* | |||||
* @arg [@ref JackLoadInit] <em>(char *) load_init</em> an arbitary | |||||
* string passed to the internal client's jack_initialize() routine | |||||
* (otherwise NULL), of no more than @ref JACK_LOAD_INIT_LIMIT bytes. | |||||
* | |||||
* @return Opaque internal client handle if successful. If this is 0, | |||||
* the load operation failed, the internal client was not loaded, and | |||||
* @a *status includes the @ref JackFailure bit. | |||||
*/ | |||||
jack_intclient_t jack_internal_client_load (jack_client_t *client, | |||||
const char *client_name, | |||||
jack_options_t options, | |||||
jack_status_t *status, ...); | |||||
/** | |||||
* Unload an internal client from a JACK server. This calls the | |||||
* intclient's jack_finish() entry point then removes it. See @ref | |||||
* inprocess.c for an example. | |||||
* | |||||
* @param client unloading JACK client's handle. | |||||
* | |||||
* @param intclient handle returned from jack_internal_client_load() or | |||||
* jack_internal_client_handle(). | |||||
* | |||||
* @return 0 if successful, otherwise @ref JackStatus bits. | |||||
*/ | |||||
jack_status_t jack_internal_client_unload (jack_client_t *client, | |||||
jack_intclient_t intclient); | |||||
#ifdef __cplusplus | |||||
} | |||||
#endif | |||||
#endif /* __jack_intclient_h__ */ |
@@ -1,561 +0,0 @@ | |||||
/* -*- mode: c; c-file-style: "bsd"; -*- */ | |||||
/* | |||||
Internal shared data and functions. | |||||
If you edit this file, you should carefully consider changing the | |||||
JACK_PROTOCOL_VERSION in configure.in. | |||||
Copyright (C) 2001-2003 Paul Davis | |||||
This program 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. | |||||
This program 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 this program; if not, write to the Free Software | |||||
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. | |||||
*/ | |||||
#ifndef __jack_internal_h__ | |||||
#define __jack_internal_h__ | |||||
#include <stdlib.h> | |||||
#include <unistd.h> | |||||
#include <limits.h> | |||||
#include <dlfcn.h> | |||||
#include <pthread.h> | |||||
#include <sys/types.h> | |||||
#include <sys/time.h> | |||||
#ifndef POST_PACKED_STRUCTURE | |||||
#ifdef __GNUC__ | |||||
/* POST_PACKED_STRUCTURE needs to be a macro which | |||||
expands into a compiler directive. The directive must | |||||
tell the compiler to arrange the preceding structure | |||||
declaration so that it is packed on byte-boundaries rather | |||||
than use the natural alignment of the processor and/or | |||||
compiler. | |||||
*/ | |||||
#define POST_PACKED_STRUCTURE __attribute__((__packed__)) | |||||
#else | |||||
/* Add other things here for non-gcc platforms */ | |||||
#endif | |||||
#endif | |||||
/* Needed by <sysdeps/time.h> */ | |||||
extern void jack_error (const char *fmt, ...); | |||||
extern void jack_info (const char *fmt, ...); | |||||
#include <jack/jack.h> | |||||
#include <jack/types.h> | |||||
#include <jack/port.h> | |||||
#include <jack/transport.h> | |||||
#include <jack/session.h> | |||||
#include <jack/thread.h> | |||||
extern jack_thread_creator_t jack_thread_creator; | |||||
typedef enum { | |||||
JACK_TIMER_SYSTEM_CLOCK, | |||||
JACK_TIMER_CYCLE_COUNTER, | |||||
JACK_TIMER_HPET, | |||||
} jack_timer_type_t; | |||||
void jack_init_time (); | |||||
void jack_set_clock_source (jack_timer_type_t); | |||||
const char* jack_clock_source_name (jack_timer_type_t); | |||||
#include <sysdeps/time.h> | |||||
#include <sysdeps/atomicity.h> | |||||
#ifdef JACK_USE_MACH_THREADS | |||||
#include <sysdeps/mach_port.h> | |||||
#endif | |||||
#include <jack/messagebuffer.h> | |||||
#ifndef PATH_MAX | |||||
#ifdef MAXPATHLEN | |||||
#define PATH_MAX MAXPATHLEN | |||||
#else | |||||
#define PATH_MAX 1024 | |||||
#endif /* MAXPATHLEN */ | |||||
#endif /* !PATH_MAX */ | |||||
#ifdef DEBUG_ENABLED | |||||
/* grab thread id instead of PID on linux */ | |||||
#if defined(__gnu_linux__) | |||||
#ifdef gettid /* glibc has a version */ | |||||
#define GETTID() gettid() | |||||
#else /* use our own version */ | |||||
#include <sys/syscall.h> | |||||
#define GETTID() syscall(__NR_gettid) | |||||
#endif | |||||
#else | |||||
#define GETTID() getpid() | |||||
#endif | |||||
#define DEBUG(format,args...) \ | |||||
MESSAGE("jack:%5d:%" PRIu64 " %s:%s:%d: " format "", GETTID(), jack_get_microseconds(), __FILE__, __FUNCTION__, __LINE__ , ## args) | |||||
#else | |||||
#if JACK_CPP_VARARGS_BROKEN | |||||
#define DEBUG(format...) | |||||
#else | |||||
#define DEBUG(format,args...) | |||||
#endif | |||||
#endif | |||||
/* Enable preemption checking for Linux Realtime Preemption kernels. | |||||
* | |||||
* This checks if any RT-safe code section does anything to cause CPU | |||||
* preemption. Examples are sleep() or other system calls that block. | |||||
* If a problem is detected, the kernel writes a syslog entry, and | |||||
* sends SIGUSR2 to the client. | |||||
*/ | |||||
#ifdef DO_PREEMPTION_CHECKING | |||||
#define CHECK_PREEMPTION(engine, onoff) \ | |||||
if ((engine)->real_time) gettimeofday (1, (onoff)) | |||||
#else | |||||
#define CHECK_PREEMPTION(engine, onoff) | |||||
#endif | |||||
#ifndef FALSE | |||||
#define FALSE (0) | |||||
#endif | |||||
#ifndef TRUE | |||||
#define TRUE (1) | |||||
#endif | |||||
typedef struct _jack_engine jack_engine_t; | |||||
typedef struct _jack_request jack_request_t; | |||||
typedef void * dlhandle; | |||||
typedef enum { | |||||
TransportCommandNone = 0, | |||||
TransportCommandStart = 1, | |||||
TransportCommandStop = 2, | |||||
} transport_command_t; | |||||
typedef struct { | |||||
volatile uint32_t guard1; | |||||
volatile jack_nframes_t frames; | |||||
volatile jack_time_t current_wakeup; | |||||
volatile jack_time_t next_wakeup; | |||||
volatile float second_order_integrator; | |||||
volatile int32_t initialized; | |||||
volatile uint32_t guard2; | |||||
/* not accessed by clients */ | |||||
int32_t reset_pending; /* xrun happened, deal with it */ | |||||
float filter_coefficient; /* set once, never altered */ | |||||
} POST_PACKED_STRUCTURE jack_frame_timer_t; | |||||
/* JACK engine shared memory data structure. */ | |||||
typedef struct { | |||||
jack_transport_state_t transport_state; | |||||
volatile transport_command_t transport_cmd; | |||||
transport_command_t previous_cmd; /* previous transport_cmd */ | |||||
jack_position_t current_time; /* position for current cycle */ | |||||
jack_position_t pending_time; /* position for next cycle */ | |||||
jack_position_t request_time; /* latest requested position */ | |||||
jack_unique_t prev_request; /* previous request unique ID */ | |||||
volatile _Atomic_word seq_number; /* unique ID sequence number */ | |||||
int8_t new_pos; /* new position this cycle */ | |||||
int8_t pending_pos; /* new position request pending */ | |||||
jack_nframes_t pending_frame; /* pending frame number */ | |||||
int32_t sync_clients; /* number of active_slowsync clients */ | |||||
int32_t sync_remain; /* number of them with sync_poll */ | |||||
jack_time_t sync_timeout; | |||||
jack_time_t sync_time_left; | |||||
jack_frame_timer_t frame_timer; | |||||
int32_t internal; | |||||
jack_timer_type_t clock_source; | |||||
pid_t engine_pid; | |||||
jack_nframes_t buffer_size; | |||||
int8_t real_time; | |||||
int8_t do_mlock; | |||||
int8_t do_munlock; | |||||
int32_t client_priority; | |||||
int32_t max_client_priority; | |||||
int32_t has_capabilities; | |||||
float cpu_load; | |||||
float xrun_delayed_usecs; | |||||
float max_delayed_usecs; | |||||
uint32_t port_max; | |||||
int32_t engine_ok; | |||||
jack_port_type_id_t n_port_types; | |||||
jack_port_type_info_t port_types[JACK_MAX_PORT_TYPES]; | |||||
jack_port_shared_t ports[0]; | |||||
} POST_PACKED_STRUCTURE jack_control_t; | |||||
typedef enum { | |||||
BufferSizeChange, | |||||
SampleRateChange, | |||||
AttachPortSegment, | |||||
PortConnected, | |||||
PortDisconnected, | |||||
GraphReordered, | |||||
PortRegistered, | |||||
PortUnregistered, | |||||
XRun, | |||||
StartFreewheel, | |||||
StopFreewheel, | |||||
ClientRegistered, | |||||
ClientUnregistered, | |||||
SaveSession, | |||||
LatencyCallback | |||||
} JackEventType; | |||||
typedef struct { | |||||
JackEventType type; | |||||
union { | |||||
uint32_t n; | |||||
char name[JACK_PORT_NAME_SIZE]; | |||||
jack_port_id_t port_id; | |||||
jack_port_id_t self_id; | |||||
} x; | |||||
union { | |||||
uint32_t n; | |||||
jack_port_type_id_t ptid; | |||||
jack_port_id_t other_id; | |||||
} y; | |||||
} POST_PACKED_STRUCTURE jack_event_t; | |||||
typedef enum { | |||||
ClientInternal, /* connect request just names .so */ | |||||
ClientDriver, /* code is loaded along with driver */ | |||||
ClientExternal /* client is in another process */ | |||||
} ClientType; | |||||
typedef enum { | |||||
NotTriggered, | |||||
Triggered, | |||||
Running, | |||||
Finished | |||||
} jack_client_state_t; | |||||
/* JACK client shared memory data structure. */ | |||||
typedef volatile struct { | |||||
volatile jack_client_id_t id; /* w: engine r: engine and client */ | |||||
volatile jack_client_id_t uid; /* w: engine r: engine and client */ | |||||
volatile jack_client_state_t state; /* w: engine and client r: engine */ | |||||
volatile char name[JACK_CLIENT_NAME_SIZE]; | |||||
volatile char session_command[JACK_PORT_NAME_SIZE]; | |||||
volatile jack_session_flags_t session_flags; | |||||
volatile ClientType type; /* w: engine r: engine and client */ | |||||
volatile int8_t active; /* w: engine r: engine and client */ | |||||
volatile int8_t dead; /* r/w: engine */ | |||||
volatile int8_t timed_out; /* r/w: engine */ | |||||
volatile int8_t is_timebase; /* w: engine, r: engine and client */ | |||||
volatile int8_t timebase_new; /* w: engine and client, r: engine */ | |||||
volatile int8_t is_slowsync; /* w: engine, r: engine and client */ | |||||
volatile int8_t active_slowsync; /* w: engine, r: engine and client */ | |||||
volatile int8_t sync_poll; /* w: engine and client, r: engine */ | |||||
volatile int8_t sync_new; /* w: engine and client, r: engine */ | |||||
volatile pid_t pid; /* w: client r: engine; client pid */ | |||||
volatile pid_t pgrp; /* w: client r: engine; client pgrp */ | |||||
volatile uint64_t signalled_at; | |||||
volatile uint64_t awake_at; | |||||
volatile uint64_t finished_at; | |||||
volatile int32_t last_status; /* w: client, r: engine and client */ | |||||
/* indicators for whether callbacks have been set for this client. | |||||
We do not include ptrs to the callbacks here (or their arguments) | |||||
so that we can avoid 32/64 bit pointer size mismatches between | |||||
the jack server and a client. The pointers are in the client- | |||||
local structure which is part of the libjack compiled for | |||||
either 32 bit or 64 bit clients. | |||||
*/ | |||||
volatile uint8_t process_cbset; | |||||
volatile uint8_t thread_init_cbset; | |||||
volatile uint8_t bufsize_cbset; | |||||
volatile uint8_t srate_cbset; | |||||
volatile uint8_t port_register_cbset; | |||||
volatile uint8_t port_connect_cbset; | |||||
volatile uint8_t graph_order_cbset; | |||||
volatile uint8_t xrun_cbset; | |||||
volatile uint8_t sync_cb_cbset; | |||||
volatile uint8_t timebase_cb_cbset; | |||||
volatile uint8_t freewheel_cb_cbset; | |||||
volatile uint8_t client_register_cbset; | |||||
volatile uint8_t thread_cb_cbset; | |||||
volatile uint8_t session_cbset; | |||||
volatile uint8_t latency_cbset; | |||||
} POST_PACKED_STRUCTURE jack_client_control_t; | |||||
typedef struct { | |||||
uint32_t protocol_v; /* protocol version, must go first */ | |||||
int32_t load; | |||||
ClientType type; | |||||
jack_options_t options; | |||||
jack_client_id_t uuid; | |||||
char name[JACK_CLIENT_NAME_SIZE]; | |||||
char object_path[PATH_MAX+1]; | |||||
char object_data[1024]; | |||||
} POST_PACKED_STRUCTURE jack_client_connect_request_t; | |||||
typedef struct { | |||||
jack_status_t status; | |||||
jack_shm_registry_index_t client_shm_index; | |||||
jack_shm_registry_index_t engine_shm_index; | |||||
char fifo_prefix[PATH_MAX+1]; | |||||
int32_t realtime; | |||||
int32_t realtime_priority; | |||||
char name[JACK_CLIENT_NAME_SIZE]; /* unique name, if assigned */ | |||||
/* these are actually pointers, but they must | |||||
be the same size regardless of whether the | |||||
server and/or client are 64 bit or 32 bit. | |||||
force them to be 64 bit. | |||||
*/ | |||||
uint64_t client_control; | |||||
uint64_t engine_control; | |||||
#ifdef JACK_USE_MACH_THREADS | |||||
/* specific resources for server/client real-time thread communication */ | |||||
int32_t portnum; | |||||
#endif | |||||
} POST_PACKED_STRUCTURE jack_client_connect_result_t; | |||||
typedef struct { | |||||
jack_client_id_t client_id; | |||||
} POST_PACKED_STRUCTURE jack_client_connect_ack_request_t; | |||||
typedef struct { | |||||
int8_t status; | |||||
} POST_PACKED_STRUCTURE jack_client_connect_ack_result_t; | |||||
typedef enum { | |||||
RegisterPort = 1, | |||||
UnRegisterPort = 2, | |||||
ConnectPorts = 3, | |||||
DisconnectPorts = 4, | |||||
SetTimeBaseClient = 5, | |||||
ActivateClient = 6, | |||||
DeactivateClient = 7, | |||||
DisconnectPort = 8, | |||||
SetClientCapabilities = 9, | |||||
GetPortConnections = 10, | |||||
GetPortNConnections = 11, | |||||
ResetTimeBaseClient = 12, | |||||
SetSyncClient = 13, | |||||
ResetSyncClient = 14, | |||||
SetSyncTimeout = 15, | |||||
SetBufferSize = 16, | |||||
FreeWheel = 17, | |||||
StopFreeWheel = 18, | |||||
IntClientHandle = 19, | |||||
IntClientLoad = 20, | |||||
IntClientName = 21, | |||||
IntClientUnload = 22, | |||||
RecomputeTotalLatencies = 23, | |||||
RecomputeTotalLatency = 24, | |||||
SessionNotify = 25, | |||||
GetClientByUUID = 26, | |||||
ReserveName = 30, | |||||
SessionReply = 31, | |||||
SessionHasCallback = 32 | |||||
} RequestType; | |||||
struct _jack_request { | |||||
//RequestType type; | |||||
uint32_t type; | |||||
union { | |||||
struct { | |||||
char name[JACK_PORT_NAME_SIZE]; | |||||
char type[JACK_PORT_TYPE_SIZE]; | |||||
uint32_t flags; | |||||
jack_shmsize_t buffer_size; | |||||
jack_port_id_t port_id; | |||||
jack_client_id_t client_id; | |||||
} POST_PACKED_STRUCTURE port_info; | |||||
struct { | |||||
char source_port[JACK_PORT_NAME_SIZE]; | |||||
char destination_port[JACK_PORT_NAME_SIZE]; | |||||
} POST_PACKED_STRUCTURE connect; | |||||
struct { | |||||
char path[JACK_PORT_NAME_SIZE]; | |||||
jack_session_event_type_t type; | |||||
char target[JACK_CLIENT_NAME_SIZE]; | |||||
} POST_PACKED_STRUCTURE session; | |||||
struct { | |||||
int32_t nports; | |||||
const char **ports; /* this is only exposed to internal clients, so there | |||||
is no 64/32 issue. external clients read the ports | |||||
one by one from the server, and allocate their | |||||
own "ports" array in their own address space. | |||||
we are lucky, because this is part of a union | |||||
whose other components are bigger than this one. | |||||
otherwise it would change structure size when | |||||
comparing the 64 and 32 bit versions. | |||||
*/ | |||||
} POST_PACKED_STRUCTURE port_connections; | |||||
struct { | |||||
jack_client_id_t client_id; | |||||
int32_t conditional; | |||||
} POST_PACKED_STRUCTURE timebase; | |||||
struct { | |||||
char name[JACK_CLIENT_NAME_SIZE]; | |||||
jack_client_id_t uuid; | |||||
} POST_PACKED_STRUCTURE reservename; | |||||
struct { | |||||
//jack_options_t options; | |||||
uint32_t options; | |||||
jack_client_id_t id; | |||||
char name[JACK_CLIENT_NAME_SIZE]; | |||||
char path[PATH_MAX+1]; | |||||
char init[JACK_LOAD_INIT_LIMIT]; | |||||
} POST_PACKED_STRUCTURE intclient; | |||||
jack_client_id_t client_id; | |||||
jack_nframes_t nframes; | |||||
jack_time_t timeout; | |||||
pid_t cap_pid; | |||||
char name[JACK_CLIENT_NAME_SIZE]; | |||||
} POST_PACKED_STRUCTURE x; | |||||
int32_t status; | |||||
} POST_PACKED_STRUCTURE; | |||||
/* Per-client structure allocated in the server's address space. | |||||
* It's here because its not part of the engine structure. | |||||
*/ | |||||
typedef struct _jack_client_internal { | |||||
jack_client_control_t *control; | |||||
int request_fd; | |||||
int event_fd; | |||||
int subgraph_start_fd; | |||||
int subgraph_wait_fd; | |||||
JSList *ports; /* protected by engine->client_lock */ | |||||
JSList *truefeeds; /* protected by engine->client_lock */ | |||||
JSList *sortfeeds; /* protected by engine->client_lock */ | |||||
int fedcount; | |||||
int tfedcount; | |||||
jack_shm_info_t control_shm; | |||||
unsigned long execution_order; | |||||
struct _jack_client_internal *next_client; /* not a linked list! */ | |||||
dlhandle handle; | |||||
int (*initialize)(jack_client_t*, const char*); /* int. clients only */ | |||||
void (*finish)(void *); /* internal clients only */ | |||||
int error; | |||||
int session_reply_pending; | |||||
#ifdef JACK_USE_MACH_THREADS | |||||
/* specific resources for server/client real-time thread communication */ | |||||
mach_port_t serverport; | |||||
trivial_message message; | |||||
int running; | |||||
int portnum; | |||||
#endif /* JACK_USE_MACH_THREADS */ | |||||
jack_client_t *private_client; | |||||
} jack_client_internal_t; | |||||
typedef struct _jack_thread_arg { | |||||
jack_client_t* client; | |||||
void* (*work_function)(void*); | |||||
int priority; | |||||
int realtime; | |||||
void* arg; | |||||
pid_t cap_pid; | |||||
} jack_thread_arg_t; | |||||
extern int jack_client_handle_port_connection (jack_client_t *client, | |||||
jack_event_t *event); | |||||
extern jack_client_t *jack_driver_client_new (jack_engine_t *, | |||||
const char *client_name); | |||||
extern jack_client_t *jack_client_alloc_internal (jack_client_control_t*, | |||||
jack_engine_t*); | |||||
/* internal clients call this. it's defined in jack/engine.c */ | |||||
void handle_internal_client_request (jack_control_t*, jack_request_t*); | |||||
extern char *jack_tmpdir; | |||||
extern char *jack_user_dir (void); | |||||
extern char *jack_server_dir (const char *server_name, char *server_dir); | |||||
extern void *jack_zero_filled_buffer; | |||||
extern jack_port_functions_t jack_builtin_audio_functions; | |||||
extern jack_port_type_info_t jack_builtin_port_types[]; | |||||
extern void jack_client_fix_port_buffers (jack_client_t *client); | |||||
extern void jack_transport_copy_position (jack_position_t *from, | |||||
jack_position_t *to); | |||||
extern void jack_call_sync_client (jack_client_t *client); | |||||
extern void jack_call_timebase_master (jack_client_t *client); | |||||
extern char *jack_default_server_name (void); | |||||
void silent_jack_error_callback (const char *desc); | |||||
/* needed for port management */ | |||||
extern jack_port_t *jack_port_by_id_int (const jack_client_t *client, | |||||
jack_port_id_t id, int* free); | |||||
extern jack_port_t *jack_port_by_name_int (jack_client_t *client, | |||||
const char *port_name); | |||||
extern int jack_port_name_equals (jack_port_shared_t* port, const char* target); | |||||
/** Get the size (in bytes) of the data structure used to store | |||||
* MIDI events internally. | |||||
*/ | |||||
extern size_t jack_midi_internal_event_size (); | |||||
extern int jack_client_handle_latency_callback (jack_client_t *client, jack_event_t *event, int is_driver); | |||||
#ifdef __GNUC__ | |||||
# define likely(x) __builtin_expect((x),1) | |||||
# define unlikely(x) __builtin_expect((x),0) | |||||
#else | |||||
# define likely(x) (x) | |||||
# define unlikely(x) (x) | |||||
#endif | |||||
#ifdef VALGRIND_CLEAN | |||||
#include <string.h> | |||||
#define VALGRIND_MEMSET(ptr,val,size) memset ((ptr),(val),(size)) | |||||
#else | |||||
#define VALGRIND_MEMSET(ptr,val,size) | |||||
#endif | |||||
#endif /* __jack_internal_h__ */ | |||||
@@ -1,56 +0,0 @@ | |||||
/* | |||||
Copyright (C) 2005-2007 Jussi Laako | |||||
This program 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. | |||||
This program 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 this program; if not, write to the Free Software | |||||
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. | |||||
*/ | |||||
#ifndef __jack_intsimd_h__ | |||||
#define __jack_intsimd_h__ | |||||
#ifdef USE_DYNSIMD | |||||
#if (defined(__i386__) || defined(__x86_64__)) | |||||
#define ARCH_X86 | |||||
#endif /* __i386__ || __x86_64__ */ | |||||
#endif /* USE_DYNSIMD */ | |||||
#ifdef ARCH_X86 | |||||
#define ARCH_X86_SSE(x) ((x) & 0xff) | |||||
#define ARCH_X86_HAVE_SSE2(x) (ARCH_X86_SSE(x) >= 2) | |||||
#define ARCH_X86_3DNOW(x) ((x) >> 8) | |||||
#define ARCH_X86_HAVE_3DNOW(x) (ARCH_X86_3DNOW(x)) | |||||
typedef float v2sf __attribute__((vector_size(8))); | |||||
typedef float v4sf __attribute__((vector_size(16))); | |||||
typedef v2sf * pv2sf; | |||||
typedef v4sf * pv4sf; | |||||
extern int cpu_type; | |||||
int have_3dnow (void); | |||||
int have_sse (void); | |||||
void x86_3dnow_copyf (float *, const float *, int); | |||||
void x86_3dnow_add2f (float *, const float *, int); | |||||
void x86_sse_copyf (float *, const float *, int); | |||||
void x86_sse_add2f (float *, const float *, int); | |||||
void x86_sse_f2i (int *, const float *, int, float); | |||||
void x86_sse_i2f (float *, const int *, int, float); | |||||
#endif /* ARCH_X86 */ | |||||
void jack_port_set_funcs (void); | |||||
#endif /* __jack_intsimd_h__ */ | |||||
@@ -1,303 +0,0 @@ | |||||
/* | |||||
Based on gslist.c from glib-1.2.9 (LGPL). | |||||
Adaption to JACK, Copyright (C) 2002 Kai Vehmanen. | |||||
- replaced use of gtypes with normal ANSI C types | |||||
- glib's memery allocation routines replaced with | |||||
malloc/free calls | |||||
This program is free software; you can redistribute it and/or modify | |||||
it under the terms of the GNU Lesser General Public License as published by | |||||
the Free Software Foundation; either version 2.1 of the License, or | |||||
(at your option) any later version. | |||||
This program 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 Lesser General Public License for more details. | |||||
You should have received a copy of the GNU Lesser General Public License | |||||
along with this program; if not, write to the Free Software | |||||
Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. | |||||
*/ | |||||
#ifndef __jack_jslist_h__ | |||||
#define __jack_jslist_h__ | |||||
#include <stdlib.h> | |||||
typedef struct _JSList JSList; | |||||
typedef int (*JCompareFunc) (void* a, | |||||
void* b); | |||||
struct _JSList | |||||
{ | |||||
void *data; | |||||
JSList *next; | |||||
}; | |||||
static __inline__ | |||||
JSList* | |||||
jack_slist_alloc (void) | |||||
{ | |||||
JSList *new_list; | |||||
new_list = malloc(sizeof(JSList)); | |||||
new_list->data = NULL; | |||||
new_list->next = NULL; | |||||
return new_list; | |||||
} | |||||
static __inline__ | |||||
JSList* | |||||
jack_slist_prepend (JSList *list, | |||||
void *data) | |||||
{ | |||||
JSList *new_list; | |||||
new_list = malloc(sizeof(JSList)); | |||||
new_list->data = data; | |||||
new_list->next = list; | |||||
return new_list; | |||||
} | |||||
#define jack_slist_next(slist) ((slist) ? (((JSList *)(slist))->next) : NULL) | |||||
static __inline__ | |||||
JSList* | |||||
jack_slist_last (JSList *list) | |||||
{ | |||||
if (list) | |||||
{ | |||||
while (list->next) | |||||
list = list->next; | |||||
} | |||||
return list; | |||||
} | |||||
static __inline__ | |||||
JSList* | |||||
jack_slist_remove_link (JSList *list, | |||||
JSList *link) | |||||
{ | |||||
JSList *tmp; | |||||
JSList *prev; | |||||
prev = NULL; | |||||
tmp = list; | |||||
while (tmp) | |||||
{ | |||||
if (tmp == link) | |||||
{ | |||||
if (prev) | |||||
prev->next = tmp->next; | |||||
if (list == tmp) | |||||
list = list->next; | |||||
tmp->next = NULL; | |||||
break; | |||||
} | |||||
prev = tmp; | |||||
tmp = tmp->next; | |||||
} | |||||
return list; | |||||
} | |||||
static __inline__ | |||||
void | |||||
jack_slist_free (JSList *list) | |||||
{ | |||||
while (list) | |||||
{ | |||||
JSList *next = list->next; | |||||
free(list); | |||||
list = next; | |||||
} | |||||
} | |||||
static __inline__ | |||||
void | |||||
jack_slist_free_1 (JSList *list) | |||||
{ | |||||
if (list) | |||||
{ | |||||
free(list); | |||||
} | |||||
} | |||||
static __inline__ | |||||
JSList* | |||||
jack_slist_remove (JSList *list, | |||||
void *data) | |||||
{ | |||||
JSList *tmp; | |||||
JSList *prev; | |||||
prev = NULL; | |||||
tmp = list; | |||||
while (tmp) | |||||
{ | |||||
if (tmp->data == data) | |||||
{ | |||||
if (prev) | |||||
prev->next = tmp->next; | |||||
if (list == tmp) | |||||
list = list->next; | |||||
tmp->next = NULL; | |||||
jack_slist_free (tmp); | |||||
break; | |||||
} | |||||
prev = tmp; | |||||
tmp = tmp->next; | |||||
} | |||||
return list; | |||||
} | |||||
static __inline__ | |||||
unsigned int | |||||
jack_slist_length (JSList *list) | |||||
{ | |||||
unsigned int length; | |||||
length = 0; | |||||
while (list) | |||||
{ | |||||
length++; | |||||
list = list->next; | |||||
} | |||||
return length; | |||||
} | |||||
static __inline__ | |||||
JSList* | |||||
jack_slist_find (JSList *list, | |||||
void *data) | |||||
{ | |||||
while (list) | |||||
{ | |||||
if (list->data == data) | |||||
break; | |||||
list = list->next; | |||||
} | |||||
return list; | |||||
} | |||||
static __inline__ | |||||
JSList* | |||||
jack_slist_copy (JSList *list) | |||||
{ | |||||
JSList *new_list = NULL; | |||||
if (list) | |||||
{ | |||||
JSList *last; | |||||
new_list = jack_slist_alloc (); | |||||
new_list->data = list->data; | |||||
last = new_list; | |||||
list = list->next; | |||||
while (list) | |||||
{ | |||||
last->next = jack_slist_alloc (); | |||||
last = last->next; | |||||
last->data = list->data; | |||||
list = list->next; | |||||
} | |||||
} | |||||
return new_list; | |||||
} | |||||
static __inline__ | |||||
JSList* | |||||
jack_slist_append (JSList *list, | |||||
void *data) | |||||
{ | |||||
JSList *new_list; | |||||
JSList *last; | |||||
new_list = jack_slist_alloc (); | |||||
new_list->data = data; | |||||
if (list) | |||||
{ | |||||
last = jack_slist_last (list); | |||||
last->next = new_list; | |||||
return list; | |||||
} | |||||
else | |||||
return new_list; | |||||
} | |||||
static __inline__ | |||||
JSList* | |||||
jack_slist_sort_merge (JSList *l1, | |||||
JSList *l2, | |||||
JCompareFunc compare_func) | |||||
{ | |||||
JSList list, *l; | |||||
l=&list; | |||||
while (l1 && l2) | |||||
{ | |||||
if (compare_func(l1->data,l2->data) < 0) | |||||
{ | |||||
l=l->next=l1; | |||||
l1=l1->next; | |||||
} | |||||
else | |||||
{ | |||||
l=l->next=l2; | |||||
l2=l2->next; | |||||
} | |||||
} | |||||
l->next= l1 ? l1 : l2; | |||||
return list.next; | |||||
} | |||||
static __inline__ | |||||
JSList* | |||||
jack_slist_sort (JSList *list, | |||||
JCompareFunc compare_func) | |||||
{ | |||||
JSList *l1, *l2; | |||||
if (!list) | |||||
return NULL; | |||||
if (!list->next) | |||||
return list; | |||||
l1 = list; | |||||
l2 = list->next; | |||||
while ((l2 = l2->next) != NULL) | |||||
{ | |||||
if ((l2 = l2->next) == NULL) | |||||
break; | |||||
l1=l1->next; | |||||
} | |||||
l2 = l1->next; | |||||
l1->next = NULL; | |||||
return jack_slist_sort_merge (jack_slist_sort (list, compare_func), | |||||
jack_slist_sort (l2, compare_func), | |||||
compare_func); | |||||
} | |||||
#endif /* __jack_jslist_h__ */ |
@@ -1,115 +0,0 @@ | |||||
/* | |||||
Copyright (C) 1999-2000 Paul Davis | |||||
This program 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. | |||||
This program 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 this program; if not, write to the Free Software | |||||
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. | |||||
*/ | |||||
#ifndef __jack_memops_h__ | |||||
#define __jack_memops_h__ | |||||
#include <jack/types.h> | |||||
typedef enum { | |||||
None, | |||||
Rectangular, | |||||
Triangular, | |||||
Shaped | |||||
} DitherAlgorithm; | |||||
#define DITHER_BUF_SIZE 8 | |||||
#define DITHER_BUF_MASK 7 | |||||
typedef struct { | |||||
unsigned int depth; | |||||
float rm1; | |||||
unsigned int idx; | |||||
float e[DITHER_BUF_SIZE]; | |||||
} dither_state_t; | |||||
/* float functions */ | |||||
void sample_move_floatLE_sSs (jack_default_audio_sample_t *dst, char *src, unsigned long nsamples, unsigned long dst_skip); | |||||
void sample_move_dS_floatLE (char *dst, jack_default_audio_sample_t *src, unsigned long nsamples, unsigned long dst_skip, dither_state_t *state); | |||||
/* integer functions */ | |||||
void sample_move_d32u24_sSs (char *dst, jack_default_audio_sample_t *src, unsigned long nsamples, unsigned long dst_skip, dither_state_t *state); | |||||
void sample_move_d32u24_sS (char *dst, jack_default_audio_sample_t *src, unsigned long nsamples, unsigned long dst_skip, dither_state_t *state); | |||||
void sample_move_d24_sSs (char *dst, jack_default_audio_sample_t *src, unsigned long nsamples, unsigned long dst_skip, dither_state_t *state); | |||||
void sample_move_d24_sS (char *dst, jack_default_audio_sample_t *src, unsigned long nsamples, unsigned long dst_skip, dither_state_t *state); | |||||
void sample_move_d16_sSs (char *dst, jack_default_audio_sample_t *src, unsigned long nsamples, unsigned long dst_skip, dither_state_t *state); | |||||
void sample_move_d16_sS (char *dst, jack_default_audio_sample_t *src, unsigned long nsamples, unsigned long dst_skip, dither_state_t *state); | |||||
void sample_move_dither_rect_d32u24_sSs (char *dst, jack_default_audio_sample_t *src, unsigned long nsamples, unsigned long dst_skip, dither_state_t *state); | |||||
void sample_move_dither_rect_d32u24_sS (char *dst, jack_default_audio_sample_t *src, unsigned long nsamples, unsigned long dst_skip, dither_state_t *state); | |||||
void sample_move_dither_tri_d32u24_sSs (char *dst, jack_default_audio_sample_t *src, unsigned long nsamples, unsigned long dst_skip, dither_state_t *state); | |||||
void sample_move_dither_tri_d32u24_sS (char *dst, jack_default_audio_sample_t *src, unsigned long nsamples, unsigned long dst_skip, dither_state_t *state); | |||||
void sample_move_dither_shaped_d32u24_sSs (char *dst, jack_default_audio_sample_t *src, unsigned long nsamples, unsigned long dst_skip, dither_state_t *state); | |||||
void sample_move_dither_shaped_d32u24_sS (char *dst, jack_default_audio_sample_t *src, unsigned long nsamples, unsigned long dst_skip, dither_state_t *state); | |||||
void sample_move_dither_rect_d24_sSs (char *dst, jack_default_audio_sample_t *src, unsigned long nsamples, unsigned long dst_skip, dither_state_t *state); | |||||
void sample_move_dither_rect_d24_sS (char *dst, jack_default_audio_sample_t *src, unsigned long nsamples, unsigned long dst_skip, dither_state_t *state); | |||||
void sample_move_dither_tri_d24_sSs (char *dst, jack_default_audio_sample_t *src, unsigned long nsamples, unsigned long dst_skip, dither_state_t *state); | |||||
void sample_move_dither_tri_d24_sS (char *dst, jack_default_audio_sample_t *src, unsigned long nsamples, unsigned long dst_skip, dither_state_t *state); | |||||
void sample_move_dither_shaped_d24_sSs (char *dst, jack_default_audio_sample_t *src, unsigned long nsamples, unsigned long dst_skip, dither_state_t *state); | |||||
void sample_move_dither_shaped_d24_sS (char *dst, jack_default_audio_sample_t *src, unsigned long nsamples, unsigned long dst_skip, dither_state_t *state); | |||||
void sample_move_dither_rect_d16_sSs (char *dst, jack_default_audio_sample_t *src, unsigned long nsamples, unsigned long dst_skip, dither_state_t *state); | |||||
void sample_move_dither_rect_d16_sS (char *dst, jack_default_audio_sample_t *src, unsigned long nsamples, unsigned long dst_skip, dither_state_t *state); | |||||
void sample_move_dither_tri_d16_sSs (char *dst, jack_default_audio_sample_t *src, unsigned long nsamples, unsigned long dst_skip, dither_state_t *state); | |||||
void sample_move_dither_tri_d16_sS (char *dst, jack_default_audio_sample_t *src, unsigned long nsamples, unsigned long dst_skip, dither_state_t *state); | |||||
void sample_move_dither_shaped_d16_sSs (char *dst, jack_default_audio_sample_t *src, unsigned long nsamples, unsigned long dst_skip, dither_state_t *state); | |||||
void sample_move_dither_shaped_d16_sS (char *dst, jack_default_audio_sample_t *src, unsigned long nsamples, unsigned long dst_skip, dither_state_t *state); | |||||
void sample_move_dS_s32u24s (jack_default_audio_sample_t *dst, char *src, unsigned long nsamples, unsigned long src_skip); | |||||
void sample_move_dS_s32u24 (jack_default_audio_sample_t *dst, char *src, unsigned long nsamples, unsigned long src_skip); | |||||
void sample_move_dS_s24s (jack_default_audio_sample_t *dst, char *src, unsigned long nsamples, unsigned long src_skip); | |||||
void sample_move_dS_s24 (jack_default_audio_sample_t *dst, char *src, unsigned long nsamples, unsigned long src_skip); | |||||
void sample_move_dS_s16s (jack_default_audio_sample_t *dst, char *src, unsigned long nsamples, unsigned long src_skip); | |||||
void sample_move_dS_s16 (jack_default_audio_sample_t *dst, char *src, unsigned long nsamples, unsigned long src_skip); | |||||
void sample_merge_d16_sS (char *dst, jack_default_audio_sample_t *src, unsigned long nsamples, unsigned long dst_skip, dither_state_t *state); | |||||
void sample_merge_d32u24_sS (char *dst, jack_default_audio_sample_t *src, unsigned long nsamples, unsigned long dst_skip, dither_state_t *state); | |||||
static __inline__ void | |||||
sample_merge (jack_default_audio_sample_t *dst, jack_default_audio_sample_t *src, unsigned long cnt) | |||||
{ | |||||
while (cnt--) { | |||||
*dst += *src; | |||||
dst++; | |||||
src++; | |||||
} | |||||
} | |||||
static __inline__ void | |||||
sample_memcpy (jack_default_audio_sample_t *dst, jack_default_audio_sample_t *src, unsigned long cnt) | |||||
{ | |||||
memcpy (dst, src, cnt * sizeof (jack_default_audio_sample_t)); | |||||
} | |||||
void memset_interleave (char *dst, char val, unsigned long bytes, unsigned long unit_bytes, unsigned long skip_bytes); | |||||
void memcpy_fake (char *dst, char *src, unsigned long src_bytes, unsigned long foo, unsigned long bar); | |||||
void memcpy_interleave_d16_s16 (char *dst, char *src, unsigned long src_bytes, unsigned long dst_skip_bytes, unsigned long src_skip_bytes); | |||||
void memcpy_interleave_d24_s24 (char *dst, char *src, unsigned long src_bytes, unsigned long dst_skip_bytes, unsigned long src_skip_bytes); | |||||
void memcpy_interleave_d32_s32 (char *dst, char *src, unsigned long src_bytes, unsigned long dst_skip_bytes, unsigned long src_skip_bytes); | |||||
void merge_memcpy_interleave_d16_s16 (char *dst, char *src, unsigned long src_bytes, unsigned long dst_skip_bytes, unsigned long src_skip_bytes); | |||||
void merge_memcpy_interleave_d24_s24 (char *dst, char *src, unsigned long src_bytes, unsigned long dst_skip_bytes, unsigned long src_skip_bytes); | |||||
void merge_memcpy_interleave_d32_s32 (char *dst, char *src, unsigned long src_bytes, unsigned long dst_skip_bytes, unsigned long src_skip_bytes); | |||||
void merge_memcpy_d16_s16 (char *dst, char *src, unsigned long src_bytes, unsigned long foo, unsigned long bar); | |||||
void merge_memcpy_d32_s32 (char *dst, char *src, unsigned long src_bytes, unsigned long foo, unsigned long bar); | |||||
#endif /* __jack_memops_h__ */ |
@@ -1,44 +0,0 @@ | |||||
/* | |||||
* messagebuffer.h -- realtime-safe message interface for jackd. | |||||
* | |||||
* This function is included in libjack so backend drivers can use | |||||
* it, *not* for external client processes. The VERBOSE() and | |||||
* MESSAGE() macros are realtime-safe. | |||||
*/ | |||||
/* | |||||
* Copyright (C) 2004 Rui Nuno Capela, Steve Harris | |||||
* | |||||
* This program is free software; you can redistribute it and/or modify | |||||
* it under the terms of the GNU Lesser General Public License as published by | |||||
* the Free Software Foundation; either version 2.1 of the License, or | |||||
* (at your option) any later version. | |||||
* | |||||
* This program 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 Lesser General Public License for more details. | |||||
* | |||||
* You should have received a copy of the GNU Lesser General Public License | |||||
* along with this program; if not, write to the Free Software | |||||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. | |||||
* | |||||
*/ | |||||
#ifndef __jack_messagebuffer_h__ | |||||
#define __jack_messagebuffer_h__ | |||||
#define MESSAGE(fmt,args...) jack_messagebuffer_add(fmt , ##args) | |||||
#define VERBOSE(engine,fmt,args...) \ | |||||
if ((engine)->verbose) \ | |||||
jack_messagebuffer_add(fmt , ##args) | |||||
void jack_messagebuffer_init(); | |||||
void jack_messagebuffer_exit(); | |||||
void jack_message_buffer_thread_init (void (*cb)(void*), void*); | |||||
void jack_messagebuffer_add(const char *fmt, ...); | |||||
void jack_messagebuffer_thread_init (void (*cb)(void*), void* arg); | |||||
#endif /* __jack_messagebuffer_h__ */ |
@@ -1,174 +0,0 @@ | |||||
/* | |||||
Copyright (C) 2004 Ian Esten | |||||
This program is free software; you can redistribute it and/or modify | |||||
it under the terms of the GNU Lesser General Public License as published by | |||||
the Free Software Foundation; either version 2.1 of the License, or | |||||
(at your option) any later version. | |||||
This program 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 Lesser General Public License for more details. | |||||
You should have received a copy of the GNU Lesser General Public License | |||||
along with this program; if not, write to the Free Software | |||||
Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. | |||||
*/ | |||||
#ifndef __JACK_MIDIPORT_H | |||||
#define __JACK_MIDIPORT_H | |||||
#ifdef __cplusplus | |||||
extern "C" { | |||||
#endif | |||||
#include <jack/weakmacros.h> | |||||
#include <jack/types.h> | |||||
#include <stdlib.h> | |||||
/** Type for raw event data contained in @ref jack_midi_event_t. */ | |||||
typedef unsigned char jack_midi_data_t; | |||||
/** A Jack MIDI event. */ | |||||
typedef struct _jack_midi_event | |||||
{ | |||||
jack_nframes_t time; /**< Sample index at which event is valid */ | |||||
size_t size; /**< Number of bytes of data in \a buffer */ | |||||
jack_midi_data_t *buffer; /**< Raw MIDI data */ | |||||
} jack_midi_event_t; | |||||
/** | |||||
* @defgroup MIDIAPI Reading and writing MIDI data | |||||
* @{ | |||||
*/ | |||||
/* Get number of events in a port buffer. | |||||
* | |||||
* @param port_buffer Port buffer from which to retrieve event. | |||||
* @return number of events inside @a port_buffer | |||||
*/ | |||||
jack_nframes_t | |||||
jack_midi_get_event_count(void* port_buffer) JACK_OPTIONAL_WEAK_EXPORT; | |||||
/** Get a MIDI event from an event port buffer. | |||||
* | |||||
* Jack MIDI is normalised, the MIDI event returned by this function is | |||||
* guaranteed to be a complete MIDI event (the status byte will always be | |||||
* present, and no realtime events will interspered with the event). | |||||
* | |||||
* @param event Event structure to store retrieved event in. | |||||
* @param port_buffer Port buffer from which to retrieve event. | |||||
* @param event_index Index of event to retrieve. | |||||
* @return 0 on success, ENODATA if buffer is empty. | |||||
*/ | |||||
int | |||||
jack_midi_event_get(jack_midi_event_t *event, | |||||
void *port_buffer, | |||||
uint32_t event_index) JACK_OPTIONAL_WEAK_EXPORT; | |||||
/** Clear an event buffer. | |||||
* | |||||
* This should be called at the beginning of each process cycle before calling | |||||
* @ref jack_midi_event_reserve or @ref jack_midi_event_write. This | |||||
* function may not be called on an input port's buffer. | |||||
* | |||||
* @param port_buffer Port buffer to clear (must be an output port buffer). | |||||
*/ | |||||
void | |||||
jack_midi_clear_buffer(void *port_buffer) JACK_OPTIONAL_WEAK_EXPORT; | |||||
/** Get the size of the largest event that can be stored by the port. | |||||
* | |||||
* This function returns the current space available, taking into account | |||||
* events already stored in the port. | |||||
* | |||||
* @param port_buffer Port buffer to check size of. | |||||
*/ | |||||
size_t | |||||
jack_midi_max_event_size(void* port_buffer) JACK_OPTIONAL_WEAK_EXPORT; | |||||
/** Allocate space for an event to be written to an event port buffer. | |||||
* | |||||
* Clients are to write the actual event data to be written starting at the | |||||
* pointer returned by this function. Clients must not write more than | |||||
* @a data_size bytes into this buffer. Clients must write normalised | |||||
* MIDI data to the port - no running status and no (1-byte) realtime | |||||
* messages interspersed with other messages (realtime messages are fine | |||||
* when they occur on their own, like other messages). | |||||
* | |||||
* Events must be written in order, sorted by their sample offsets. | |||||
* JACK will not sort the events for you, and will refuse to store | |||||
* out-of-order events. | |||||
* | |||||
* @param port_buffer Buffer to write event to. | |||||
* @param time Sample offset of event. | |||||
* @param data_size Length of event's raw data in bytes. | |||||
* @return Pointer to the beginning of the reserved event's data buffer, or | |||||
* NULL on error (ie not enough space). | |||||
*/ | |||||
jack_midi_data_t* | |||||
jack_midi_event_reserve(void *port_buffer, | |||||
jack_nframes_t time, | |||||
size_t data_size) JACK_OPTIONAL_WEAK_EXPORT; | |||||
/** Write an event into an event port buffer. | |||||
* | |||||
* This function is simply a wrapper for @ref jack_midi_event_reserve | |||||
* which writes the event data into the space reserved in the buffer. | |||||
* | |||||
* Clients must not write more than | |||||
* @a data_size bytes into this buffer. Clients must write normalised | |||||
* MIDI data to the port - no running status and no (1-byte) realtime | |||||
* messages interspersed with other messages (realtime messages are fine | |||||
* when they occur on their own, like other messages). | |||||
* | |||||
* Events must be written in order, sorted by their sample offsets. | |||||
* JACK will not sort the events for you, and will refuse to store | |||||
* out-of-order events. | |||||
* | |||||
* @param port_buffer Buffer to write event to. | |||||
* @param time Sample offset of event. | |||||
* @param data Message data to be written. | |||||
* @param data_size Length of @a data in bytes. | |||||
* @return 0 on success, ENOBUFS if there's not enough space in buffer for event. | |||||
*/ | |||||
int | |||||
jack_midi_event_write(void *port_buffer, | |||||
jack_nframes_t time, | |||||
const jack_midi_data_t *data, | |||||
size_t data_size) JACK_OPTIONAL_WEAK_EXPORT; | |||||
/** Get the number of events that could not be written to @a port_buffer. | |||||
* | |||||
* This function returning a non-zero value implies @a port_buffer is full. | |||||
* Currently the only way this can happen is if events are lost on port mixdown. | |||||
* | |||||
* @param port_buffer Port to receive count for. | |||||
* @returns Number of events that could not be written to @a port_buffer. | |||||
*/ | |||||
uint32_t | |||||
jack_midi_get_lost_event_count(void *port_buffer) JACK_OPTIONAL_WEAK_EXPORT; | |||||
/*@}*/ | |||||
#ifdef __cplusplus | |||||
} | |||||
#endif | |||||
#endif /* __JACK_MIDIPORT_H */ | |||||
@@ -1,28 +0,0 @@ | |||||
/* | |||||
Copyright (C) 2001 Paul Davis | |||||
This program is free software; you can redistribute it and/or modify | |||||
it under the terms of the GNU Lesser General Public License as published by | |||||
the Free Software Foundation; either version 2.1 of the License, or | |||||
(at your option) any later version. | |||||
This program 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 Lesser General Public License for more details. | |||||
You should have received a copy of the GNU Lesser General Public License | |||||
along with this program; if not, write to the Free Software | |||||
Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. | |||||
*/ | |||||
#ifndef __jack_pool_h__ | |||||
#define __jack_pool_h__ | |||||
#include <sys/types.h> | |||||
void * jack_pool_alloc (size_t bytes); | |||||
void jack_pool_release (void *); | |||||
#endif /* __jack_pool_h__ */ |
@@ -1,188 +0,0 @@ | |||||
/* | |||||
Copyright (C) 2001 Paul Davis | |||||
This program is free software; you can redistribute it and/or modify | |||||
it under the terms of the GNU Lesser General Public License as published by | |||||
the Free Software Foundation; either version 2.1 of the License, or | |||||
(at your option) any later version. | |||||
This program 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 Lesser General Public License for more details. | |||||
You should have received a copy of the GNU Lesser General Public License | |||||
along with this program; if not, write to the Free Software | |||||
Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. | |||||
*/ | |||||
#ifndef __jack_port_h__ | |||||
#define __jack_port_h__ | |||||
#include <pthread.h> | |||||
#include <jack/types.h> | |||||
#include <jack/jslist.h> | |||||
#include <jack/shm.h> | |||||
#define JACK_PORT_NAME_SIZE 256 | |||||
#define JACK_PORT_TYPE_SIZE 32 | |||||
/* The relatively low value of this constant reflects the fact that | |||||
* JACK currently only knows about *2* port types. (May 2006) | |||||
* | |||||
* Further, the 4 covers: | |||||
* - a single non-negotiated audio format | |||||
* - music data (ie. MIDI) | |||||
* - video | |||||
* - one other | |||||
* | |||||
* which is probably enough for more than just the foreseeable future. | |||||
*/ | |||||
#define JACK_MAX_PORT_TYPES 4 | |||||
#define JACK_AUDIO_PORT_TYPE 0 | |||||
#define JACK_MIDI_PORT_TYPE 1 | |||||
/* these should probably go somewhere else, but not in <jack/types.h> */ | |||||
#define JACK_CLIENT_NAME_SIZE 33 | |||||
typedef uint32_t jack_client_id_t; | |||||
/* JACK shared memory segments are limited to MAX_INT32, they can be | |||||
* shared between 32-bit and 64-bit clients. | |||||
*/ | |||||
#define JACK_SHM_MAX (MAX_INT32) | |||||
typedef int32_t jack_port_type_id_t; | |||||
#define JACK_BACKEND_ALIAS "system" | |||||
#ifndef POST_PACKED_STRUCTURE | |||||
#ifdef __GNUC__ | |||||
/* POST_PACKED_STRUCTURE needs to be a macro which | |||||
expands into a compiler directive. The directive must | |||||
tell the compiler to arrange the preceding structure | |||||
declaration so that it is packed on byte-boundaries rather | |||||
than use the natural alignment of the processor and/or | |||||
compiler. | |||||
*/ | |||||
#define POST_PACKED_STRUCTURE __attribute__((__packed__)) | |||||
#else | |||||
/* Add other things here for non-gcc platforms */ | |||||
#endif | |||||
#endif | |||||
/* Port type structure. | |||||
* | |||||
* (1) One for each port type is part of the engine's jack_control_t | |||||
* shared memory structure. | |||||
* | |||||
* (2) One for each port type is appended to the engine's | |||||
* jack_client_connect_result_t response. The client reads them into | |||||
* its local memory, using them to attach the corresponding shared | |||||
* memory segments. | |||||
*/ | |||||
typedef struct _jack_port_type_info { | |||||
jack_port_type_id_t ptype_id; | |||||
const char type_name[JACK_PORT_TYPE_SIZE]; | |||||
/* If == 1, then a buffer to handle nframes worth of data has | |||||
* sizeof(jack_default_audio_sample_t) * nframes bytes. | |||||
* | |||||
* If > 1, the buffer allocated for input mixing will be | |||||
* this value times sizeof(jack_default_audio_sample_t) | |||||
* * nframes bytes in size. For non-audio data types, | |||||
* it may have a different value. | |||||
* | |||||
* If < 0, the value should be ignored, and buffer_size | |||||
* should be used. | |||||
*/ | |||||
int32_t buffer_scale_factor; | |||||
/* ignored unless buffer_scale_factor is < 0. see above */ | |||||
jack_shmsize_t buffer_size; | |||||
jack_shm_registry_index_t shm_registry_index; | |||||
jack_shmsize_t zero_buffer_offset; | |||||
} POST_PACKED_STRUCTURE jack_port_type_info_t; | |||||
/* Allocated by the engine in shared memory. */ | |||||
typedef struct _jack_port_shared { | |||||
jack_port_type_id_t ptype_id; /* index into port type array */ | |||||
jack_shmsize_t offset; /* buffer offset in shm segment */ | |||||
jack_port_id_t id; /* index into engine port array */ | |||||
uint32_t flags; | |||||
char name[JACK_CLIENT_NAME_SIZE+JACK_PORT_NAME_SIZE]; | |||||
char alias1[JACK_CLIENT_NAME_SIZE+JACK_PORT_NAME_SIZE]; | |||||
char alias2[JACK_CLIENT_NAME_SIZE+JACK_PORT_NAME_SIZE]; | |||||
jack_client_id_t client_id; /* who owns me */ | |||||
volatile jack_nframes_t latency; | |||||
volatile jack_nframes_t total_latency; | |||||
volatile jack_latency_range_t playback_latency; | |||||
volatile jack_latency_range_t capture_latency; | |||||
volatile uint8_t monitor_requests; | |||||
char has_mixdown; /* port has a mixdown function */ | |||||
char in_use; | |||||
char unused; /* legacy locked field */ | |||||
} POST_PACKED_STRUCTURE jack_port_shared_t; | |||||
typedef struct _jack_port_functions { | |||||
/* Function to initialize port buffer. Cannot be NULL. | |||||
* NOTE: This must take a buffer rather than jack_port_t as it is called | |||||
* in jack_engine_place_buffers() before any port creation. | |||||
* A better solution is to make jack_engine_place_buffers to be type-specific, | |||||
* but this works. | |||||
*/ | |||||
void (*buffer_init)(void *buffer, size_t size, jack_nframes_t); | |||||
/* Function to mixdown multiple inputs to a buffer. Can be NULL, | |||||
* indicating that multiple input connections are not legal for | |||||
* this data type. | |||||
*/ | |||||
void (*mixdown)(jack_port_t *, jack_nframes_t); | |||||
} jack_port_functions_t; | |||||
/** | |||||
* Get port functions. | |||||
* @param ptid port type id. | |||||
* | |||||
* @return pointer to port type functions or NULL if port type is unknown. | |||||
*/ | |||||
/*const*/ jack_port_functions_t * | |||||
jack_get_port_functions(jack_port_type_id_t ptid); | |||||
/* Allocated by the client in local memory. */ | |||||
struct _jack_port { | |||||
void **client_segment_base; | |||||
void *mix_buffer; | |||||
jack_port_type_info_t *type_info; /* shared memory type info */ | |||||
struct _jack_port_shared *shared; /* corresponding shm struct */ | |||||
struct _jack_port *tied; /* locally tied source port */ | |||||
jack_port_functions_t fptr; | |||||
pthread_mutex_t connection_lock; | |||||
JSList *connections; | |||||
}; | |||||
/* Inline would be cleaner, but it needs to be fast even in | |||||
* non-optimized code. jack_output_port_buffer() only handles output | |||||
* ports. jack_port_buffer() works for both input and output ports. | |||||
*/ | |||||
#define jack_port_buffer(p) \ | |||||
((void *) ((p)->mix_buffer? (p)->mix_buffer: \ | |||||
*(p)->client_segment_base + (p)->shared->offset)) | |||||
#define jack_output_port_buffer(p) \ | |||||
((void *) (*(p)->client_segment_base + (p)->shared->offset)) | |||||
/* not for use by JACK applications */ | |||||
size_t jack_port_type_buffer_size (jack_port_type_info_t* port_type_info, jack_nframes_t nframes); | |||||
#endif /* __jack_port_h__ */ | |||||
@@ -1,235 +0,0 @@ | |||||
/* | |||||
Copyright (C) 2000 Paul Davis | |||||
Copyright (C) 2003 Rohan Drape | |||||
This program is free software; you can redistribute it and/or modify | |||||
it under the terms of the GNU Lesser General Public License as published by | |||||
the Free Software Foundation; either version 2.1 of the License, or | |||||
(at your option) any later version. | |||||
This program 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 Lesser General Public License for more details. | |||||
You should have received a copy of the GNU Lesser General Public License | |||||
along with this program; if not, write to the Free Software | |||||
Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. | |||||
*/ | |||||
#ifndef _RINGBUFFER_H | |||||
#define _RINGBUFFER_H | |||||
#ifdef __cplusplus | |||||
extern "C" { | |||||
#endif | |||||
#include <sys/types.h> | |||||
/** @file ringbuffer.h | |||||
* | |||||
* A set of library functions to make lock-free ringbuffers available | |||||
* to JACK clients. The `capture_client.c' (in the example_clients | |||||
* directory) is a fully functioning user of this API. | |||||
* | |||||
* The key attribute of a ringbuffer is that it can be safely accessed | |||||
* by two threads simultaneously -- one reading from the buffer and | |||||
* the other writing to it -- without using any synchronization or | |||||
* mutual exclusion primitives. For this to work correctly, there can | |||||
* only be a single reader and a single writer thread. Their | |||||
* identities cannot be interchanged. | |||||
*/ | |||||
typedef struct | |||||
{ | |||||
char *buf; | |||||
size_t len; | |||||
} | |||||
jack_ringbuffer_data_t ; | |||||
typedef struct | |||||
{ | |||||
char *buf; | |||||
volatile size_t write_ptr; | |||||
volatile size_t read_ptr; | |||||
size_t size; | |||||
size_t size_mask; | |||||
int mlocked; | |||||
} | |||||
jack_ringbuffer_t ; | |||||
/** | |||||
* Allocates a ringbuffer data structure of a specified size. The | |||||
* caller must arrange for a call to jack_ringbuffer_free() to release | |||||
* the memory associated with the ringbuffer. | |||||
* | |||||
* @param sz the ringbuffer size in bytes. | |||||
* | |||||
* @return a pointer to a new jack_ringbuffer_t, if successful; NULL | |||||
* otherwise. | |||||
*/ | |||||
jack_ringbuffer_t *jack_ringbuffer_create(size_t sz); | |||||
/** | |||||
* Frees the ringbuffer data structure allocated by an earlier call to | |||||
* jack_ringbuffer_create(). | |||||
* | |||||
* @param rb a pointer to the ringbuffer structure. | |||||
*/ | |||||
void jack_ringbuffer_free(jack_ringbuffer_t *rb); | |||||
/** | |||||
* Fill a data structure with a description of the current readable | |||||
* data held in the ringbuffer. This description is returned in a two | |||||
* element array of jack_ringbuffer_data_t. Two elements are needed | |||||
* because the data to be read may be split across the end of the | |||||
* ringbuffer. | |||||
* | |||||
* The first element will always contain a valid @a len field, which | |||||
* may be zero or greater. If the @a len field is non-zero, then data | |||||
* can be read in a contiguous fashion using the address given in the | |||||
* corresponding @a buf field. | |||||
* | |||||
* If the second element has a non-zero @a len field, then a second | |||||
* contiguous stretch of data can be read from the address given in | |||||
* its corresponding @a buf field. | |||||
* | |||||
* @param rb a pointer to the ringbuffer structure. | |||||
* @param vec a pointer to a 2 element array of jack_ringbuffer_data_t. | |||||
* | |||||
*/ | |||||
void jack_ringbuffer_get_read_vector(const jack_ringbuffer_t *rb, | |||||
jack_ringbuffer_data_t *vec); | |||||
/** | |||||
* Fill a data structure with a description of the current writable | |||||
* space in the ringbuffer. The description is returned in a two | |||||
* element array of jack_ringbuffer_data_t. Two elements are needed | |||||
* because the space available for writing may be split across the end | |||||
* of the ringbuffer. | |||||
* | |||||
* The first element will always contain a valid @a len field, which | |||||
* may be zero or greater. If the @a len field is non-zero, then data | |||||
* can be written in a contiguous fashion using the address given in | |||||
* the corresponding @a buf field. | |||||
* | |||||
* If the second element has a non-zero @a len field, then a second | |||||
* contiguous stretch of data can be written to the address given in | |||||
* the corresponding @a buf field. | |||||
* | |||||
* @param rb a pointer to the ringbuffer structure. | |||||
* @param vec a pointer to a 2 element array of jack_ringbuffer_data_t. | |||||
*/ | |||||
void jack_ringbuffer_get_write_vector(const jack_ringbuffer_t *rb, | |||||
jack_ringbuffer_data_t *vec); | |||||
/** | |||||
* Read data from the ringbuffer. | |||||
* | |||||
* @param rb a pointer to the ringbuffer structure. | |||||
* @param dest a pointer to a buffer where data read from the | |||||
* ringbuffer will go. | |||||
* @param cnt the number of bytes to read. | |||||
* | |||||
* @return the number of bytes read, which may range from 0 to cnt. | |||||
*/ | |||||
size_t jack_ringbuffer_read(jack_ringbuffer_t *rb, char *dest, size_t cnt); | |||||
/** | |||||
* Read data from the ringbuffer. Opposed to jack_ringbuffer_read() | |||||
* this function does not move the read pointer. Thus it's | |||||
* a convenient way to inspect data in the ringbuffer in a | |||||
* continous fashion. The price is that the data is copied | |||||
* into a user provided buffer. For "raw" non-copy inspection | |||||
* of the data in the ringbuffer use jack_ringbuffer_get_read_vector(). | |||||
* | |||||
* @param rb a pointer to the ringbuffer structure. | |||||
* @param dest a pointer to a buffer where data read from the | |||||
* ringbuffer will go. | |||||
* @param cnt the number of bytes to read. | |||||
* | |||||
* @return the number of bytes read, which may range from 0 to cnt. | |||||
*/ | |||||
size_t jack_ringbuffer_peek(jack_ringbuffer_t *rb, char *dest, size_t cnt); | |||||
/** | |||||
* Advance the read pointer. | |||||
* | |||||
* After data have been read from the ringbuffer using the pointers | |||||
* returned by jack_ringbuffer_get_read_vector(), use this function to | |||||
* advance the buffer pointers, making that space available for future | |||||
* write operations. | |||||
* | |||||
* @param rb a pointer to the ringbuffer structure. | |||||
* @param cnt the number of bytes read. | |||||
*/ | |||||
void jack_ringbuffer_read_advance(jack_ringbuffer_t *rb, size_t cnt); | |||||
/** | |||||
* Return the number of bytes available for reading. | |||||
* | |||||
* @param rb a pointer to the ringbuffer structure. | |||||
* | |||||
* @return the number of bytes available to read. | |||||
*/ | |||||
size_t jack_ringbuffer_read_space(const jack_ringbuffer_t *rb); | |||||
/** | |||||
* Lock a ringbuffer data block into memory. | |||||
* | |||||
* Uses the mlock() system call. This is not a realtime operation. | |||||
* | |||||
* @param rb a pointer to the ringbuffer structure. | |||||
*/ | |||||
int jack_ringbuffer_mlock(jack_ringbuffer_t *rb); | |||||
/** | |||||
* Reset the read and write pointers, making an empty buffer. | |||||
* | |||||
* This is not thread safe. | |||||
* | |||||
* @param rb a pointer to the ringbuffer structure. | |||||
*/ | |||||
void jack_ringbuffer_reset(jack_ringbuffer_t *rb); | |||||
/** | |||||
* Write data into the ringbuffer. | |||||
* | |||||
* @param rb a pointer to the ringbuffer structure. | |||||
* @param src a pointer to the data to be written to the ringbuffer. | |||||
* @param cnt the number of bytes to write. | |||||
* | |||||
* @return the number of bytes write, which may range from 0 to cnt | |||||
*/ | |||||
size_t jack_ringbuffer_write(jack_ringbuffer_t *rb, const char *src, | |||||
size_t cnt); | |||||
/** | |||||
* Advance the write pointer. | |||||
* | |||||
* After data have been written the ringbuffer using the pointers | |||||
* returned by jack_ringbuffer_get_write_vector(), use this function | |||||
* to advance the buffer pointer, making the data available for future | |||||
* read operations. | |||||
* | |||||
* @param rb a pointer to the ringbuffer structure. | |||||
* @param cnt the number of bytes written. | |||||
*/ | |||||
void jack_ringbuffer_write_advance(jack_ringbuffer_t *rb, size_t cnt); | |||||
/** | |||||
* Return the number of bytes available for writing. | |||||
* | |||||
* @param rb a pointer to the ringbuffer structure. | |||||
* | |||||
* @return the amount of free space (in bytes) available for writing. | |||||
*/ | |||||
size_t jack_ringbuffer_write_space(const jack_ringbuffer_t *rb); | |||||
#ifdef __cplusplus | |||||
} | |||||
#endif | |||||
#endif |
@@ -1,22 +0,0 @@ | |||||
#ifndef __jack_sanitycheck_h__ | |||||
#define __jack_sanitycheck_h__ | |||||
/** | |||||
* GPL etc. | |||||
* | |||||
* @author Florian Faber | |||||
* | |||||
* @version 0.1 (2009-01-17) [FF] | |||||
* - initial version | |||||
**/ | |||||
/** | |||||
* Performs a range of sanity checks on the system. The number of | |||||
* found problems is returned. | |||||
* | |||||
**/ | |||||
int sanitycheck (int do_realtime_check, | |||||
int do_freqscaling_check); | |||||
#endif /* __jack_sanitycheck_h__ */ |
@@ -1,289 +0,0 @@ | |||||
/* | |||||
Copyright (C) 2001 Paul Davis | |||||
Copyright (C) 2004 Jack O'Quin | |||||
Copyright (C) 2010 Torben Hohn | |||||
This program is free software; you can redistribute it and/or modify | |||||
it under the terms of the GNU Lesser General Public License as published by | |||||
the Free Software Foundation; either version 2.1 of the License, or | |||||
(at your option) any later version. | |||||
This program 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 Lesser General Public License for more details. | |||||
You should have received a copy of the GNU Lesser General Public License | |||||
along with this program; if not, write to the Free Software | |||||
Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. | |||||
*/ | |||||
#ifndef __jack_session_h__ | |||||
#define __jack_session_h__ | |||||
#ifdef __cplusplus | |||||
extern "C" { | |||||
#endif | |||||
#include <jack/types.h> | |||||
#include <jack/weakmacros.h> | |||||
/** | |||||
* @defgroup SessionClientFunctions Session API for clients. | |||||
* @{ | |||||
*/ | |||||
/** | |||||
* Session event type. | |||||
* | |||||
* if a client cant save templates, i might just do a normal save. | |||||
* | |||||
* There is no "quit without saving" event because a client might refuse to | |||||
* quit when it has unsaved data, but other clients may have already quit. | |||||
* This results in too much confusion, so it is unsupported. | |||||
*/ | |||||
enum JackSessionEventType { | |||||
/** | |||||
* Save the session completely. | |||||
* | |||||
* The client may save references to data outside the provided directory, | |||||
* but it must do so by creating a link inside the provided directory and | |||||
* referring to that in any save files. The client must not refer to data | |||||
* files outside the provided directory directly in save files, because | |||||
* this makes it impossible for the session manager to create a session | |||||
* archive for distribution or archival. | |||||
*/ | |||||
JackSessionSave = 1, | |||||
/** | |||||
* Save the session completly, then quit. | |||||
* | |||||
* The rules for saving are exactly the same as for JackSessionSave. | |||||
*/ | |||||
JackSessionSaveAndQuit = 2, | |||||
/** | |||||
* Save a session template. | |||||
* | |||||
* A session template is a "skeleton" of the session, but without any data. | |||||
* Clients must save a session that, when restored, will create the same | |||||
* ports as a full save would have. However, the actual data contained in | |||||
* the session may not be saved (e.g. a DAW would create the necessary | |||||
* tracks, but not save the actual recorded data). | |||||
*/ | |||||
JackSessionSaveTemplate = 3 | |||||
}; | |||||
typedef enum JackSessionEventType jack_session_event_type_t; | |||||
/** | |||||
* @ref jack_session_flags_t bits | |||||
*/ | |||||
enum JackSessionFlags { | |||||
/** | |||||
* An error occured while saving. | |||||
*/ | |||||
JackSessionSaveError = 0x01, | |||||
/** | |||||
* Client needs to be run in a terminal. | |||||
*/ | |||||
JackSessionNeedTerminal = 0x02 | |||||
}; | |||||
/** | |||||
* Session flags. | |||||
*/ | |||||
typedef enum JackSessionFlags jack_session_flags_t; | |||||
struct _jack_session_event { | |||||
/** | |||||
* The type of this session event. | |||||
*/ | |||||
jack_session_event_type_t type; | |||||
/** | |||||
* Session directory path, with trailing separator. | |||||
* | |||||
* This directory is exclusive to the client; when saving the client may | |||||
* create any files it likes in this directory. | |||||
*/ | |||||
const char *session_dir; | |||||
/** | |||||
* Client UUID which must be passed to jack_client_open on session load. | |||||
* | |||||
* The client can specify this in the returned command line, or save it | |||||
* in a state file within the session directory. | |||||
*/ | |||||
const char *client_uuid; | |||||
/** | |||||
* Reply (set by client): the command line needed to restore the client. | |||||
* | |||||
* This is a platform dependent command line. It must contain | |||||
* ${SESSION_DIR} instead of the actual session directory path. More | |||||
* generally, just as in session files, clients should not include any | |||||
* paths outside the session directory here as this makes | |||||
* archival/distribution impossible. | |||||
* | |||||
* This field is set to NULL by Jack when the event is delivered to the | |||||
* client. The client must set to allocated memory that is safe to | |||||
* free(). This memory will be freed by jack_session_event_free. | |||||
*/ | |||||
char *command_line; | |||||
/** | |||||
* Reply (set by client): Session flags. | |||||
*/ | |||||
jack_session_flags_t flags; | |||||
/** | |||||
* Future flags. Set to zero for now. | |||||
*/ | |||||
uint32_t future; | |||||
}; | |||||
typedef struct _jack_session_event jack_session_event_t; | |||||
/** | |||||
* Prototype for the client supplied function that is called | |||||
* whenever a session notification is sent via jack_session_notify(). | |||||
* | |||||
* Ownership of the memory of @a event is passed to the application. | |||||
* It must be freed using jack_session_event_free when its not used anymore. | |||||
* | |||||
* The client must promptly call jack_session_reply for this event. | |||||
* | |||||
* @param event The event structure. | |||||
* @param arg Pointer to a client supplied structure. | |||||
*/ | |||||
typedef void (*JackSessionCallback)(jack_session_event_t *event, | |||||
void *arg); | |||||
/** | |||||
* Tell the JACK server to call @a session_callback when a session event | |||||
* is to be delivered. | |||||
* | |||||
* setting more than one session_callback per process is probably a design | |||||
* error. if you have a multiclient application its more sensible to create | |||||
* a jack_client with only a session callback set. | |||||
* | |||||
* @return 0 on success, otherwise a non-zero error code | |||||
*/ | |||||
int jack_set_session_callback (jack_client_t *client, | |||||
JackSessionCallback session_callback, | |||||
void *arg) JACK_WEAK_EXPORT; | |||||
/** | |||||
* Reply to a session event. | |||||
* | |||||
* This can either be called directly from the callback, or later from a | |||||
* different thread. For example, it is possible to push the event through a | |||||
* queue and execute the save code from the GUI thread. | |||||
* | |||||
* @return 0 on success, otherwise a non-zero error code | |||||
*/ | |||||
int jack_session_reply (jack_client_t *client, | |||||
jack_session_event_t *event) JACK_WEAK_EXPORT; | |||||
/** | |||||
* free memory used by a jack_session_event_t | |||||
* this also frees the memory used by the command_line pointer. | |||||
* if its non NULL. | |||||
*/ | |||||
void jack_session_event_free (jack_session_event_t *event) JACK_WEAK_EXPORT; | |||||
/** | |||||
* get the assigned uuid for client. | |||||
* safe to call from callback and all other threads. | |||||
* memory needs to be freed. | |||||
*/ | |||||
char *jack_client_get_uuid (jack_client_t *client) JACK_WEAK_EXPORT; | |||||
/** | |||||
* @} | |||||
*/ | |||||
/** | |||||
* @defgroup JackSessionManagerAPI API for a session manager. | |||||
* | |||||
* @{ | |||||
*/ | |||||
typedef struct { | |||||
const char *uuid; | |||||
const char *client_name; | |||||
const char *command; | |||||
jack_session_flags_t flags; | |||||
} jack_session_command_t; | |||||
/** | |||||
* Send an event to all clients listening for session callbacks. | |||||
* | |||||
* The returned strings of the clients are accumulated and returned as an array | |||||
* of jack_session_command_t. its terminated by ret[i].uuid == NULL target == | |||||
* NULL means send to all interested clients. otherwise a clientname | |||||
*/ | |||||
jack_session_command_t *jack_session_notify ( | |||||
jack_client_t* client, | |||||
const char *target, | |||||
jack_session_event_type_t type, | |||||
const char *path) JACK_WEAK_EXPORT; | |||||
/** | |||||
* Free the memory allocated by a session command. | |||||
*/ | |||||
void jack_session_commands_free (jack_session_command_t *cmds) JACK_WEAK_EXPORT; | |||||
/** | |||||
* Get the session ID for a client name. | |||||
* The session manager needs this to reassociate a client name to the session_id. | |||||
*/ | |||||
char *jack_get_uuid_for_client_name (jack_client_t *client, | |||||
const char *client_name) JACK_WEAK_EXPORT; | |||||
/** | |||||
* Get the client name for a session_id. | |||||
* | |||||
* In order to snapshot the graph connections, the session manager needs to map | |||||
* session_ids to client names. | |||||
*/ | |||||
char *jack_get_client_name_by_uuid (jack_client_t *client, | |||||
const char *client_uuid ) JACK_WEAK_EXPORT; | |||||
/** | |||||
* Reserve a client name and associate it with a UUID. | |||||
* | |||||
* When a client later calls jack_client_open() and specifies the UUID, jackd | |||||
* will assign the reserved name. This allows a session manager to know in | |||||
* advance under which client name its managed clients will appear. | |||||
* | |||||
* @return 0 on success, otherwise a non-zero error code | |||||
*/ | |||||
int | |||||
jack_reserve_client_name (jack_client_t *client, | |||||
const char *name, | |||||
const char *uuid) JACK_WEAK_EXPORT; | |||||
/** | |||||
* Find out whether a client has set up a session callback. | |||||
* | |||||
* @return 0 when the client has no session callback, 1 when it has one. | |||||
* -1 on error. | |||||
*/ | |||||
int | |||||
jack_client_has_session_callback (jack_client_t *client, const char *client_name) JACK_WEAK_EXPORT; | |||||
/** | |||||
* @} | |||||
*/ | |||||
#ifdef __cplusplus | |||||
} | |||||
#endif | |||||
#endif |
@@ -1,110 +0,0 @@ | |||||
#ifndef __jack_shm_h__ | |||||
#define __jack_shm_h__ | |||||
#include <limits.h> | |||||
#include <sys/types.h> | |||||
#include <jack/types.h> | |||||
#define MAX_SERVERS 8 /* maximum concurrent servers */ | |||||
#define MAX_SHM_ID 256 /* generally about 16 per server */ | |||||
#define JACK_SERVER_NAME_SIZE 256 /* maximum length of server name */ | |||||
#define JACK_SHM_MAGIC 0x4a41434b /* shm magic number: "JACK" */ | |||||
#define JACK_SHM_NULL_INDEX -1 /* NULL SHM index */ | |||||
#define JACK_SHM_REGISTRY_INDEX -2 /* pseudo SHM index for registry */ | |||||
/* On Mac OS X, SHM_NAME_MAX is the maximum length of a shared memory | |||||
* segment name (instead of NAME_MAX or PATH_MAX as defined by the | |||||
* standard). | |||||
*/ | |||||
#ifdef USE_POSIX_SHM | |||||
#ifndef SHM_NAME_MAX | |||||
#define SHM_NAME_MAX NAME_MAX | |||||
#endif | |||||
typedef char shm_name_t[SHM_NAME_MAX]; | |||||
typedef shm_name_t jack_shm_id_t; | |||||
#else /* System V SHM */ | |||||
typedef int jack_shm_id_t; | |||||
#endif /* SHM type */ | |||||
/* shared memory type */ | |||||
typedef enum { | |||||
shm_POSIX = 1, /* POSIX shared memory */ | |||||
shm_SYSV = 2 /* System V shared memory */ | |||||
} jack_shmtype_t; | |||||
typedef int16_t jack_shm_registry_index_t; | |||||
/** | |||||
* A structure holding information about shared memory allocated by | |||||
* JACK. this persists across invocations of JACK, and can be used by | |||||
* multiple JACK servers. It contains no pointers and is valid across | |||||
* address spaces. | |||||
* | |||||
* The registry consists of two parts: a header including an array of | |||||
* server names, followed by an array of segment registry entries. | |||||
*/ | |||||
typedef struct _jack_shm_server { | |||||
pid_t pid; /* process ID */ | |||||
char name[JACK_SERVER_NAME_SIZE]; | |||||
} jack_shm_server_t; | |||||
typedef struct _jack_shm_header { | |||||
uint32_t magic; /* magic number */ | |||||
uint16_t protocol; /* JACK protocol version */ | |||||
jack_shmtype_t type; /* shm type */ | |||||
jack_shmsize_t size; /* total registry segment size */ | |||||
jack_shmsize_t hdr_len; /* size of header */ | |||||
jack_shmsize_t entry_len; /* size of registry entry */ | |||||
jack_shm_server_t server[MAX_SERVERS]; /* current server array */ | |||||
} jack_shm_header_t; | |||||
typedef struct _jack_shm_registry { | |||||
jack_shm_registry_index_t index; /* offset into the registry */ | |||||
pid_t allocator; /* PID that created shm segment */ | |||||
jack_shmsize_t size; /* for POSIX unattach */ | |||||
jack_shm_id_t id; /* API specific, see above */ | |||||
} jack_shm_registry_t; | |||||
#define JACK_SHM_REGISTRY_SIZE (sizeof (jack_shm_header_t) \ | |||||
+ sizeof (jack_shm_registry_t) * MAX_SHM_ID) | |||||
/** | |||||
* a structure holding information about shared memory | |||||
* allocated by JACK. this version is valid only | |||||
* for a given address space. It contains a pointer | |||||
* indicating where the shared memory has been | |||||
* attached to the address space. | |||||
*/ | |||||
typedef struct _jack_shm_info { | |||||
jack_shm_registry_index_t index; /* offset into the registry */ | |||||
void *attached_at; /* address where attached */ | |||||
} jack_shm_info_t; | |||||
/* utility functions used only within JACK */ | |||||
extern void jack_shm_copy_from_registry (jack_shm_info_t*, | |||||
jack_shm_registry_index_t); | |||||
extern void jack_shm_copy_to_registry (jack_shm_info_t*, | |||||
jack_shm_registry_index_t*); | |||||
extern void jack_release_shm_info (jack_shm_registry_index_t); | |||||
static inline char* jack_shm_addr (jack_shm_info_t* si) { | |||||
return si->attached_at; | |||||
} | |||||
/* here beginneth the API */ | |||||
extern int jack_register_server (const char *server_name, int new_registry); | |||||
extern void jack_unregister_server (const char *server_name); | |||||
extern int jack_initialize_shm (const char *server_name); | |||||
extern int jack_cleanup_shm (void); | |||||
extern int jack_shmalloc (jack_shmsize_t size, jack_shm_info_t* result); | |||||
extern void jack_release_shm (jack_shm_info_t*); | |||||
extern void jack_destroy_shm (jack_shm_info_t*); | |||||
extern int jack_attach_shm (jack_shm_info_t*); | |||||
extern int jack_resize_shm (jack_shm_info_t*, jack_shmsize_t size); | |||||
#endif /* __jack_shm_h__ */ |
@@ -1,21 +0,0 @@ | |||||
/* | |||||
Copyright (C) 2002 Fernando Lopez-Lezcano | |||||
This program 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. | |||||
This program 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 this program; if not, write to the Free Software | |||||
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. | |||||
*/ | |||||
#define PIPE_READ_FD (3) | |||||
#define PIPE_WRITE_FD (4) |
@@ -1,56 +0,0 @@ | |||||
/* | |||||
* Copyright (C) 2004 Rui Nuno Capela, Lee Revell | |||||
* | |||||
* This program is free software; you can redistribute it and/or | |||||
* modify it under the terms of the GNU Lesser General Public License | |||||
* as published by the Free Software Foundation; either version 2.1 | |||||
* of the License, or (at your option) any later version. | |||||
* | |||||
* This program 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 | |||||
* Lesser General Public License for more details. | |||||
* | |||||
* You should have received a copy of the GNU Lesser General Public | |||||
* License along with this program; if not, write to the Free | |||||
* Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA | |||||
* 02111-1307, USA. | |||||
* | |||||
*/ | |||||
#ifndef __statistics_h__ | |||||
#define __statistics_h__ | |||||
#ifdef __cplusplus | |||||
extern "C" { | |||||
#endif | |||||
#include <jack/types.h> | |||||
/** | |||||
* @return the maximum delay reported by the backend since | |||||
* startup or reset. When compared to the period size in usecs, this | |||||
* can be used to estimate the ideal period size for a given setup. | |||||
*/ | |||||
float jack_get_max_delayed_usecs (jack_client_t *client); | |||||
/** | |||||
* @return the delay in microseconds due to the most recent XRUN | |||||
* occurrence. This probably only makes sense when called from a @ref | |||||
* JackXRunCallback defined using jack_set_xrun_callback(). | |||||
*/ | |||||
float jack_get_xrun_delayed_usecs (jack_client_t *client); | |||||
/** | |||||
* Reset the maximum delay counter. This would be useful | |||||
* to estimate the effect that a change to the configuration of a running | |||||
* system (e.g. toggling kernel preemption) has on the delay | |||||
* experienced by JACK, without having to restart the JACK engine. | |||||
*/ | |||||
void jack_reset_max_delayed_usecs (jack_client_t *client); | |||||
#ifdef __cplusplus | |||||
} | |||||
#endif | |||||
#endif /* __statistics_h__ */ |
@@ -1,97 +0,0 @@ | |||||
#ifndef __jack_systemtest_h__ | |||||
#define __jack_systemtest_h__ | |||||
/** | |||||
* GPL, yabbadabba | |||||
* | |||||
* Set of functions to gather system information for the jack setup wizard. | |||||
* | |||||
* @author Florian Faber, faber@faberman.de | |||||
* | |||||
* @version 0.1 (2009-01-15) [FF] | |||||
* - initial version | |||||
* | |||||
**/ | |||||
/** | |||||
* This function checks for the existence of known frequency scaling mechanisms | |||||
* in this system. | |||||
* | |||||
* @returns 0 if the system has no frequency scaling capabilities non-0 otherwise. | |||||
**/ | |||||
int system_has_frequencyscaling(); | |||||
/** | |||||
* This function determines wether the CPU has a variable clock speed if frequency | |||||
* scaling is available. | |||||
* | |||||
* @returns 0 if system doesn't use frequency scaling at the moment, non-0 otherwise | |||||
**/ | |||||
int system_uses_frequencyscaling(); | |||||
/*** | |||||
* Checks for a definition in /etc/security/limits.conf that looks | |||||
* as if it allows RT scheduling priority. | |||||
* | |||||
* @returns 1 if there appears to be such a line | |||||
**/ | |||||
int system_has_rtprio_limits_conf (); | |||||
/** | |||||
* Checks for the existence of the 'audio' group on this system | |||||
* | |||||
* @returns 0 is there is no 'audio' group, non-0 otherwise | |||||
**/ | |||||
int system_has_audiogroup(); | |||||
/** | |||||
* Tests wether the owner of this process is in the 'audio' group. | |||||
* | |||||
* @returns 0 if the owner of this process is not in the audio group, non-0 otherwise | |||||
**/ | |||||
int system_user_in_audiogroup(); | |||||
/** | |||||
* Determines wether the owner of this process can enable rt priority. | |||||
* | |||||
* @returns 0 if this process can not be switched to rt prio, non-0 otherwise | |||||
**/ | |||||
int system_user_can_rtprio(); | |||||
long long unsigned int system_memlock_amount(); | |||||
/** | |||||
* Checks wether the memlock limit is unlimited | |||||
* | |||||
* @returns 0 if the memlock limit is limited, non-0 otherwise | |||||
**/ | |||||
int system_memlock_is_unlimited(); | |||||
long long unsigned int system_available_physical_mem(); | |||||
/** | |||||
* Gets the version of the currently running kernel | |||||
* | |||||
* @returns String with the full version of the kernel | |||||
**/ | |||||
char* system_kernel_version(); | |||||
/** | |||||
* Returns the username. The caller is in charge of disposal of | |||||
* the returned name. | |||||
* | |||||
* @returns Pointer to a username or NULL | |||||
**/ | |||||
char* system_get_username(); | |||||
#endif /* __jack_systemtest_h__ */ |
@@ -1,135 +0,0 @@ | |||||
/* | |||||
Copyright (C) 2004 Paul Davis | |||||
This program is free software; you can redistribute it and/or modify | |||||
it under the terms of the GNU Lesser General Public License as published by | |||||
the Free Software Foundation; either version 2.1 of the License, or | |||||
(at your option) any later version. | |||||
This program 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 Lesser General Public License for more details. | |||||
You should have received a copy of the GNU Lesser General Public License | |||||
along with this program; if not, write to the Free Software | |||||
Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. | |||||
*/ | |||||
#ifndef __jack_thread_h__ | |||||
#define __jack_thread_h__ | |||||
#ifdef __cplusplus | |||||
extern "C" { | |||||
#endif | |||||
#include <pthread.h> | |||||
#include <jack/weakmacros.h> | |||||
/* use 512KB stack per thread - the default is way too high to be feasible | |||||
* with mlockall() on many systems */ | |||||
#define THREAD_STACK 524288 | |||||
/** @file thread.h | |||||
* | |||||
* Library functions to standardize thread creation for JACK and its | |||||
* clients. These interfaces hide some system variations in the | |||||
* handling of realtime scheduling and associated privileges. | |||||
*/ | |||||
/** | |||||
* @defgroup ClientThreads Creating and managing client threads | |||||
* @{ | |||||
*/ | |||||
/** | |||||
* @returns if JACK is running with realtime scheduling, this returns | |||||
* the priority that any JACK-created client threads will run at. | |||||
* Otherwise returns -1. | |||||
*/ | |||||
int jack_client_real_time_priority (jack_client_t*) JACK_OPTIONAL_WEAK_EXPORT; | |||||
/** | |||||
* @returns if JACK is running with realtime scheduling, this returns | |||||
* the maximum priority that a JACK client thread should use if the thread | |||||
* is subject to realtime scheduling. Otherwise returns -1. | |||||
*/ | |||||
int jack_client_max_real_time_priority (jack_client_t*) JACK_OPTIONAL_WEAK_EXPORT; | |||||
/** | |||||
* Attempt to enable realtime scheduling for a thread. On some | |||||
* systems that may require special privileges. | |||||
* | |||||
* @param thread POSIX thread ID. | |||||
* @param priority requested thread priority. | |||||
* | |||||
* @returns 0, if successful; EPERM, if the calling process lacks | |||||
* required realtime privileges; otherwise some other error number. | |||||
*/ | |||||
int jack_acquire_real_time_scheduling (jack_native_thread_t thread, int priority) JACK_OPTIONAL_WEAK_EXPORT; | |||||
/** | |||||
* Create a thread for JACK or one of its clients. The thread is | |||||
* created executing @a start_routine with @a arg as its sole | |||||
* argument. | |||||
* | |||||
* @param client the JACK client for whom the thread is being created. May be | |||||
* NULL if the client is being created within the JACK server. | |||||
* @param thread place to return POSIX thread ID. | |||||
* @param priority thread priority, if realtime. | |||||
* @param realtime true for the thread to use realtime scheduling. On | |||||
* some systems that may require special privileges. | |||||
* @param start_routine function the thread calls when it starts. | |||||
* @param arg parameter passed to the @a start_routine. | |||||
* | |||||
* @returns 0, if successful; otherwise some error number. | |||||
*/ | |||||
int jack_client_create_thread (jack_client_t* client, | |||||
jack_native_thread_t *thread, | |||||
int priority, | |||||
int realtime, /* boolean */ | |||||
void *(*start_routine)(void*), | |||||
void *arg) JACK_OPTIONAL_WEAK_EXPORT; | |||||
/** | |||||
* Drop realtime scheduling for a thread. | |||||
* | |||||
* @param thread POSIX thread ID. | |||||
* | |||||
* @returns 0, if successful; otherwise an error number. | |||||
*/ | |||||
int jack_drop_real_time_scheduling (jack_native_thread_t thread) JACK_OPTIONAL_WEAK_EXPORT; | |||||
typedef int (*jack_thread_creator_t)(jack_native_thread_t*, | |||||
const pthread_attr_t*, | |||||
void* (*function)(void*), | |||||
void* arg) JACK_OPTIONAL_WEAK_EXPORT; | |||||
/** | |||||
* This function can be used in very very specialized cases | |||||
* where it is necessary that client threads created by JACK | |||||
* are created by something other than pthread_create(). After | |||||
* it is used, any threads that JACK needs for the client will | |||||
* will be created by calling the function passed to this | |||||
* function. | |||||
* | |||||
* No normal application/client should consider calling this. | |||||
* The specific case for which it was created involves running | |||||
* win32/x86 plugins under Wine on Linux, where it is necessary | |||||
* that all threads that might call win32 functions are known | |||||
* to Wine. | |||||
* | |||||
* @param creator a function that creates a new thread | |||||
* | |||||
*/ | |||||
void jack_set_thread_creator (jack_thread_creator_t creator) JACK_OPTIONAL_WEAK_EXPORT; | |||||
/* @} */ | |||||
#ifdef __cplusplus | |||||
} | |||||
#endif | |||||
#endif /* __jack_thread_h__ */ |
@@ -1,40 +0,0 @@ | |||||
/* | |||||
Copyright (C) 2002 Paul Davis | |||||
This program is free software; you can redistribute it and/or modify | |||||
it under the terms of the GNU Lesser General Public License as published by | |||||
the Free Software Foundation; either version 2.1 of the License, or | |||||
(at your option) any later version. | |||||
This program 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 Lesser General Public License for more details. | |||||
You should have received a copy of the GNU Lesser General Public License | |||||
along with this program; if not, write to the Free Software | |||||
Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. | |||||
*/ | |||||
#ifndef __jack_timestamps_h__ | |||||
#define __jack_timestamps_h__ | |||||
#include <stdio.h> | |||||
#ifdef __cplusplus | |||||
extern "C" { | |||||
#endif | |||||
void jack_init_timestamps (unsigned long howmany); | |||||
void jack_timestamp (const char *what); | |||||
void jack_dump_timestamps (FILE *out); | |||||
void jack_reset_timestamps (); | |||||
#ifdef __cplusplus | |||||
} | |||||
#endif | |||||
#endif /* __jack_timestamps_h__ */ | |||||
@@ -1,544 +0,0 @@ | |||||
/* | |||||
Copyright (C) 2002 Paul Davis | |||||
Copyright (C) 2003 Jack O'Quin | |||||
This program is free software; you can redistribute it and/or modify | |||||
it under the terms of the GNU Lesser General Public License as published by | |||||
the Free Software Foundation; either version 2.1 of the License, or | |||||
(at your option) any later version. | |||||
This program 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 Lesser General Public License for more details. | |||||
You should have received a copy of the GNU Lesser General Public License | |||||
along with this program; if not, write to the Free Software | |||||
Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. | |||||
*/ | |||||
#ifndef __jack_transport_h__ | |||||
#define __jack_transport_h__ | |||||
#ifdef __cplusplus | |||||
extern "C" { | |||||
#endif | |||||
#include <jack/types.h> | |||||
#include <jack/weakmacros.h> | |||||
#ifndef POST_PACKED_STRUCTURE | |||||
#ifdef __GNUC__ | |||||
/* POST_PACKED_STRUCTURE needs to be a macro which | |||||
expands into a compiler directive. The directive must | |||||
tell the compiler to arrange the preceding structure | |||||
declaration so that it is packed on byte-boundaries rather | |||||
than use the natural alignment of the processor and/or | |||||
compiler. | |||||
*/ | |||||
#define POST_PACKED_STRUCTURE __attribute__((__packed__)) | |||||
#else | |||||
/* Add other things here for non-gcc platforms */ | |||||
#endif | |||||
#endif | |||||
/** | |||||
* Transport states. | |||||
*/ | |||||
typedef enum { | |||||
/* the order matters for binary compatibility */ | |||||
JackTransportStopped = 0, /**< Transport halted */ | |||||
JackTransportRolling = 1, /**< Transport playing */ | |||||
JackTransportLooping = 2, /**< For OLD_TRANSPORT, now ignored */ | |||||
JackTransportStarting = 3 /**< Waiting for sync ready */ | |||||
} jack_transport_state_t; | |||||
typedef uint64_t jack_unique_t; /**< Unique ID (opaque) */ | |||||
/** | |||||
* Optional struct jack_position_t fields. | |||||
*/ | |||||
typedef enum { | |||||
JackPositionBBT = 0x10, /**< Bar, Beat, Tick */ | |||||
JackPositionTimecode = 0x20, /**< External timecode */ | |||||
JackBBTFrameOffset = 0x40, /**< Frame offset of BBT information */ | |||||
JackAudioVideoRatio = 0x80, /**< audio frames per video frame */ | |||||
JackVideoFrameOffset = 0x100 /**< frame offset of first video frame */ | |||||
} jack_position_bits_t; | |||||
/** all valid position bits */ | |||||
#define JACK_POSITION_MASK (JackPositionBBT|JackPositionTimecode|JackBBTFrameOffset|JackAudioVideoRatio|JackVideoFrameOffset) | |||||
#define EXTENDED_TIME_INFO | |||||
/** | |||||
* Struct for transport position information. | |||||
*/ | |||||
typedef struct { | |||||
/*@{*/ | |||||
/** @name Server-set fields | |||||
* these cannot be set from clients; the server sets them */ | |||||
jack_unique_t unique_1; /**< unique ID */ | |||||
jack_time_t usecs; /**< microsecond timestamp that is guaranteed to be | |||||
monotonic, but not neccessarily | |||||
linear. | |||||
The absolute value is | |||||
implementation-dependent (i.e. it | |||||
could be wall-clock, time since | |||||
jack started, uptime, etc). */ | |||||
jack_nframes_t frame_rate; /**< current frame rate, in frames per second */ | |||||
/*}@*/ | |||||
/*@{*/ | |||||
/** @name Mandatory fields | |||||
*/ | |||||
jack_nframes_t frame; /**< frame number, always present/required. | |||||
This is the frame number on the | |||||
transport timeline, which is not | |||||
the same as what @ref | |||||
jack_frame_time returns. */ | |||||
jack_position_bits_t valid; /**< which other fields are valid, as a | |||||
bitmask constructed from values in | |||||
\ref jack_position_bits_t */ | |||||
/*}@*/ | |||||
/*@{*/ | |||||
/** @name JackPositionBBT fields | |||||
* Bar:Beat.Tick-related information. | |||||
* | |||||
* Applications that support | |||||
* JackPositionBBT are encouraged to also fill the JackBBTFrameOffset | |||||
*/ | |||||
int32_t bar; /**< current bar | |||||
Should be >0: the first bar is | |||||
bar '1'. */ | |||||
int32_t beat; /**< current beat-within-bar | |||||
Should be >0 and <=beats_per_bar: | |||||
the first beat is beat '1'. | |||||
*/ | |||||
int32_t tick; /**< current tick-within-beat | |||||
Should be >0 and <=ticks_per_beat: | |||||
the first tick is tick '0'. */ | |||||
double bar_start_tick; /**< number of ticks that have elapsed | |||||
between frame 0 and the first beat | |||||
of the current measure. */ | |||||
float beats_per_bar; /**< time signature "numerator" */ | |||||
float beat_type; /**< time signature "denominator" */ | |||||
double ticks_per_beat; /**< number of ticks within a bar. | |||||
Usually a moderately large integer | |||||
with many denominators, such as | |||||
1920.0 */ | |||||
double beats_per_minute; /**< BPM, quantized to block size. This | |||||
means when the tempo is not constant | |||||
within this block, the BPM value should | |||||
adapted to compensate for this. This | |||||
is different from most fields in this | |||||
struct, which specify the value at | |||||
the beginning of the block rather | |||||
than an average.*/ | |||||
/*}@*/ | |||||
/*@{*/ | |||||
/** @name JackPositionTimecode fields | |||||
* EXPERIMENTAL: could change */ | |||||
double frame_time; /**< current time in seconds */ | |||||
double next_time; /**< next sequential frame_time | |||||
(unless repositioned) */ | |||||
/*}@*/ | |||||
/*@{*/ | |||||
/* JackBBTFrameOffset fields */ | |||||
jack_nframes_t bbt_offset; /**< frame offset for the BBT fields | |||||
(the given bar, beat, and tick | |||||
values actually refer to a time | |||||
frame_offset frames before the | |||||
start of the cycle), should | |||||
be assumed to be 0 if | |||||
JackBBTFrameOffset is not | |||||
set. If JackBBTFrameOffset is | |||||
set and this value is zero, the BBT | |||||
time refers to the first frame of this | |||||
cycle. If the value is positive, | |||||
the BBT time refers to a frame that | |||||
many frames before the start of the | |||||
cycle. */ | |||||
/*}@*/ | |||||
/*@{*/ | |||||
/* JACK video positional data | |||||
* EXPERIMENTAL: could change */ | |||||
float audio_frames_per_video_frame; /**< number of audio frames | |||||
per video frame. Should be assumed | |||||
zero if JackAudioVideoRatio is not | |||||
set. If JackAudioVideoRatio is set | |||||
and the value is zero, no video | |||||
data exists within the JACK graph */ | |||||
jack_nframes_t video_offset; /**< audio frame at which the first video | |||||
frame in this cycle occurs. Should | |||||
be assumed to be 0 if JackVideoFrameOffset | |||||
is not set. If JackVideoFrameOffset is | |||||
set, but the value is zero, there is | |||||
no video frame within this cycle. */ | |||||
/*}@*/ | |||||
/*@{*/ | |||||
/** @name Other fields */ | |||||
/* For binary compatibility, new fields should be allocated from | |||||
* this padding area with new valid bits controlling access, so | |||||
* the existing structure size and offsets are preserved. */ | |||||
int32_t padding[7]; | |||||
/*}@*/ | |||||
/* When (unique_1 == unique_2) the contents are consistent. */ | |||||
jack_unique_t unique_2; /**< unique ID */ | |||||
} POST_PACKED_STRUCTURE jack_position_t; | |||||
/** | |||||
* @defgroup TransportControl Transport and Timebase control | |||||
* @{ | |||||
*/ | |||||
/** | |||||
* Called by the timebase master to release itself from that | |||||
* responsibility. | |||||
* | |||||
* If the timebase master releases the timebase or leaves the JACK | |||||
* graph for any reason, the JACK engine takes over at the start of | |||||
* the next process cycle. The transport state does not change. If | |||||
* rolling, it continues to play, with frame numbers as the only | |||||
* available position information. | |||||
* | |||||
* @see jack_set_timebase_callback | |||||
* | |||||
* @param client the JACK client structure. | |||||
* | |||||
* @return 0 on success, otherwise a non-zero error code. | |||||
*/ | |||||
int jack_release_timebase (jack_client_t *client) JACK_OPTIONAL_WEAK_EXPORT; | |||||
/** | |||||
* Prototype for the @a sync_callback defined by @ref slowsyncclients | |||||
* "slow-sync clients". When the client is active, this callback is | |||||
* invoked just before process() in the same thread. This occurs once | |||||
* after registration, then subsequently whenever some client requests | |||||
* a new position, or the transport enters the ::JackTransportStarting | |||||
* state. This realtime function must not wait. | |||||
* | |||||
* The transport @a state will be: | |||||
* | |||||
* - ::JackTransportStopped when a new position is requested; | |||||
* - ::JackTransportStarting when the transport is waiting to start; | |||||
* - ::JackTransportRolling when the timeout has expired, and the | |||||
* position is now a moving target. | |||||
* | |||||
* @param state current transport state. | |||||
* @param pos new transport position. | |||||
* @param arg the argument supplied by jack_set_sync_callback(). | |||||
* | |||||
* @return TRUE (non-zero) when ready to roll. | |||||
*/ | |||||
typedef int (*JackSyncCallback)(jack_transport_state_t state, | |||||
jack_position_t *pos, | |||||
void *arg); | |||||
/** | |||||
* Register (or unregister) as a @ref slowsyncclients "slow-sync client", that cannot | |||||
* respond immediately to transport position changes. | |||||
* | |||||
* The @a sync_callback will be invoked at the first available | |||||
* opportunity after its registration is complete. If the client is | |||||
* currently active this will be the following process cycle, | |||||
* otherwise it will be the first cycle after calling jack_activate(). | |||||
* After that, it runs according to the ::JackSyncCallback rules. | |||||
* Clients that don't set a @a sync_callback are assumed to be ready | |||||
* immediately any time the transport wants to start. | |||||
* | |||||
* @param client the JACK client structure. | |||||
* @param sync_callback is a realtime function that returns TRUE when | |||||
* the client is ready. Setting @a sync_callback to NULL declares that | |||||
* this client no longer requires slow-sync processing. | |||||
* @param arg an argument for the @a sync_callback function. | |||||
* | |||||
* @return 0 on success, otherwise a non-zero error code. | |||||
*/ | |||||
int jack_set_sync_callback (jack_client_t *client, | |||||
JackSyncCallback sync_callback, | |||||
void *arg) JACK_OPTIONAL_WEAK_EXPORT; | |||||
/** | |||||
* Set the timeout value for @ref slowsyncclients "slow-sync clients". | |||||
* | |||||
* This timeout prevents unresponsive slow-sync clients from | |||||
* completely halting the transport mechanism. The default is two | |||||
* seconds. When the timeout expires, the transport starts rolling, | |||||
* even if some slow-sync clients are still unready. The @a | |||||
* sync_callbacks of these clients continue being invoked, giving them | |||||
* a chance to catch up. | |||||
* | |||||
* @see jack_set_sync_callback | |||||
* | |||||
* @param client the JACK client structure. | |||||
* @param timeout is delay (in microseconds) before the timeout expires. | |||||
* | |||||
* @return 0 on success, otherwise a non-zero error code. | |||||
*/ | |||||
int jack_set_sync_timeout (jack_client_t *client, | |||||
jack_time_t timeout) JACK_OPTIONAL_WEAK_EXPORT; | |||||
/** | |||||
* Prototype for the @a timebase_callback used to provide extended | |||||
* position information. Its output affects all of the following | |||||
* process cycle. This realtime function must not wait. | |||||
* | |||||
* This function is called immediately after process() in the same | |||||
* thread whenever the transport is rolling, or when any client has | |||||
* requested a new position in the previous cycle. The first cycle | |||||
* after jack_set_timebase_callback() is also treated as a new | |||||
* position, or the first cycle after jack_activate() if the client | |||||
* had been inactive. | |||||
* | |||||
* The timebase master may not use its @a pos argument to set @a | |||||
* pos->frame. To change position, use jack_transport_reposition() or | |||||
* jack_transport_locate(). These functions are realtime-safe, the @a | |||||
* timebase_callback can call them directly. | |||||
* | |||||
* @param state current transport state. | |||||
* @param nframes number of frames in current period. | |||||
* @param pos address of the position structure for the next cycle; @a | |||||
* pos->frame will be its frame number. If @a new_pos is FALSE, this | |||||
* structure contains extended position information from the current | |||||
* cycle. If TRUE, it contains whatever was set by the requester. | |||||
* The @a timebase_callback's task is to update the extended | |||||
* information here. | |||||
* @param new_pos TRUE (non-zero) for a newly requested @a pos, or for | |||||
* the first cycle after the @a timebase_callback is defined. | |||||
* @param arg the argument supplied by jack_set_timebase_callback(). | |||||
*/ | |||||
typedef void (*JackTimebaseCallback)(jack_transport_state_t state, | |||||
jack_nframes_t nframes, | |||||
jack_position_t *pos, | |||||
int new_pos, | |||||
void *arg); | |||||
/** | |||||
* Register as timebase master for the JACK subsystem. | |||||
* | |||||
* The timebase master registers a callback that updates extended | |||||
* position information such as beats or timecode whenever necessary. | |||||
* Without this extended information, there is no need for this | |||||
* function. | |||||
* | |||||
* There is never more than one master at a time. When a new client | |||||
* takes over, the former @a timebase_callback is no longer called. | |||||
* Taking over the timebase may be done conditionally, so it fails if | |||||
* there was a master already. | |||||
* | |||||
* The method may be called whether the client has been activated or not. | |||||
* | |||||
* @param client the JACK client structure. | |||||
* @param conditional non-zero for a conditional request. | |||||
* @param timebase_callback is a realtime function that returns | |||||
* position information. | |||||
* @param arg an argument for the @a timebase_callback function. | |||||
* | |||||
* @return | |||||
* - 0 on success; | |||||
* - EBUSY if a conditional request fails because there was already a | |||||
* timebase master; | |||||
* - other non-zero error code. | |||||
*/ | |||||
int jack_set_timebase_callback (jack_client_t *client, | |||||
int conditional, | |||||
JackTimebaseCallback timebase_callback, | |||||
void *arg) JACK_OPTIONAL_WEAK_EXPORT; | |||||
/** | |||||
* Reposition the transport to a new frame number. | |||||
* | |||||
* May be called at any time by any client. The new position takes | |||||
* effect in two process cycles. If there are @ref slowsyncclients | |||||
* "slow-sync clients" and the transport is already rolling, it will | |||||
* enter the ::JackTransportStarting state and begin invoking their @a | |||||
* sync_callbacks until ready. This function is realtime-safe. | |||||
* | |||||
* @see jack_transport_reposition, jack_set_sync_callback | |||||
* | |||||
* @param client the JACK client structure. | |||||
* @param frame frame number of new transport position. | |||||
* | |||||
* @return 0 if valid request, non-zero otherwise. | |||||
*/ | |||||
int jack_transport_locate (jack_client_t *client, | |||||
jack_nframes_t frame) JACK_OPTIONAL_WEAK_EXPORT; | |||||
/** | |||||
* Query the current transport state and position. | |||||
* | |||||
* This function is realtime-safe, and can be called from any thread. | |||||
* If called from the process thread, @a pos corresponds to the first | |||||
* frame of the current cycle and the state returned is valid for the | |||||
* entire cycle. | |||||
* | |||||
* @param client the JACK client structure. | |||||
* @param pos pointer to structure for returning current transport | |||||
* position; @a pos->valid will show which fields contain valid data. | |||||
* If @a pos is NULL, do not return position information. | |||||
* | |||||
* @return Current transport state. | |||||
*/ | |||||
jack_transport_state_t jack_transport_query (const jack_client_t *client, | |||||
jack_position_t *pos) JACK_OPTIONAL_WEAK_EXPORT; | |||||
/** | |||||
* Return an estimate of the current transport frame, | |||||
* including any time elapsed since the last transport | |||||
* positional update. | |||||
* | |||||
* @param client the JACK client structure | |||||
*/ | |||||
jack_nframes_t jack_get_current_transport_frame (const jack_client_t *client) JACK_OPTIONAL_WEAK_EXPORT; | |||||
/** | |||||
* Request a new transport position. | |||||
* | |||||
* May be called at any time by any client. The new position takes | |||||
* effect in two process cycles. If there are @ref slowsyncclients | |||||
* "slow-sync clients" and the transport is already rolling, it will | |||||
* enter the ::JackTransportStarting state and begin invoking their @a | |||||
* sync_callbacks until ready. This function is realtime-safe. | |||||
* | |||||
* @see jack_transport_locate, jack_set_sync_callback | |||||
* | |||||
* @param client the JACK client structure. | |||||
* @param pos requested new transport position. Fill pos->valid to specify | |||||
* which fields should be taken into account. If you mark a set of fields | |||||
* as valid, you are expected to fill them all. | |||||
* | |||||
* @return 0 if valid request, EINVAL if position structure rejected. | |||||
*/ | |||||
int jack_transport_reposition (jack_client_t *client, | |||||
const jack_position_t *pos) JACK_OPTIONAL_WEAK_EXPORT; | |||||
/** | |||||
* Start the JACK transport rolling. | |||||
* | |||||
* Any client can make this request at any time. It takes effect no | |||||
* sooner than the next process cycle, perhaps later if there are | |||||
* @ref slowsyncclients "slow-sync clients". This function is realtime-safe. | |||||
* | |||||
* @see jack_set_sync_callback | |||||
* | |||||
* @param client the JACK client structure. | |||||
*/ | |||||
void jack_transport_start (jack_client_t *client) JACK_OPTIONAL_WEAK_EXPORT; | |||||
/** | |||||
* Stop the JACK transport. | |||||
* | |||||
* Any client can make this request at any time. It takes effect on | |||||
* the next process cycle. This function is realtime-safe. | |||||
* | |||||
* @param client the JACK client structure. | |||||
*/ | |||||
void jack_transport_stop (jack_client_t *client) JACK_OPTIONAL_WEAK_EXPORT; | |||||
/*@}*/ | |||||
/********************************************************************* | |||||
* The following interfaces are DEPRECATED. They are only provided | |||||
* for compatibility with the earlier JACK transport implementation. | |||||
*********************************************************************/ | |||||
/** | |||||
* Optional struct jack_transport_info_t fields. | |||||
* | |||||
* @see jack_position_bits_t. | |||||
*/ | |||||
typedef enum { | |||||
JackTransportState = 0x1, /**< Transport state */ | |||||
JackTransportPosition = 0x2, /**< Frame number */ | |||||
JackTransportLoop = 0x4, /**< Loop boundaries (ignored) */ | |||||
JackTransportSMPTE = 0x8, /**< SMPTE (ignored) */ | |||||
JackTransportBBT = 0x10 /**< Bar, Beat, Tick */ | |||||
} jack_transport_bits_t; | |||||
/** | |||||
* Deprecated struct for transport position information. | |||||
* | |||||
* @deprecated This is for compatibility with the earlier transport | |||||
* interface. Use the jack_position_t struct, instead. | |||||
*/ | |||||
typedef struct { | |||||
/* these two cannot be set from clients: the server sets them */ | |||||
jack_nframes_t frame_rate; /**< current frame rate (per second) */ | |||||
jack_time_t usecs; /**< monotonic, free-rolling */ | |||||
jack_transport_bits_t valid; /**< which fields are legal to read */ | |||||
jack_transport_state_t transport_state; | |||||
jack_nframes_t frame; | |||||
jack_nframes_t loop_start; | |||||
jack_nframes_t loop_end; | |||||
long smpte_offset; /**< SMPTE offset (from frame 0) */ | |||||
float smpte_frame_rate; /**< 29.97, 30, 24 etc. */ | |||||
int bar; | |||||
int beat; | |||||
int tick; | |||||
double bar_start_tick; | |||||
float beats_per_bar; | |||||
float beat_type; | |||||
double ticks_per_beat; | |||||
double beats_per_minute; | |||||
} jack_transport_info_t; | |||||
/** | |||||
* Gets the current transport info structure (deprecated). | |||||
* | |||||
* @param client the JACK client structure. | |||||
* @param tinfo current transport info structure. The "valid" field | |||||
* describes which fields contain valid data. | |||||
* | |||||
* @deprecated This is for compatibility with the earlier transport | |||||
* interface. Use jack_transport_query(), instead. | |||||
* | |||||
* @pre Must be called from the process thread. | |||||
*/ | |||||
void jack_get_transport_info (jack_client_t *client, | |||||
jack_transport_info_t *tinfo) JACK_OPTIONAL_WEAK_DEPRECATED_EXPORT; | |||||
/** | |||||
* Set the transport info structure (deprecated). | |||||
* | |||||
* @deprecated This function still exists for compatibility with the | |||||
* earlier transport interface, but it does nothing. Instead, define | |||||
* a ::JackTimebaseCallback. | |||||
*/ | |||||
void jack_set_transport_info (jack_client_t *client, | |||||
jack_transport_info_t *tinfo) JACK_OPTIONAL_WEAK_DEPRECATED_EXPORT; | |||||
#ifdef __cplusplus | |||||
} | |||||
#endif | |||||
#endif /* __jack_transport_h__ */ |
@@ -1,506 +0,0 @@ | |||||
/* | |||||
Copyright (C) 2001 Paul Davis | |||||
Copyright (C) 2004 Jack O'Quin | |||||
This program is free software; you can redistribute it and/or modify | |||||
it under the terms of the GNU Lesser General Public License as published by | |||||
the Free Software Foundation; either version 2.1 of the License, or | |||||
(at your option) any later version. | |||||
This program 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 Lesser General Public License for more details. | |||||
You should have received a copy of the GNU Lesser General Public License | |||||
along with this program; if not, write to the Free Software | |||||
Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. | |||||
*/ | |||||
#ifndef __jack_types_h__ | |||||
#define __jack_types_h__ | |||||
#include <inttypes.h> | |||||
#include <pthread.h> | |||||
typedef int32_t jack_shmsize_t; | |||||
/** | |||||
* Type used to represent sample frame counts. | |||||
*/ | |||||
typedef uint32_t jack_nframes_t; | |||||
/** | |||||
* Maximum value that can be stored in jack_nframes_t | |||||
*/ | |||||
#define JACK_MAX_FRAMES (4294967295U) /* This should be UINT32_MAX, but | |||||
C++ has a problem with that. */ | |||||
/** | |||||
* Type used to represent the value of free running | |||||
* monotonic clock with units of microseconds. | |||||
*/ | |||||
typedef uint64_t jack_time_t; | |||||
/** | |||||
* Maximum size of @a load_init string passed to an internal client | |||||
* jack_initialize() function via jack_internal_client_load(). | |||||
*/ | |||||
#define JACK_LOAD_INIT_LIMIT 1024 | |||||
/** | |||||
* jack_intclient_t is an opaque type representing a loaded internal | |||||
* client. You may only access it using the API provided in @ref | |||||
* intclient.h "<jack/intclient.h>". | |||||
*/ | |||||
typedef uint64_t jack_intclient_t; | |||||
/** | |||||
* jack_port_t is an opaque type. You may only access it using the | |||||
* API provided. | |||||
*/ | |||||
typedef struct _jack_port jack_port_t; | |||||
/** | |||||
* jack_client_t is an opaque type. You may only access it using the | |||||
* API provided. | |||||
*/ | |||||
typedef struct _jack_client jack_client_t; | |||||
/** | |||||
* Ports have unique ids. A port registration callback is the only | |||||
* place you ever need to know their value. | |||||
*/ | |||||
typedef uint32_t jack_port_id_t; | |||||
/** | |||||
* to make jack API independent of different thread implementations, | |||||
* we define jack_native_thread_t to pthread_t here. | |||||
* (all platforms that jack1 runs on, have pthread) | |||||
*/ | |||||
typedef pthread_t jack_native_thread_t; | |||||
/** | |||||
* @ref jack_options_t bits | |||||
*/ | |||||
enum JackOptions { | |||||
/** | |||||
* Null value to use when no option bits are needed. | |||||
*/ | |||||
JackNullOption = 0x00, | |||||
/** | |||||
* Do not automatically start the JACK server when it is not | |||||
* already running. This option is always selected if | |||||
* \$JACK_NO_START_SERVER is defined in the calling process | |||||
* environment. | |||||
*/ | |||||
JackNoStartServer = 0x01, | |||||
/** | |||||
* Use the exact client name requested. Otherwise, JACK | |||||
* automatically generates a unique one, if needed. | |||||
*/ | |||||
JackUseExactName = 0x02, | |||||
/** | |||||
* Open with optional <em>(char *) server_name</em> parameter. | |||||
*/ | |||||
JackServerName = 0x04, | |||||
/** | |||||
* Load internal client from optional <em>(char *) | |||||
* load_name</em>. Otherwise use the @a client_name. | |||||
*/ | |||||
JackLoadName = 0x08, | |||||
/** | |||||
* Pass optional <em>(char *) load_init</em> string to the | |||||
* jack_initialize() entry point of an internal client. | |||||
*/ | |||||
JackLoadInit = 0x10, | |||||
/** | |||||
* pass a SessionID Token this allows the sessionmanager to identify the client again. | |||||
*/ | |||||
JackSessionID = 0x20 | |||||
}; | |||||
/** Valid options for opening an external client. */ | |||||
#define JackOpenOptions (JackSessionID|JackServerName|JackNoStartServer|JackUseExactName) | |||||
/** Valid options for loading an internal client. */ | |||||
#define JackLoadOptions (JackLoadInit|JackLoadName|JackUseExactName) | |||||
/** | |||||
* Options for several JACK operations, formed by OR-ing together the | |||||
* relevant @ref JackOptions bits. | |||||
*/ | |||||
typedef enum JackOptions jack_options_t; | |||||
/** | |||||
* @ref jack_status_t bits | |||||
*/ | |||||
enum JackStatus { | |||||
/** | |||||
* Overall operation failed. | |||||
*/ | |||||
JackFailure = 0x01, | |||||
/** | |||||
* The operation contained an invalid or unsupported option. | |||||
*/ | |||||
JackInvalidOption = 0x02, | |||||
/** | |||||
* The desired client name was not unique. With the @ref | |||||
* JackUseExactName option this situation is fatal. Otherwise, | |||||
* the name was modified by appending a dash and a two-digit | |||||
* number in the range "-01" to "-99". The | |||||
* jack_get_client_name() function will return the exact string | |||||
* that was used. If the specified @a client_name plus these | |||||
* extra characters would be too long, the open fails instead. | |||||
*/ | |||||
JackNameNotUnique = 0x04, | |||||
/** | |||||
* The JACK server was started as a result of this operation. | |||||
* Otherwise, it was running already. In either case the caller | |||||
* is now connected to jackd, so there is no race condition. | |||||
* When the server shuts down, the client will find out. | |||||
*/ | |||||
JackServerStarted = 0x08, | |||||
/** | |||||
* Unable to connect to the JACK server. | |||||
*/ | |||||
JackServerFailed = 0x10, | |||||
/** | |||||
* Communication error with the JACK server. | |||||
*/ | |||||
JackServerError = 0x20, | |||||
/** | |||||
* Requested client does not exist. | |||||
*/ | |||||
JackNoSuchClient = 0x40, | |||||
/** | |||||
* Unable to load internal client | |||||
*/ | |||||
JackLoadFailure = 0x80, | |||||
/** | |||||
* Unable to initialize client | |||||
*/ | |||||
JackInitFailure = 0x100, | |||||
/** | |||||
* Unable to access shared memory | |||||
*/ | |||||
JackShmFailure = 0x200, | |||||
/** | |||||
* Client's protocol version does not match | |||||
*/ | |||||
JackVersionError = 0x400, | |||||
/* | |||||
* BackendError | |||||
*/ | |||||
JackBackendError = 0x800, | |||||
/* | |||||
* Client is being shutdown against its will | |||||
*/ | |||||
JackClientZombie = 0x1000 | |||||
}; | |||||
/** | |||||
* Status word returned from several JACK operations, formed by | |||||
* OR-ing together the relevant @ref JackStatus bits. | |||||
*/ | |||||
typedef enum JackStatus jack_status_t; | |||||
/** | |||||
* @ref jack_latency_callback_mode_t | |||||
*/ | |||||
enum JackLatencyCallbackMode { | |||||
/** | |||||
* Latency Callback for Capture Latency. | |||||
* Input Ports have their latency value setup. | |||||
* In the Callback the client needs to set the latency of the output ports | |||||
*/ | |||||
JackCaptureLatency, | |||||
/** | |||||
* Latency Callback for Playback Latency. | |||||
* Output Ports have their latency value setup. | |||||
* In the Callback the client needs to set the latency of the input ports | |||||
*/ | |||||
JackPlaybackLatency | |||||
}; | |||||
/** | |||||
* Type of Latency Callback (Capture or Playback) | |||||
*/ | |||||
typedef enum JackLatencyCallbackMode jack_latency_callback_mode_t; | |||||
/** | |||||
* Prototype for the client supplied function that is called | |||||
* by the engine when port latencies need to be recalculated | |||||
* | |||||
* @param mode playback or capture latency | |||||
* @param arg pointer to a client supplied data | |||||
* | |||||
* @return zero on success, non-zero on error | |||||
*/ | |||||
typedef void (*JackLatencyCallback)(jack_latency_callback_mode_t mode, void *arg); | |||||
/** | |||||
* the new latency API operates on Ranges. | |||||
*/ | |||||
struct _jack_latency_range | |||||
{ | |||||
/** | |||||
* minimum latency | |||||
*/ | |||||
jack_nframes_t min; | |||||
/** | |||||
* maximum latency | |||||
*/ | |||||
jack_nframes_t max; | |||||
}; | |||||
typedef struct _jack_latency_range jack_latency_range_t; | |||||
/** | |||||
* Prototype for the client supplied function that is called | |||||
* by the engine anytime there is work to be done. | |||||
* | |||||
* @pre nframes == jack_get_buffer_size() | |||||
* @pre nframes == pow(2,x) | |||||
* | |||||
* @param nframes number of frames to process | |||||
* @param arg pointer to a client supplied data | |||||
* | |||||
* @return zero on success, non-zero on error | |||||
*/ | |||||
typedef int (*JackProcessCallback)(jack_nframes_t nframes, void *arg); | |||||
/** | |||||
* Prototype for the client supplied function that is called | |||||
* once after the creation of the thread in which other | |||||
* callbacks will be made. Special thread characteristics | |||||
* can be set from this callback, for example. This is a | |||||
* highly specialized callback and most clients will not | |||||
* and should not use it. | |||||
* | |||||
* @param arg pointer to a client supplied structure | |||||
* | |||||
* @return void | |||||
*/ | |||||
typedef void (*JackThreadInitCallback)(void *arg); | |||||
/** | |||||
* Prototype for the client supplied function that is called | |||||
* whenever the processing graph is reordered. | |||||
* | |||||
* @param arg pointer to a client supplied data | |||||
* | |||||
* @return zero on success, non-zero on error | |||||
*/ | |||||
typedef int (*JackGraphOrderCallback)(void *arg); | |||||
/** | |||||
* Prototype for the client-supplied function that is called whenever | |||||
* an xrun has occured. | |||||
* | |||||
* @see jack_get_xrun_delayed_usecs() | |||||
* | |||||
* @param arg pointer to a client supplied data | |||||
* | |||||
* @return zero on success, non-zero on error | |||||
*/ | |||||
typedef int (*JackXRunCallback)(void *arg); | |||||
/** | |||||
* Prototype for the @a bufsize_callback that is invoked whenever the | |||||
* JACK engine buffer size changes. Although this function is called | |||||
* in the JACK process thread, the normal process cycle is suspended | |||||
* during its operation, causing a gap in the audio flow. So, the @a | |||||
* bufsize_callback can allocate storage, touch memory not previously | |||||
* referenced, and perform other operations that are not realtime | |||||
* safe. | |||||
* | |||||
* @param nframes buffer size | |||||
* @param arg pointer supplied by jack_set_buffer_size_callback(). | |||||
* | |||||
* @return zero on success, non-zero on error | |||||
*/ | |||||
typedef int (*JackBufferSizeCallback)(jack_nframes_t nframes, void *arg); | |||||
/** | |||||
* Prototype for the client supplied function that is called | |||||
* when the engine sample rate changes. | |||||
* | |||||
* @param nframes new engine sample rate | |||||
* @param arg pointer to a client supplied data | |||||
* | |||||
* @return zero on success, non-zero on error | |||||
*/ | |||||
typedef int (*JackSampleRateCallback)(jack_nframes_t nframes, void *arg); | |||||
/** | |||||
* Prototype for the client supplied function that is called | |||||
* whenever a port is registered or unregistered. | |||||
* | |||||
* @param port the ID of the port | |||||
* @param arg pointer to a client supplied data | |||||
* @param register non-zero if the port is being registered, | |||||
* zero if the port is being unregistered | |||||
*/ | |||||
typedef void (*JackPortRegistrationCallback)(jack_port_id_t port, int register, void *arg); | |||||
/** | |||||
* Prototype for the client supplied function that is called | |||||
* whenever a client is registered or unregistered. | |||||
* | |||||
* @param name a null-terminated string containing the client name | |||||
* @param register non-zero if the client is being registered, | |||||
* zero if the client is being unregistered | |||||
* @param arg pointer to a client supplied data | |||||
*/ | |||||
typedef void (*JackClientRegistrationCallback)(const char* name, int register, void *arg); | |||||
/** | |||||
* Prototype for the client supplied function that is called | |||||
* whenever a client is registered or unregistered. | |||||
* | |||||
* @param a one of two ports connected or disconnected | |||||
* @param b one of two ports connected or disconnected | |||||
* @param connect non-zero if ports were connected | |||||
* zero if ports were disconnected | |||||
* @param arg pointer to a client supplied data | |||||
*/ | |||||
typedef void (*JackPortConnectCallback)(jack_port_id_t a, jack_port_id_t b, int connect, void* arg); | |||||
/** | |||||
* Prototype for the client supplied function that is called | |||||
* whenever jackd starts or stops freewheeling. | |||||
* | |||||
* @param starting non-zero if we start starting to freewheel, zero otherwise | |||||
* @param arg pointer to a client supplied structure | |||||
*/ | |||||
typedef void (*JackFreewheelCallback)(int starting, void *arg); | |||||
typedef void *(*JackThreadCallback)(void* arg); | |||||
/** | |||||
* Prototype for the client supplied function that is called | |||||
* whenever jackd is shutdown. Note that after server shutdown, | |||||
* the client pointer is *not* deallocated by libjack, | |||||
* the application is responsible to properly use jack_client_close() | |||||
* to release client ressources. Warning: jack_client_close() cannot be | |||||
* safely used inside the shutdown callback and has to be called outside of | |||||
* the callback context. | |||||
* | |||||
* @param arg pointer to a client supplied structure | |||||
*/ | |||||
typedef void (*JackShutdownCallback)(void *arg); | |||||
/** | |||||
* Prototype for the client supplied function that is called | |||||
* whenever jackd is shutdown. Note that after server shutdown, | |||||
* the client pointer is *not* deallocated by libjack, | |||||
* the application is responsible to properly use jack_client_close() | |||||
* to release client ressources. Warning: jack_client_close() cannot be | |||||
* safely used inside the shutdown callback and has to be called outside of | |||||
* the callback context. | |||||
* | |||||
* @param code a shutdown code | |||||
* @param reason a string describing the shutdown reason (backend failure, server crash... etc...) | |||||
* @param arg pointer to a client supplied structure | |||||
*/ | |||||
typedef void (*JackInfoShutdownCallback)(jack_status_t code, const char* reason, void *arg); | |||||
/** | |||||
* Used for the type argument of jack_port_register() for default | |||||
* audio and midi ports. | |||||
*/ | |||||
#define JACK_DEFAULT_AUDIO_TYPE "32 bit float mono audio" | |||||
#define JACK_DEFAULT_MIDI_TYPE "8 bit raw midi" | |||||
/** | |||||
* For convenience, use this typedef if you want to be able to change | |||||
* between float and double. You may want to typedef sample_t to | |||||
* jack_default_audio_sample_t in your application. | |||||
*/ | |||||
typedef float jack_default_audio_sample_t; | |||||
/** | |||||
* A port has a set of flags that are formed by OR-ing together the | |||||
* desired values from the list below. The flags "JackPortIsInput" and | |||||
* "JackPortIsOutput" are mutually exclusive and it is an error to use | |||||
* them both. | |||||
*/ | |||||
enum JackPortFlags { | |||||
/** | |||||
* if JackPortIsInput is set, then the port can receive | |||||
* data. | |||||
*/ | |||||
JackPortIsInput = 0x1, | |||||
/** | |||||
* if JackPortIsOutput is set, then data can be read from | |||||
* the port. | |||||
*/ | |||||
JackPortIsOutput = 0x2, | |||||
/** | |||||
* if JackPortIsPhysical is set, then the port corresponds | |||||
* to some kind of physical I/O connector. | |||||
*/ | |||||
JackPortIsPhysical = 0x4, | |||||
/** | |||||
* if JackPortCanMonitor is set, then a call to | |||||
* jack_port_request_monitor() makes sense. | |||||
* | |||||
* Precisely what this means is dependent on the client. A typical | |||||
* result of it being called with TRUE as the second argument is | |||||
* that data that would be available from an output port (with | |||||
* JackPortIsPhysical set) is sent to a physical output connector | |||||
* as well, so that it can be heard/seen/whatever. | |||||
* | |||||
* Clients that do not control physical interfaces | |||||
* should never create ports with this bit set. | |||||
*/ | |||||
JackPortCanMonitor = 0x8, | |||||
/** | |||||
* JackPortIsTerminal means: | |||||
* | |||||
* for an input port: the data received by the port | |||||
* will not be passed on or made | |||||
* available at any other port | |||||
* | |||||
* for an output port: the data available at the port | |||||
* does not originate from any other port | |||||
* | |||||
* Audio synthesizers, I/O hardware interface clients, HDR | |||||
* systems are examples of clients that would set this flag for | |||||
* their ports. | |||||
*/ | |||||
JackPortIsTerminal = 0x10 | |||||
}; | |||||
#endif /* __jack_types_h__ */ |
@@ -1,26 +0,0 @@ | |||||
/* -*- mode: c; c-file-style: "bsd"; -*- */ | |||||
/* | |||||
Copyright (C) 2001-2003 Paul Davis | |||||
This program is free software; you can redistribute it and/or modify | |||||
it under the terms of the GNU Lesser General Public License as published by | |||||
the Free Software Foundation; either version 2.1 of the License, or | |||||
(at your option) any later version. | |||||
This program 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 Lesser General Public License for more details. | |||||
You should have received a copy of the GNU Lesser General Public License | |||||
along with this program; if not, write to the Free Software | |||||
Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. | |||||
*/ | |||||
#ifndef __jack_mlock_h__ | |||||
#define __jack_mlock_h__ | |||||
extern void cleanup_mlock (void); | |||||
#endif /* __jack_mlock_h__ */ |
@@ -1,65 +0,0 @@ | |||||
/* | |||||
* Copyright (C) 2004 Jack O'Quin | |||||
* | |||||
* This program is free software; you can redistribute it and/or modify | |||||
* it under the terms of the GNU Lesser General Public License as published by | |||||
* the Free Software Foundation; either version 2.1 of the License, or | |||||
* (at your option) any later version. | |||||
* | |||||
* This program 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 Lesser General Public License for more details. | |||||
* | |||||
* You should have received a copy of the GNU Lesser General Public License | |||||
* along with this program; if not, write to the Free Software | |||||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. | |||||
* | |||||
*/ | |||||
#ifndef __jack_varargs_h__ | |||||
#define __jack_varargs_h__ | |||||
#ifdef __cplusplus | |||||
extern "C" { | |||||
#endif | |||||
/* variable argument structure */ | |||||
typedef struct { | |||||
char *server_name; /* server name */ | |||||
char *load_name; /* load module name */ | |||||
char *load_init; /* initialization string */ | |||||
char *sess_uuid; | |||||
} jack_varargs_t; | |||||
static inline void | |||||
jack_varargs_init (jack_varargs_t *va) | |||||
{ | |||||
memset (va, 0, sizeof(jack_varargs_t)); | |||||
va->server_name = jack_default_server_name (); | |||||
} | |||||
static inline void | |||||
jack_varargs_parse (jack_options_t options, va_list ap, jack_varargs_t *va) | |||||
{ | |||||
/* initialize default settings */ | |||||
jack_varargs_init (va); | |||||
if ((options & JackServerName)) { | |||||
char *sn = va_arg(ap, char *); | |||||
if (sn) | |||||
va->server_name = sn; | |||||
} | |||||
if ((options & JackLoadName)) | |||||
va->load_name = va_arg(ap, char *); | |||||
if ((options & JackLoadInit)) | |||||
va->load_init = va_arg(ap, char *); | |||||
if ((options & JackSessionID)) | |||||
va->sess_uuid = va_arg(ap, char *); | |||||
} | |||||
#ifdef __cplusplus | |||||
} | |||||
#endif | |||||
#endif /* __jack_varargs_h__ */ |
@@ -1,20 +0,0 @@ | |||||
/* | |||||
Copyright (C) 2003 Paul Davis | |||||
@configure_input@ | |||||
This program 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. | |||||
This program 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 this program; if not, write to the Free Software | |||||
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. | |||||
*/ | |||||
#define jack_protocol_version @JACK_PROTOCOL_VERSION@ |
@@ -1,125 +0,0 @@ | |||||
/* | |||||
Copyright (C) 2010 Paul Davis | |||||
This program is free software; you can redistribute it and/or modify | |||||
it under the terms of the GNU Lesser General Public License as published by | |||||
the Free Software Foundation; either version 2.1 of the License, or | |||||
(at your option) any later version. | |||||
This program 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 Lesser General Public License for more details. | |||||
You should have received a copy of the GNU Lesser General Public License | |||||
along with this program; if not, write to the Free Software | |||||
Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. | |||||
*/ | |||||
#ifndef __weakjack_h__ | |||||
#define __weakjack_h__ | |||||
/** | |||||
* @defgroup WeakLinkage managing support for newer/older versions of JACK | |||||
* @{ One challenge faced by developers is that of taking | |||||
* advantage of new features introduced in new versions | |||||
* of [ JACK ] while still supporting older versions of | |||||
* the system. Normally, if an application uses a new | |||||
* feature in a library/API, it is unable to run on | |||||
* earlier versions of the library/API that do not | |||||
* support that feature. Such applications would either | |||||
* fail to launch or crash when an attempt to use the | |||||
* feature was made. This problem cane be solved using | |||||
* weakly-linked symbols. | |||||
* | |||||
* When a symbol in a framework is defined as weakly | |||||
* linked, the symbol does not have to be present at | |||||
* runtime for a process to continue running. The static | |||||
* linker identifies a weakly linked symbol as such in | |||||
* any code module that references the symbol. The | |||||
* dynamic linker uses this same information at runtime | |||||
* to determine whether a process can continue | |||||
* running. If a weakly linked symbol is not present in | |||||
* the framework, the code module can continue to run as | |||||
* long as it does not reference the symbol. However, if | |||||
* the symbol is present, the code can use it normally. | |||||
* | |||||
* (adapted from: http://developer.apple.com/library/mac/#documentation/MacOSX/Conceptual/BPFrameworks/Concepts/WeakLinking.html) | |||||
* | |||||
* A concrete example will help. Suppose that someone uses a version | |||||
* of a JACK client we'll call "Jill". Jill was linked against a version | |||||
* of JACK that contains a newer part of the API (say, jack_set_latency_callback()) | |||||
* and would like to use it if it is available. | |||||
* | |||||
* When Jill is run on a system that has a suitably "new" version of | |||||
* JACK, this function will be available entirely normally. But if Jill | |||||
* is run on a system with an old version of JACK, the function isn't | |||||
* available. | |||||
* | |||||
* With normal symbol linkage, this would create a startup error whenever | |||||
* someone tries to run Jill with the "old" version of JACK. However, functions | |||||
* added to JACK after version 0.116.2 are all declared to have "weak" linkage | |||||
* which means that their abscence doesn't cause an error during program | |||||
* startup. Instead, Jill can test whether or not the symbol jack_set_latency_callback | |||||
* is null or not. If its null, it means that the JACK installed on this machine | |||||
* is too old to support this function. If its not null, then Jill can use it | |||||
* just like any other function in the API. For example: | |||||
* | |||||
* \code | |||||
* if (jack_set_latency_callback) { | |||||
* jack_set_latency_callback (jill_client, jill_latency_callback, arg); | |||||
* } | |||||
* \endcode | |||||
* | |||||
* However, there are clients that may want to use this approach to parts of the | |||||
* the JACK API that predate 0.116.2. For example, they might want to see if even | |||||
* really old basic parts of the API like jack_client_open() exist at runtime. | |||||
* | |||||
* Such clients should include <jack/weakjack.h> before any other JACK header. | |||||
* This will make the \b entire JACK API be subject to weak linkage, so that any | |||||
* and all functions can be checked for existence at runtime. It is important | |||||
* to understand that very few clients need to do this - if you use this | |||||
* feature you should have a clear reason to do so. | |||||
* | |||||
* | |||||
*/ | |||||
#ifdef __APPLE__ | |||||
#define WEAK_ATTRIBUTE weak_import | |||||
#else | |||||
#define WEAK_ATTRIBUTE __weak__ | |||||
#endif | |||||
#ifndef JACK_OPTIONAL_WEAK_EXPORT | |||||
/* JACK_OPTIONAL_WEAK_EXPORT needs to be a macro which | |||||
expands into a compiler directive. If non-null, the directive | |||||
must tell the compiler to arrange for weak linkage of | |||||
the symbol it used with. For this to work fully may | |||||
require linker arguments for the client as well. | |||||
*/ | |||||
#ifdef __GNUC__ | |||||
#define JACK_OPTIONAL_WEAK_EXPORT __attribute__((WEAK_ATTRIBUTE)) | |||||
#else | |||||
/* Add other things here for non-gcc platforms */ | |||||
#endif | |||||
#endif | |||||
#ifndef JACK_OPTIONAL_WEAK_DEPRECATED_EXPORT | |||||
/* JACK_OPTIONAL_WEAK_DEPRECATED_EXPORT needs to be a macro | |||||
which expands into a compiler directive. If non-null, the directive | |||||
must tell the compiler to arrange for weak linkage of the | |||||
symbol it is used with AND optionally to mark the symbol | |||||
as deprecated. For this to work fully may require | |||||
linker arguments for the client as well. | |||||
*/ | |||||
#ifdef __GNUC__ | |||||
#define JACK_OPTIONAL_WEAK_DEPRECATED_EXPORT __attribute__((WEAK_ATTRIBUTE,__deprecated__)) | |||||
#else | |||||
/* Add other things here for non-gcc platforms */ | |||||
#endif | |||||
#endif | |||||
/*@}*/ | |||||
#endif /* weakjack */ |
@@ -1,67 +0,0 @@ | |||||
/* | |||||
Copyright (C) 2010 Paul Davis | |||||
This program is free software; you can redistribute it and/or modify | |||||
it under the terms of the GNU Lesser General Public License as published by | |||||
the Free Software Foundation; either version 2.1 of the License, or | |||||
(at your option) any later version. | |||||
This program 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 Lesser General Public License for more details. | |||||
You should have received a copy of the GNU Lesser General Public License | |||||
along with this program; if not, write to the Free Software | |||||
Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. | |||||
*/ | |||||
#ifndef __weakmacros_h__ | |||||
#define __weakmacros_h__ | |||||
/************************************************************* | |||||
* NOTE: JACK_WEAK_EXPORT ***MUST*** be used on every function | |||||
* added to the JACK API after the 0.116.2 release. | |||||
* | |||||
* Functions that predate this release are marked with | |||||
* JACK_WEAK_OPTIONAL_EXPORT which can be defined at compile | |||||
* time in a variety of ways. The default definition is empty, | |||||
* so that these symbols get normal linkage. If you wish to | |||||
* use all JACK symbols with weak linkage, include | |||||
* <jack/weakjack.h> before jack.h. | |||||
*************************************************************/ | |||||
#ifdef __APPLE__ | |||||
#define WEAK_ATTRIBUTE weak_import | |||||
#else | |||||
#define WEAK_ATTRIBUTE __weak__ | |||||
#endif | |||||
#ifndef JACK_WEAK_EXPORT | |||||
#ifdef __GNUC__ | |||||
/* JACK_WEAK_EXPORT needs to be a macro which | |||||
expands into a compiler directive. If non-null, the directive | |||||
must tell the compiler to arrange for weak linkage of | |||||
the symbol it used with. For this to work full may | |||||
require linker arguments in the client as well. | |||||
*/ | |||||
#define JACK_WEAK_EXPORT __attribute__((WEAK_ATTRIBUTE)) | |||||
#else | |||||
/* Add other things here for non-gcc platforms */ | |||||
#endif | |||||
#endif | |||||
#ifndef JACK_OPTIONAL_WEAK_EXPORT | |||||
#define JACK_OPTIONAL_WEAK_EXPORT | |||||
#endif | |||||
#ifndef JACK_OPTIONAL_WEAK_DEPRECATED_EXPORT | |||||
#ifdef __GNUC__ | |||||
#define JACK_OPTIONAL_WEAK_DEPRECATED_EXPORT __attribute__((__deprecated__)) | |||||
#else | |||||
/* Add other things here for non-gcc platforms */ | |||||
#endif /* __GNUC__ */ | |||||
#endif | |||||
#endif /* __weakmacros_h__ */ |
@@ -0,0 +1 @@ | |||||
Subproject commit c8270e367f8d45663f8bfd5478c6ae763645ae24 |
@@ -1,158 +0,0 @@ | |||||
MAINTAINERCLEANFILES = Makefile.in | |||||
if HAVE_READLINE | |||||
JACK_TRANSPORT = jack_transport | |||||
dist-check-readline: | |||||
else | |||||
JACK_TRANSPORT = | |||||
dist-check-readline: | |||||
@echo | |||||
@echo ' ******' You need readline installed to make dist.' ******' | |||||
@echo | |||||
@false | |||||
endif | |||||
NETJACK_TOOLS = jack_netsource | |||||
if HAVE_SAMPLERATE | |||||
if HAVE_ALSA | |||||
NETJACK_TOOLS += alsa_in alsa_out | |||||
endif | |||||
dist-check-samplerate: | |||||
else | |||||
dist-check-samplerate: | |||||
@echo | |||||
@echo ' ******' You need libsamplerate installed to make dist.' ******' | |||||
@echo | |||||
@false | |||||
endif | |||||
bin_PROGRAMS = jack_load \ | |||||
jack_unload \ | |||||
jack_monitor_client \ | |||||
jack_connect \ | |||||
jack_disconnect \ | |||||
jack_lsp \ | |||||
jack_freewheel \ | |||||
jack_evmon \ | |||||
jack_alias \ | |||||
jack_bufsize \ | |||||
jack_samplerate \ | |||||
jack_session_notify \ | |||||
jack_wait \ | |||||
jack_midi_dump \ | |||||
jack_iodelay \ | |||||
jack_load_test \ | |||||
$(JACK_TRANSPORT) \ | |||||
$(NETJACK_TOOLS) | |||||
noinst_PROGRAMS = jack_thread_wait | |||||
if HAVE_SNDFILE | |||||
# note! jackrec_CFLAGS syntax not supported by automake-1.4 | |||||
sndfile_cflags = @SNDFILE_CFLAGS@ | |||||
endif | |||||
AM_CFLAGS = -I.. $(JACK_CFLAGS) $(sndfile_cflags) | |||||
AM_CXXFLAGS = -I.. $(JACK_CFLAGS) $(sndfile_cflags) | |||||
jack_connect_SOURCES = connect.c | |||||
jack_connect_LDFLAGS = @OS_LDFLAGS@ | |||||
jack_connect_LDADD = $(top_builddir)/libjack/libjack.la | |||||
jack_disconnect_SOURCES = connect.c | |||||
jack_disconnect_LDFLAGS = @OS_LDFLAGS@ | |||||
jack_disconnect_LDADD = $(top_builddir)/libjack/libjack.la | |||||
jack_monitor_client_SOURCES = monitor_client.c | |||||
jack_monitor_client_LDFLAGS = @OS_LDFLAGS@ | |||||
jack_monitor_client_LDADD = $(top_builddir)/libjack/libjack.la | |||||
jack_thread_wait_SOURCES = tw.c | |||||
jack_thread_wait_LDFLAGS = @OS_LDFLAGS@ | |||||
jack_thread_wait_LDADD = $(top_builddir)/libjack/libjack.la | |||||
jack_wait_SOURCES = wait.c | |||||
jack_wait_LDFLAGS = @OS_LDFLAGS@ | |||||
jack_wait_LDADD = $(top_builddir)/libjack/libjack.la | |||||
jack_evmon_SOURCES = evmon.c | |||||
jack_evmon_LDFLAGS = @OS_LDFLAGS@ | |||||
jack_evmon_LDADD = $(top_builddir)/libjack/libjack.la | |||||
jack_alias_SOURCES = alias.c | |||||
jack_alias_LDFLAGS = @OS_LDFLAGS@ | |||||
jack_alias_LDADD = $(top_builddir)/libjack/libjack.la | |||||
jack_lsp_SOURCES = lsp.c | |||||
jack_lsp_LDFLAGS = @OS_LDFLAGS@ | |||||
jack_lsp_LDADD = $(top_builddir)/libjack/libjack.la | |||||
jack_freewheel_SOURCES = freewheel.c | |||||
jack_freewheel_LDFLAGS = @OS_LDFLAGS@ | |||||
jack_freewheel_LDADD = $(top_builddir)/libjack/libjack.la | |||||
jack_bufsize_SOURCES = bufsize.c | |||||
jack_bufsize_LDFLAGS = @OS_LDFLAGS@ | |||||
jack_bufsize_LDADD = $(top_builddir)/libjack/libjack.la | |||||
jack_samplerate_SOURCES = samplerate.c | |||||
jack_samplerate_LDFLAGS = @OS_LDFLAGS@ | |||||
jack_samplerate_LDADD = $(top_builddir)/libjack/libjack.la | |||||
jack_session_notify_SOURCES = session_notify.c | |||||
jack_session_notify_LDFLAGS = @OS_LDFLAGS@ | |||||
jack_session_notify_LDADD = $(top_builddir)/libjack/libjack.la | |||||
jack_midi_dump_SOURCES = midi_dump.c | |||||
jack_midi_dump_LDFLAGS = @OS_LDFLAGS@ | |||||
jack_midi_dump_LDADD = $(top_builddir)/libjack/libjack.la | |||||
jack_iodelay_SOURCES = iodelay.c | |||||
jack_iodelay_LDFLAGS = @OS_LDFLAGS@ | |||||
jack_iodelay_LDADD = $(top_builddir)/libjack/libjack.la | |||||
if HAVE_READLINE | |||||
jack_transport_SOURCES = transport.c | |||||
jack_transport_LDFLAGS = -lreadline @READLINE_DEPS@ @OS_LDFLAGS@ | |||||
jack_transport_LDADD = $(top_builddir)/libjack/libjack.la | |||||
endif | |||||
jack_load_test_SOURCES = load_test.c | |||||
jack_load_test_LDFLAGS = @OS_LDFLAGS@ | |||||
jack_load_test_LDADD = $(top_builddir)/libjack/libjack.la | |||||
# | |||||
# General purpose in-process loader/unloader | |||||
# | |||||
jack_load_SOURCES = ipload.c | |||||
jack_load_LDFLAGS = @OS_LDFLAGS@ | |||||
jack_load_LDADD = $(top_builddir)/libjack/libjack.la | |||||
jack_unload_SOURCES = ipunload.c | |||||
jack_unload_LDFLAGS = @OS_LDFLAGS@ | |||||
jack_unload_LDADD = $(top_builddir)/libjack/libjack.la | |||||
# | |||||
# Netjack slave tools | |||||
# | |||||
jack_netsource_SOURCES = netsource.c $(top_builddir)/drivers/netjack/netjack_packet.c | |||||
jack_netsource_CFLAGS = @NETJACK_CFLAGS@ -I$(top_srcdir)/drivers/netjack | |||||
jack_netsource_LDFLAGS = @NETJACK_LIBS@ @OS_LDFLAGS@ | |||||
jack_netsource_LDADD = $(top_builddir)/libjack/libjack.la | |||||
if HAVE_SAMPLERATE | |||||
if HAVE_ALSA | |||||
alsa_in_SOURCES = alsa_in.c $(top_builddir)/drivers/alsa/memops.c | |||||
alsa_in_CFLAGS = @NETJACK_CFLAGS@ -I$(top_builddir)/drivers/alsa | |||||
alsa_in_LDFLAGS = -lasound -lsamplerate @OS_LDFLAGS@ | |||||
alsa_in_LDADD = $(top_builddir)/libjack/libjack.la | |||||
alsa_out_SOURCES = alsa_out.c $(top_builddir)/drivers/alsa/memops.c | |||||
alsa_out_CFLAGS = @NETJACK_CFLAGS@ -I$(top_builddir)/drivers/alsa | |||||
alsa_out_LDFLAGS = -lasound -lsamplerate @OS_LDFLAGS@ | |||||
alsa_out_LDADD = $(top_builddir)/libjack/libjack.la | |||||
endif #HAVE_ALSA | |||||
endif #HAVE_SAMPLERATE | |||||
# XXX ? dist-hook: dist-check-sndfile dist-check-samplerate |
@@ -1,121 +0,0 @@ | |||||
#include <stdio.h> | |||||
#include <stdlib.h> | |||||
#include <unistd.h> | |||||
#include <string.h> | |||||
#include <getopt.h> | |||||
#include <config.h> | |||||
#include <jack/jack.h> | |||||
char * my_name; | |||||
void | |||||
show_version (void) | |||||
{ | |||||
fprintf (stderr, "%s: JACK Audio Connection Kit version " VERSION "\n", | |||||
my_name); | |||||
} | |||||
void | |||||
show_usage (void) | |||||
{ | |||||
show_version (); | |||||
fprintf (stderr, "\nUsage: %s [options] portname alias\n", my_name); | |||||
fprintf (stderr, "List active Jack ports, and optionally display extra information.\n\n"); | |||||
fprintf (stderr, "Display options:\n"); | |||||
fprintf (stderr, " -u, --unalias remove `alias' as an alias for `port'\n"); | |||||
fprintf (stderr, " -h, --help Display this help message\n"); | |||||
fprintf (stderr, " --version Output version information and exit\n\n"); | |||||
fprintf (stderr, "For more information see http://jackaudio.org/\n"); | |||||
} | |||||
int | |||||
main (int argc, char *argv[]) | |||||
{ | |||||
jack_client_t *client; | |||||
jack_status_t status; | |||||
char* portname; | |||||
char* alias; | |||||
int unset = 0; | |||||
int ret; | |||||
int c; | |||||
int option_index; | |||||
extern int optind; | |||||
jack_port_t* port; | |||||
struct option long_options[] = { | |||||
{ "unalias", 0, 0, 'u' }, | |||||
{ "help", 0, 0, 'h' }, | |||||
{ "version", 0, 0, 'v' }, | |||||
{ 0, 0, 0, 0 } | |||||
}; | |||||
if (argc < 3) { | |||||
show_usage (); | |||||
return 1; | |||||
} | |||||
my_name = strrchr(argv[0], '/'); | |||||
if (my_name == 0) { | |||||
my_name = argv[0]; | |||||
} else { | |||||
my_name ++; | |||||
} | |||||
while ((c = getopt_long (argc, argv, "uhv", long_options, &option_index)) >= 0) { | |||||
switch (c) { | |||||
case 'u': | |||||
unset = 1; | |||||
break; | |||||
case 'h': | |||||
show_usage (); | |||||
return 1; | |||||
break; | |||||
case 'v': | |||||
show_version (); | |||||
return 1; | |||||
break; | |||||
default: | |||||
show_usage (); | |||||
return 1; | |||||
break; | |||||
} | |||||
} | |||||
portname = argv[optind++]; | |||||
alias = argv[optind]; | |||||
/* 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", JackNoStartServer, &status); | |||||
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; | |||||
} | |||||
if ((port = jack_port_by_name (client, portname)) == 0) { | |||||
fprintf (stderr, "No port named \"%s\"\n", portname); | |||||
return 1; | |||||
} | |||||
if (!unset) { | |||||
ret = jack_port_set_alias (port, alias); | |||||
} else { | |||||
ret = jack_port_unset_alias (port, alias); | |||||
} | |||||
jack_client_close (client); | |||||
return ret; | |||||
} |
@@ -1,801 +0,0 @@ | |||||
/** @file simple_client.c | |||||
* | |||||
* @brief This simple client demonstrates the basic features of JACK | |||||
* as they would be used by many applications. | |||||
*/ | |||||
#include <stdio.h> | |||||
#include <errno.h> | |||||
#include <unistd.h> | |||||
#include <stdlib.h> | |||||
#include <string.h> | |||||
#include <signal.h> | |||||
#include <math.h> | |||||
#include <jack/jack.h> | |||||
#include <jack/jslist.h> | |||||
#include <jack/memops.h> | |||||
#include "alsa/asoundlib.h" | |||||
#include <samplerate.h> | |||||
// Here are the lists of the jack ports... | |||||
JSList *capture_ports = NULL; | |||||
JSList *capture_srcs = NULL; | |||||
JSList *playback_ports = NULL; | |||||
JSList *playback_srcs = NULL; | |||||
jack_client_t *client; | |||||
snd_pcm_t *alsa_handle; | |||||
int jack_sample_rate; | |||||
int jack_buffer_size; | |||||
int quit = 0; | |||||
double resample_mean = 1.0; | |||||
double static_resample_factor = 1.0; | |||||
double resample_lower_limit = 0.25; | |||||
double resample_upper_limit = 4.0; | |||||
double *offset_array; | |||||
double *window_array; | |||||
int offset_differential_index = 0; | |||||
double offset_integral = 0; | |||||
// ------------------------------------------------------ commandline parameters | |||||
int sample_rate = 0; /* stream rate */ | |||||
int num_channels = 2; /* count of channels */ | |||||
int period_size = 1024; | |||||
int num_periods = 2; | |||||
int target_delay = 0; /* the delay which the program should try to approach. */ | |||||
int max_diff = 0; /* the diff value, when a hard readpointer skip should occur */ | |||||
int catch_factor = 100000; | |||||
int catch_factor2 = 10000; | |||||
double pclamp = 15.0; | |||||
double controlquant = 10000.0; | |||||
int smooth_size = 256; | |||||
int good_window=0; | |||||
int verbose = 0; | |||||
int instrument = 0; | |||||
int samplerate_quality = 2; | |||||
// Debug stuff: | |||||
volatile float output_resampling_factor = 1.0; | |||||
volatile int output_new_delay = 0; | |||||
volatile float output_offset = 0.0; | |||||
volatile float output_integral = 0.0; | |||||
volatile float output_diff = 0.0; | |||||
snd_pcm_uframes_t real_buffer_size; | |||||
snd_pcm_uframes_t real_period_size; | |||||
// buffers | |||||
char *tmpbuf; | |||||
char *outbuf; | |||||
float *resampbuf; | |||||
// format selection, and corresponding functions from memops in a nice set of structs. | |||||
typedef struct alsa_format { | |||||
snd_pcm_format_t format_id; | |||||
size_t sample_size; | |||||
void (*jack_to_soundcard) (char *dst, jack_default_audio_sample_t *src, unsigned long nsamples, unsigned long dst_skip, dither_state_t *state); | |||||
void (*soundcard_to_jack) (jack_default_audio_sample_t *dst, char *src, unsigned long nsamples, unsigned long src_skip); | |||||
const char *name; | |||||
} alsa_format_t; | |||||
alsa_format_t formats[] = { | |||||
{ SND_PCM_FORMAT_FLOAT_LE, 4, sample_move_dS_floatLE, sample_move_floatLE_sSs, "float" }, | |||||
{ SND_PCM_FORMAT_S32, 4, sample_move_d32u24_sS, sample_move_dS_s32u24, "32bit" }, | |||||
{ SND_PCM_FORMAT_S24_3LE, 3, sample_move_d24_sS, sample_move_dS_s24, "24bit - real" }, | |||||
{ SND_PCM_FORMAT_S24, 4, sample_move_d24_sS, sample_move_dS_s24, "24bit" }, | |||||
{ SND_PCM_FORMAT_S16, 2, sample_move_d16_sS, sample_move_dS_s16, "16bit" } | |||||
}; | |||||
#define NUMFORMATS (sizeof(formats)/sizeof(formats[0])) | |||||
int format=0; | |||||
// Alsa stuff... i dont want to touch this bullshit in the next years.... please... | |||||
static int xrun_recovery(snd_pcm_t *handle, int err) { | |||||
// printf( "xrun !!!.... %d\n", err ); | |||||
if (err == -EPIPE) { /* under-run */ | |||||
err = snd_pcm_prepare(handle); | |||||
if (err < 0) | |||||
printf("Can't recovery from underrun, prepare failed: %s\n", snd_strerror(err)); | |||||
return 0; | |||||
} else if (err == -EAGAIN) { | |||||
while ((err = snd_pcm_resume(handle)) == -EAGAIN) | |||||
usleep(100); /* wait until the suspend flag is released */ | |||||
if (err < 0) { | |||||
err = snd_pcm_prepare(handle); | |||||
if (err < 0) | |||||
printf("Can't recovery from suspend, prepare failed: %s\n", snd_strerror(err)); | |||||
} | |||||
return 0; | |||||
} | |||||
return err; | |||||
} | |||||
static int set_hwformat( snd_pcm_t *handle, snd_pcm_hw_params_t *params ) | |||||
{ | |||||
int i; | |||||
int err; | |||||
for( i=0; i<NUMFORMATS; i++ ) { | |||||
/* set the sample format */ | |||||
err = snd_pcm_hw_params_set_format(handle, params, formats[i].format_id); | |||||
if (err == 0) { | |||||
format = i; | |||||
return 0; | |||||
} | |||||
} | |||||
return err; | |||||
} | |||||
static int set_hwparams(snd_pcm_t *handle, snd_pcm_hw_params_t *params, snd_pcm_access_t access, int rate, int channels, int period, int nperiods ) { | |||||
int err, dir=0; | |||||
unsigned int buffer_time; | |||||
unsigned int period_time; | |||||
unsigned int rrate; | |||||
unsigned int rchannels; | |||||
/* choose all parameters */ | |||||
err = snd_pcm_hw_params_any(handle, params); | |||||
if (err < 0) { | |||||
printf("Broken configuration for playback: no configurations available: %s\n", snd_strerror(err)); | |||||
return err; | |||||
} | |||||
/* set the interleaved read/write format */ | |||||
err = snd_pcm_hw_params_set_access(handle, params, access); | |||||
if (err < 0) { | |||||
printf("Access type not available for playback: %s\n", snd_strerror(err)); | |||||
return err; | |||||
} | |||||
/* set the sample format */ | |||||
err = set_hwformat(handle, params); | |||||
if (err < 0) { | |||||
printf("Sample format not available for playback: %s\n", snd_strerror(err)); | |||||
return err; | |||||
} | |||||
/* set the count of channels */ | |||||
rchannels = channels; | |||||
err = snd_pcm_hw_params_set_channels_near(handle, params, &rchannels); | |||||
if (err < 0) { | |||||
printf("Channels count (%i) not available for record: %s\n", channels, snd_strerror(err)); | |||||
return err; | |||||
} | |||||
if (rchannels != channels) { | |||||
printf("WARNING: chennel count does not match (requested %d got %d)\n", channels, rchannels); | |||||
num_channels = rchannels; | |||||
} | |||||
/* set the stream rate */ | |||||
rrate = rate; | |||||
err = snd_pcm_hw_params_set_rate_near(handle, params, &rrate, 0); | |||||
if (err < 0) { | |||||
printf("Rate %iHz not available for playback: %s\n", rate, snd_strerror(err)); | |||||
return err; | |||||
} | |||||
if (rrate != rate) { | |||||
printf("WARNING: Rate doesn't match (requested %iHz, get %iHz)\n", rate, rrate); | |||||
sample_rate = rrate; | |||||
} | |||||
/* set the buffer time */ | |||||
buffer_time = 1000000*(uint64_t)period*nperiods/rate; | |||||
err = snd_pcm_hw_params_set_buffer_time_near(handle, params, &buffer_time, &dir); | |||||
if (err < 0) { | |||||
printf("Unable to set buffer time %i for playback: %s\n", 1000000*period*nperiods/rate, snd_strerror(err)); | |||||
return err; | |||||
} | |||||
err = snd_pcm_hw_params_get_buffer_size( params, &real_buffer_size ); | |||||
if (err < 0) { | |||||
printf("Unable to get buffer size back: %s\n", snd_strerror(err)); | |||||
return err; | |||||
} | |||||
if( real_buffer_size != nperiods * period ) { | |||||
printf( "WARNING: buffer size does not match: (requested %d, got %d)\n", nperiods * period, (int) real_buffer_size ); | |||||
} | |||||
/* set the period time */ | |||||
period_time = 1000000*(uint64_t)period/rate; | |||||
err = snd_pcm_hw_params_set_period_time_near(handle, params, &period_time, &dir); | |||||
if (err < 0) { | |||||
printf("Unable to set period time %i for playback: %s\n", 1000000*period/rate, snd_strerror(err)); | |||||
return err; | |||||
} | |||||
err = snd_pcm_hw_params_get_period_size(params, &real_period_size, NULL ); | |||||
if (err < 0) { | |||||
printf("Unable to get period size back: %s\n", snd_strerror(err)); | |||||
return err; | |||||
} | |||||
if( real_period_size != period ) { | |||||
printf( "WARNING: period size does not match: (requested %i, got %i)\n", period, (int)real_period_size ); | |||||
} | |||||
/* write the parameters to device */ | |||||
err = snd_pcm_hw_params(handle, params); | |||||
if (err < 0) { | |||||
printf("Unable to set hw params for playback: %s\n", snd_strerror(err)); | |||||
return err; | |||||
} | |||||
return 0; | |||||
} | |||||
static int set_swparams(snd_pcm_t *handle, snd_pcm_sw_params_t *swparams, int period) { | |||||
int err; | |||||
/* get the current swparams */ | |||||
err = snd_pcm_sw_params_current(handle, swparams); | |||||
if (err < 0) { | |||||
printf("Unable to determine current swparams for capture: %s\n", snd_strerror(err)); | |||||
return err; | |||||
} | |||||
/* start the transfer when the buffer is full */ | |||||
err = snd_pcm_sw_params_set_start_threshold(handle, swparams, period ); | |||||
if (err < 0) { | |||||
printf("Unable to set start threshold mode for capture: %s\n", snd_strerror(err)); | |||||
return err; | |||||
} | |||||
err = snd_pcm_sw_params_set_stop_threshold(handle, swparams, -1 ); | |||||
if (err < 0) { | |||||
printf("Unable to set start threshold mode for capture: %s\n", snd_strerror(err)); | |||||
return err; | |||||
} | |||||
/* allow the transfer when at least period_size samples can be processed */ | |||||
err = snd_pcm_sw_params_set_avail_min(handle, swparams, 2*period ); | |||||
if (err < 0) { | |||||
printf("Unable to set avail min for capture: %s\n", snd_strerror(err)); | |||||
return err; | |||||
} | |||||
/* align all transfers to 1 sample */ | |||||
err = snd_pcm_sw_params_set_xfer_align(handle, swparams, 1); | |||||
if (err < 0) { | |||||
printf("Unable to set transfer align for capture: %s\n", snd_strerror(err)); | |||||
return err; | |||||
} | |||||
/* write the parameters to the playback device */ | |||||
err = snd_pcm_sw_params(handle, swparams); | |||||
if (err < 0) { | |||||
printf("Unable to set sw params for capture: %s\n", snd_strerror(err)); | |||||
return err; | |||||
} | |||||
return 0; | |||||
} | |||||
// ok... i only need this function to communicate with the alsa bloat api... | |||||
static snd_pcm_t *open_audiofd( char *device_name, int capture, int rate, int channels, int period, int nperiods ) { | |||||
int err; | |||||
snd_pcm_t *handle; | |||||
snd_pcm_hw_params_t *hwparams; | |||||
snd_pcm_sw_params_t *swparams; | |||||
snd_pcm_hw_params_alloca(&hwparams); | |||||
snd_pcm_sw_params_alloca(&swparams); | |||||
if ((err = snd_pcm_open(&(handle), device_name, capture ? SND_PCM_STREAM_CAPTURE : SND_PCM_STREAM_PLAYBACK, SND_PCM_NONBLOCK )) < 0) { | |||||
printf("Capture open error: %s\n", snd_strerror(err)); | |||||
return NULL; | |||||
} | |||||
if ((err = set_hwparams(handle, hwparams,SND_PCM_ACCESS_RW_INTERLEAVED, rate, channels, period, nperiods )) < 0) { | |||||
printf("Setting of hwparams failed: %s\n", snd_strerror(err)); | |||||
return NULL; | |||||
} | |||||
if ((err = set_swparams(handle, swparams, period)) < 0) { | |||||
printf("Setting of swparams failed: %s\n", snd_strerror(err)); | |||||
return NULL; | |||||
} | |||||
snd_pcm_start( handle ); | |||||
snd_pcm_wait( handle, 200 ); | |||||
return handle; | |||||
} | |||||
double hann( double x ) | |||||
{ | |||||
return 0.5 * (1.0 - cos( 2*M_PI * x ) ); | |||||
} | |||||
/** | |||||
* The process callback for this JACK application. | |||||
* It is called by JACK at the appropriate times. | |||||
*/ | |||||
int process (jack_nframes_t nframes, void *arg) { | |||||
int rlen; | |||||
int err; | |||||
snd_pcm_sframes_t delay = target_delay; | |||||
int put_back_samples=0; | |||||
int i; | |||||
delay = snd_pcm_avail( alsa_handle ); | |||||
delay -= jack_frames_since_cycle_start( client ); | |||||
// Do it the hard way. | |||||
// this is for compensating xruns etc... | |||||
if( delay > (target_delay+max_diff) ) { | |||||
output_new_delay = (int) delay; | |||||
while ((delay-target_delay) > 0) { | |||||
snd_pcm_uframes_t to_read = ((delay-target_delay) > 512) ? 512 : (delay-target_delay); | |||||
snd_pcm_readi( alsa_handle, tmpbuf, to_read ); | |||||
delay -= to_read; | |||||
} | |||||
delay = target_delay; | |||||
// Set the resample_rate... we need to adjust the offset integral, to do this. | |||||
// first look at the PI controller, this code is just a special case, which should never execute once | |||||
// everything is swung in. | |||||
offset_integral = - (resample_mean - static_resample_factor) * catch_factor * catch_factor2; | |||||
// Also clear the array. we are beginning a new control cycle. | |||||
for( i=0; i<smooth_size; i++ ) | |||||
offset_array[i] = 0.0; | |||||
} | |||||
if( delay < (target_delay-max_diff) ) { | |||||
snd_pcm_rewind( alsa_handle, target_delay - delay ); | |||||
output_new_delay = (int) delay; | |||||
delay = target_delay; | |||||
// Set the resample_rate... we need to adjust the offset integral, to do this. | |||||
offset_integral = - (resample_mean - static_resample_factor) * catch_factor * catch_factor2; | |||||
// Also clear the array. we are beginning a new control cycle. | |||||
for( i=0; i<smooth_size; i++ ) | |||||
offset_array[i] = 0.0; | |||||
} | |||||
/* ok... now we should have target_delay +- max_diff on the alsa side. | |||||
* | |||||
* calculate the number of frames, we want to get. | |||||
*/ | |||||
double offset = delay - target_delay; | |||||
// Save offset. | |||||
offset_array[(offset_differential_index++)% smooth_size ] = offset; | |||||
// Build the mean of the windowed offset array | |||||
// basically fir lowpassing. | |||||
double smooth_offset = 0.0; | |||||
for( i=0; i<smooth_size; i++ ) | |||||
smooth_offset += | |||||
offset_array[ (i + offset_differential_index-1) % smooth_size] * window_array[i]; | |||||
smooth_offset /= (double) smooth_size; | |||||
// this is the integral of the smoothed_offset | |||||
offset_integral += smooth_offset; | |||||
// Clamp offset. | |||||
// the smooth offset still contains unwanted noise | |||||
// which would go straigth onto the resample coeff. | |||||
// it only used in the P component and the I component is used for the fine tuning anyways. | |||||
if( fabs( smooth_offset ) < pclamp ) | |||||
smooth_offset = 0.0; | |||||
// ok. now this is the PI controller. | |||||
// u(t) = K * ( e(t) + 1/T \int e(t') dt' ) | |||||
// K = 1/catch_factor and T = catch_factor2 | |||||
double current_resample_factor = static_resample_factor - smooth_offset / (double) catch_factor - offset_integral / (double) catch_factor / (double)catch_factor2; | |||||
// now quantize this value around resample_mean, so that the noise which is in the integral component doesnt hurt. | |||||
current_resample_factor = floor( (current_resample_factor - resample_mean) * controlquant + 0.5 ) / controlquant + resample_mean; | |||||
// Output "instrumentatio" gonna change that to real instrumentation in a few. | |||||
output_resampling_factor = (float) current_resample_factor; | |||||
output_diff = (float) smooth_offset; | |||||
output_integral = (float) offset_integral; | |||||
output_offset = (float) offset; | |||||
// Clamp a bit. | |||||
if( current_resample_factor < resample_lower_limit ) current_resample_factor = resample_lower_limit; | |||||
if( current_resample_factor > resample_upper_limit ) current_resample_factor = resample_upper_limit; | |||||
// Now Calculate how many samples we need. | |||||
rlen = ceil( ((double)nframes) / current_resample_factor )+2; | |||||
assert( rlen > 2 ); | |||||
// Calculate resample_mean so we can init ourselves to saner values. | |||||
resample_mean = 0.9999 * resample_mean + 0.0001 * current_resample_factor; | |||||
// get the data... | |||||
again: | |||||
err = snd_pcm_readi(alsa_handle, outbuf, rlen); | |||||
if( err < 0 ) { | |||||
printf( "err = %d\n", err ); | |||||
if (xrun_recovery(alsa_handle, err) < 0) { | |||||
//printf("Write error: %s\n", snd_strerror(err)); | |||||
//exit(EXIT_FAILURE); | |||||
} | |||||
goto again; | |||||
} | |||||
if( err != rlen ) { | |||||
//printf( "read = %d\n", rlen ); | |||||
} | |||||
/* | |||||
* render jack ports to the outbuf... | |||||
*/ | |||||
int chn = 0; | |||||
JSList *node = capture_ports; | |||||
JSList *src_node = capture_srcs; | |||||
SRC_DATA src; | |||||
while ( node != NULL) | |||||
{ | |||||
jack_port_t *port = (jack_port_t *) node->data; | |||||
float *buf = jack_port_get_buffer (port, nframes); | |||||
SRC_STATE *src_state = src_node->data; | |||||
formats[format].soundcard_to_jack( resampbuf, outbuf + format[formats].sample_size * chn, rlen, num_channels*format[formats].sample_size ); | |||||
src.data_in = resampbuf; | |||||
src.input_frames = rlen; | |||||
src.data_out = buf; | |||||
src.output_frames = nframes; | |||||
src.end_of_input = 0; | |||||
src.src_ratio = current_resample_factor; | |||||
src_process( src_state, &src ); | |||||
put_back_samples = rlen-src.input_frames_used; | |||||
src_node = jack_slist_next (src_node); | |||||
node = jack_slist_next (node); | |||||
chn++; | |||||
} | |||||
// Put back the samples libsamplerate did not consume. | |||||
//printf( "putback = %d\n", put_back_samples ); | |||||
snd_pcm_rewind( alsa_handle, put_back_samples ); | |||||
return 0; | |||||
} | |||||
/** | |||||
* the latency callback. | |||||
* sets up the latencies on the ports. | |||||
*/ | |||||
void | |||||
latency_cb (jack_latency_callback_mode_t mode, void *arg) | |||||
{ | |||||
jack_latency_range_t range; | |||||
JSList *node; | |||||
range.min = range.max = target_delay; | |||||
if (mode == JackCaptureLatency) { | |||||
for (node = capture_ports; node; node = jack_slist_next (node)) { | |||||
jack_port_t *port = node->data; | |||||
jack_port_set_latency_range (port, mode, &range); | |||||
} | |||||
} else { | |||||
for (node = playback_ports; node; node = jack_slist_next (node)) { | |||||
jack_port_t *port = node->data; | |||||
jack_port_set_latency_range (port, mode, &range); | |||||
} | |||||
} | |||||
} | |||||
/** | |||||
* Allocate the necessary jack ports... | |||||
*/ | |||||
void alloc_ports( int n_capture, int n_playback ) { | |||||
int port_flags = JackPortIsOutput; | |||||
int chn; | |||||
jack_port_t *port; | |||||
char buf[32]; | |||||
capture_ports = NULL; | |||||
for (chn = 0; chn < n_capture; chn++) | |||||
{ | |||||
snprintf (buf, sizeof(buf) - 1, "capture_%u", chn+1); | |||||
port = jack_port_register (client, buf, | |||||
JACK_DEFAULT_AUDIO_TYPE, | |||||
port_flags, 0); | |||||
if (!port) | |||||
{ | |||||
printf( "jacknet_client: cannot register port for %s", buf); | |||||
break; | |||||
} | |||||
capture_srcs = jack_slist_append( capture_srcs, src_new( 4-samplerate_quality, 1, NULL ) ); | |||||
capture_ports = jack_slist_append (capture_ports, port); | |||||
} | |||||
port_flags = JackPortIsInput; | |||||
playback_ports = NULL; | |||||
for (chn = 0; chn < n_playback; chn++) | |||||
{ | |||||
snprintf (buf, sizeof(buf) - 1, "playback_%u", chn+1); | |||||
port = jack_port_register (client, buf, | |||||
JACK_DEFAULT_AUDIO_TYPE, | |||||
port_flags, 0); | |||||
if (!port) | |||||
{ | |||||
printf( "jacknet_client: cannot register port for %s", buf); | |||||
break; | |||||
} | |||||
playback_srcs = jack_slist_append( playback_srcs, src_new( 4-samplerate_quality, 1, NULL ) ); | |||||
playback_ports = jack_slist_append (playback_ports, port); | |||||
} | |||||
} | |||||
/** | |||||
* This is the shutdown callback for this JACK application. | |||||
* It is called by JACK if the server ever shuts down or | |||||
* decides to disconnect the client. | |||||
*/ | |||||
void jack_shutdown (void *arg) { | |||||
exit (1); | |||||
} | |||||
/** | |||||
* be user friendly. | |||||
* be user friendly. | |||||
* be user friendly. | |||||
*/ | |||||
void printUsage() { | |||||
fprintf(stderr, "usage: alsa_out [options]\n" | |||||
"\n" | |||||
" -j <jack name> - client name\n" | |||||
" -d <alsa_device> \n" | |||||
" -c <channels> \n" | |||||
" -p <period_size> \n" | |||||
" -n <num_period> \n" | |||||
" -r <sample_rate> \n" | |||||
" -q <sample_rate quality [0..4]\n" | |||||
" -m <max_diff> \n" | |||||
" -t <target_delay> \n" | |||||
" -i turns on instrumentation\n" | |||||
" -v turns on printouts\n" | |||||
"\n"); | |||||
} | |||||
/** | |||||
* the main function.... | |||||
*/ | |||||
void | |||||
sigterm_handler( int signal ) | |||||
{ | |||||
quit = 1; | |||||
} | |||||
int main (int argc, char *argv[]) { | |||||
char jack_name[30] = "alsa_in"; | |||||
char alsa_device[30] = "hw:0"; | |||||
extern char *optarg; | |||||
extern int optind, optopt; | |||||
int errflg=0; | |||||
int c; | |||||
while ((c = getopt(argc, argv, "ivj:r:c:p:n:d:q:m:t:f:F:C:Q:s:")) != -1) { | |||||
switch(c) { | |||||
case 'j': | |||||
strcpy(jack_name,optarg); | |||||
break; | |||||
case 'r': | |||||
sample_rate = atoi(optarg); | |||||
break; | |||||
case 'c': | |||||
num_channels = atoi(optarg); | |||||
break; | |||||
case 'p': | |||||
period_size = atoi(optarg); | |||||
break; | |||||
case 'n': | |||||
num_periods = atoi(optarg); | |||||
break; | |||||
case 'd': | |||||
strcpy(alsa_device,optarg); | |||||
break; | |||||
case 't': | |||||
target_delay = atoi(optarg); | |||||
break; | |||||
case 'q': | |||||
samplerate_quality = atoi(optarg); | |||||
break; | |||||
case 'm': | |||||
max_diff = atoi(optarg); | |||||
break; | |||||
case 'f': | |||||
catch_factor = atoi(optarg); | |||||
break; | |||||
case 'F': | |||||
catch_factor2 = atoi(optarg); | |||||
break; | |||||
case 'C': | |||||
pclamp = (double) atoi(optarg); | |||||
break; | |||||
case 'Q': | |||||
controlquant = (double) atoi(optarg); | |||||
break; | |||||
case 'v': | |||||
verbose = 1; | |||||
break; | |||||
case 'i': | |||||
instrument = 1; | |||||
break; | |||||
case 's': | |||||
smooth_size = atoi(optarg); | |||||
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); | |||||
} | |||||
if( (samplerate_quality < 0) || (samplerate_quality > 4) ) { | |||||
fprintf (stderr, "invalid samplerate quality\n"); | |||||
return 1; | |||||
} | |||||
if ((client = jack_client_open (jack_name, 0, NULL)) == 0) { | |||||
fprintf (stderr, "jack server not running?\n"); | |||||
return 1; | |||||
} | |||||
/* tell the JACK server to call `process()' whenever | |||||
there is work to be done. | |||||
*/ | |||||
jack_set_process_callback (client, process, 0); | |||||
/* tell the JACK server to call `jack_shutdown()' if | |||||
it ever shuts down, either entirely, or if it | |||||
just decides to stop calling us. | |||||
*/ | |||||
jack_on_shutdown (client, jack_shutdown, 0); | |||||
if (jack_set_latency_callback) | |||||
jack_set_latency_callback (client, latency_cb, 0); | |||||
// get jack sample_rate | |||||
jack_sample_rate = jack_get_sample_rate( client ); | |||||
if( !sample_rate ) | |||||
sample_rate = jack_sample_rate; | |||||
// now open the alsa fd... | |||||
alsa_handle = open_audiofd( alsa_device, 1, sample_rate, num_channels, period_size, num_periods); | |||||
if( alsa_handle == 0 ) | |||||
exit(20); | |||||
printf( "selected sample format: %s\n", formats[format].name ); | |||||
static_resample_factor = (double) jack_sample_rate / (double) sample_rate; | |||||
resample_lower_limit = static_resample_factor * 0.25; | |||||
resample_upper_limit = static_resample_factor * 4.0; | |||||
resample_mean = static_resample_factor; | |||||
offset_array = malloc( sizeof(double) * smooth_size ); | |||||
if( offset_array == NULL ) { | |||||
fprintf( stderr, "no memory for offset_array !!!\n" ); | |||||
exit(20); | |||||
} | |||||
window_array = malloc( sizeof(double) * smooth_size ); | |||||
if( window_array == NULL ) { | |||||
fprintf( stderr, "no memory for window_array !!!\n" ); | |||||
exit(20); | |||||
} | |||||
int i; | |||||
for( i=0; i<smooth_size; i++ ) { | |||||
offset_array[i] = 0.0; | |||||
window_array[i] = hann( (double) i / ((double) smooth_size - 1.0) ); | |||||
} | |||||
jack_buffer_size = jack_get_buffer_size( client ); | |||||
// Setup target delay and max_diff for the normal user, who does not play with them... | |||||
if( !target_delay ) | |||||
target_delay = (num_periods*period_size / 2) + jack_buffer_size/2; | |||||
if( !max_diff ) | |||||
max_diff = num_periods*period_size - target_delay ; | |||||
if( max_diff > target_delay ) { | |||||
fprintf( stderr, "target_delay (%d) cant be smaller than max_diff(%d)\n", target_delay, max_diff ); | |||||
exit(20); | |||||
} | |||||
if( (target_delay+max_diff) > (num_periods*period_size) ) { | |||||
fprintf( stderr, "target_delay+max_diff (%d) cant be bigger than buffersize(%d)\n", target_delay+max_diff, num_periods*period_size ); | |||||
exit(20); | |||||
} | |||||
// alloc input ports, which are blasted out to alsa... | |||||
alloc_ports( num_channels, 0 ); | |||||
outbuf = malloc( num_periods * period_size * formats[format].sample_size * num_channels ); | |||||
resampbuf = malloc( num_periods * period_size * sizeof( float ) ); | |||||
tmpbuf = malloc( 512 * formats[format].sample_size * num_channels ); | |||||
if ((outbuf == NULL) || (resampbuf == NULL) || (tmpbuf == NULL)) | |||||
{ | |||||
fprintf( stderr, "no memory for buffers.\n" ); | |||||
exit(20); | |||||
} | |||||
memset( tmpbuf, 0, 512 * formats[format].sample_size * num_channels); | |||||
/* tell the JACK server that we are ready to roll */ | |||||
if (jack_activate (client)) { | |||||
fprintf (stderr, "cannot activate client"); | |||||
return 1; | |||||
} | |||||
signal( SIGTERM, sigterm_handler ); | |||||
signal( SIGINT, sigterm_handler ); | |||||
if( verbose ) { | |||||
while(!quit) { | |||||
usleep(500000); | |||||
if( output_new_delay ) { | |||||
printf( "delay = %d\n", output_new_delay ); | |||||
output_new_delay = 0; | |||||
} | |||||
printf( "res: %f, \tdiff = %f, \toffset = %f \n", output_resampling_factor, output_diff, output_offset ); | |||||
} | |||||
} else if( instrument ) { | |||||
printf( "# n\tresamp\tdiff\toffseti\tintegral\n"); | |||||
int n=0; | |||||
while(!quit) { | |||||
usleep(1000); | |||||
printf( "%d\t%f\t%f\t%f\t%f\n", n++, output_resampling_factor, output_diff, output_offset, output_integral ); | |||||
} | |||||
} else { | |||||
while(!quit) | |||||
{ | |||||
usleep(500000); | |||||
if( output_new_delay ) { | |||||
printf( "delay = %d\n", output_new_delay ); | |||||
output_new_delay = 0; | |||||
} | |||||
} | |||||
} | |||||
jack_deactivate( client ); | |||||
jack_client_close (client); | |||||
exit (0); | |||||
} | |||||
@@ -1,803 +0,0 @@ | |||||
/** @file simple_client.c | |||||
* | |||||
* @brief This simple client demonstrates the basic features of JACK | |||||
* as they would be used by many applications. | |||||
*/ | |||||
#include <stdio.h> | |||||
#include <errno.h> | |||||
#include <unistd.h> | |||||
#include <stdlib.h> | |||||
#include <string.h> | |||||
#include <signal.h> | |||||
#include <math.h> | |||||
#include <jack/jack.h> | |||||
#include <jack/jslist.h> | |||||
#include <jack/memops.h> | |||||
#include "alsa/asoundlib.h" | |||||
#include <samplerate.h> | |||||
// Here are the lists of the jack ports... | |||||
JSList *capture_ports = NULL; | |||||
JSList *capture_srcs = NULL; | |||||
JSList *playback_ports = NULL; | |||||
JSList *playback_srcs = NULL; | |||||
jack_client_t *client; | |||||
snd_pcm_t *alsa_handle; | |||||
int jack_sample_rate; | |||||
int jack_buffer_size; | |||||
int quit = 0; | |||||
double resample_mean = 1.0; | |||||
double static_resample_factor = 1.0; | |||||
double resample_lower_limit = 0.25; | |||||
double resample_upper_limit = 4.0; | |||||
double *offset_array; | |||||
double *window_array; | |||||
int offset_differential_index = 0; | |||||
double offset_integral = 0; | |||||
// ------------------------------------------------------ commandline parameters | |||||
int sample_rate = 0; /* stream rate */ | |||||
int num_channels = 2; /* count of channels */ | |||||
int period_size = 1024; | |||||
int num_periods = 2; | |||||
int target_delay = 0; /* the delay which the program should try to approach. */ | |||||
int max_diff = 0; /* the diff value, when a hard readpointer skip should occur */ | |||||
int catch_factor = 100000; | |||||
int catch_factor2 = 10000; | |||||
double pclamp = 15.0; | |||||
double controlquant = 10000.0; | |||||
int smooth_size = 256; | |||||
int good_window=0; | |||||
int verbose = 0; | |||||
int instrument = 0; | |||||
int samplerate_quality = 2; | |||||
// Debug stuff: | |||||
volatile float output_resampling_factor = 1.0; | |||||
volatile int output_new_delay = 0; | |||||
volatile float output_offset = 0.0; | |||||
volatile float output_integral = 0.0; | |||||
volatile float output_diff = 0.0; | |||||
snd_pcm_uframes_t real_buffer_size; | |||||
snd_pcm_uframes_t real_period_size; | |||||
// buffers | |||||
char *tmpbuf; | |||||
char *outbuf; | |||||
float *resampbuf; | |||||
// format selection, and corresponding functions from memops in a nice set of structs. | |||||
typedef struct alsa_format { | |||||
snd_pcm_format_t format_id; | |||||
size_t sample_size; | |||||
void (*jack_to_soundcard) (char *dst, jack_default_audio_sample_t *src, unsigned long nsamples, unsigned long dst_skip, dither_state_t *state); | |||||
void (*soundcard_to_jack) (jack_default_audio_sample_t *dst, char *src, unsigned long nsamples, unsigned long src_skip); | |||||
const char *name; | |||||
} alsa_format_t; | |||||
alsa_format_t formats[] = { | |||||
{ SND_PCM_FORMAT_FLOAT_LE, 4, sample_move_dS_floatLE, sample_move_floatLE_sSs, "float" }, | |||||
{ SND_PCM_FORMAT_S32, 4, sample_move_d32u24_sS, sample_move_dS_s32u24, "32bit" }, | |||||
{ SND_PCM_FORMAT_S24_3LE, 3, sample_move_d24_sS, sample_move_dS_s24, "24bit - real" }, | |||||
{ SND_PCM_FORMAT_S24, 4, sample_move_d24_sS, sample_move_dS_s24, "24bit" }, | |||||
{ SND_PCM_FORMAT_S16, 2, sample_move_d16_sS, sample_move_dS_s16, "16bit" } | |||||
}; | |||||
#define NUMFORMATS (sizeof(formats)/sizeof(formats[0])) | |||||
int format=0; | |||||
// Alsa stuff... i dont want to touch this bullshit in the next years.... please... | |||||
static int xrun_recovery(snd_pcm_t *handle, int err) { | |||||
// printf( "xrun !!!.... %d\n", err ); | |||||
if (err == -EPIPE) { /* under-run */ | |||||
err = snd_pcm_prepare(handle); | |||||
if (err < 0) | |||||
printf("Can't recovery from underrun, prepare failed: %s\n", snd_strerror(err)); | |||||
return 0; | |||||
} else if (err == -EAGAIN) { | |||||
while ((err = snd_pcm_resume(handle)) == -EAGAIN) | |||||
usleep(100); /* wait until the suspend flag is released */ | |||||
if (err < 0) { | |||||
err = snd_pcm_prepare(handle); | |||||
if (err < 0) | |||||
printf("Can't recovery from suspend, prepare failed: %s\n", snd_strerror(err)); | |||||
} | |||||
return 0; | |||||
} | |||||
return err; | |||||
} | |||||
static int set_hwformat( snd_pcm_t *handle, snd_pcm_hw_params_t *params ) | |||||
{ | |||||
int i; | |||||
int err; | |||||
for( i=0; i<NUMFORMATS; i++ ) { | |||||
/* set the sample format */ | |||||
err = snd_pcm_hw_params_set_format(handle, params, formats[i].format_id); | |||||
if (err == 0) { | |||||
format = i; | |||||
return 0; | |||||
} | |||||
} | |||||
return err; | |||||
} | |||||
static int set_hwparams(snd_pcm_t *handle, snd_pcm_hw_params_t *params, snd_pcm_access_t access, int rate, int channels, int period, int nperiods ) { | |||||
int err, dir=0; | |||||
unsigned int buffer_time; | |||||
unsigned int period_time; | |||||
unsigned int rrate; | |||||
unsigned int rchannels; | |||||
/* choose all parameters */ | |||||
err = snd_pcm_hw_params_any(handle, params); | |||||
if (err < 0) { | |||||
printf("Broken configuration for playback: no configurations available: %s\n", snd_strerror(err)); | |||||
return err; | |||||
} | |||||
/* set the interleaved read/write format */ | |||||
err = snd_pcm_hw_params_set_access(handle, params, access); | |||||
if (err < 0) { | |||||
printf("Access type not available for playback: %s\n", snd_strerror(err)); | |||||
return err; | |||||
} | |||||
/* set the sample format */ | |||||
err = set_hwformat(handle, params); | |||||
if (err < 0) { | |||||
printf("Sample format not available for playback: %s\n", snd_strerror(err)); | |||||
return err; | |||||
} | |||||
/* set the count of channels */ | |||||
rchannels = channels; | |||||
err = snd_pcm_hw_params_set_channels_near(handle, params, &rchannels); | |||||
if (err < 0) { | |||||
printf("Channels count (%i) not available for record: %s\n", channels, snd_strerror(err)); | |||||
return err; | |||||
} | |||||
if (rchannels != channels) { | |||||
printf("WARNING: chennel count does not match (requested %d got %d)\n", channels, rchannels); | |||||
num_channels = rchannels; | |||||
} | |||||
/* set the stream rate */ | |||||
rrate = rate; | |||||
err = snd_pcm_hw_params_set_rate_near(handle, params, &rrate, 0); | |||||
if (err < 0) { | |||||
printf("Rate %iHz not available for playback: %s\n", rate, snd_strerror(err)); | |||||
return err; | |||||
} | |||||
if (rrate != rate) { | |||||
printf("Rate doesn't match (requested %iHz, get %iHz)\n", rate, rrate); | |||||
return -EINVAL; | |||||
} | |||||
/* set the buffer time */ | |||||
buffer_time = 1000000*(uint64_t)period*nperiods/rate; | |||||
err = snd_pcm_hw_params_set_buffer_time_near(handle, params, &buffer_time, &dir); | |||||
if (err < 0) { | |||||
printf("Unable to set buffer time %i for playback: %s\n", 1000000*period*nperiods/rate, snd_strerror(err)); | |||||
return err; | |||||
} | |||||
err = snd_pcm_hw_params_get_buffer_size( params, &real_buffer_size ); | |||||
if (err < 0) { | |||||
printf("Unable to get buffer size back: %s\n", snd_strerror(err)); | |||||
return err; | |||||
} | |||||
if( real_buffer_size != nperiods * period ) { | |||||
printf( "WARNING: buffer size does not match: (requested %d, got %d)\n", nperiods * period, (int) real_buffer_size ); | |||||
} | |||||
/* set the period time */ | |||||
period_time = 1000000*(uint64_t)period/rate; | |||||
err = snd_pcm_hw_params_set_period_time_near(handle, params, &period_time, &dir); | |||||
if (err < 0) { | |||||
printf("Unable to set period time %i for playback: %s\n", 1000000*period/rate, snd_strerror(err)); | |||||
return err; | |||||
} | |||||
err = snd_pcm_hw_params_get_period_size(params, &real_period_size, NULL ); | |||||
if (err < 0) { | |||||
printf("Unable to get period size back: %s\n", snd_strerror(err)); | |||||
return err; | |||||
} | |||||
if( real_period_size != period ) { | |||||
printf( "WARNING: period size does not match: (requested %i, got %i)\n", period, (int)real_period_size ); | |||||
} | |||||
/* write the parameters to device */ | |||||
err = snd_pcm_hw_params(handle, params); | |||||
if (err < 0) { | |||||
printf("Unable to set hw params for playback: %s\n", snd_strerror(err)); | |||||
return err; | |||||
} | |||||
return 0; | |||||
} | |||||
static int set_swparams(snd_pcm_t *handle, snd_pcm_sw_params_t *swparams, int period, int nperiods) { | |||||
int err; | |||||
/* get the current swparams */ | |||||
err = snd_pcm_sw_params_current(handle, swparams); | |||||
if (err < 0) { | |||||
printf("Unable to determine current swparams for capture: %s\n", snd_strerror(err)); | |||||
return err; | |||||
} | |||||
/* start the transfer when the buffer is full */ | |||||
err = snd_pcm_sw_params_set_start_threshold(handle, swparams, period ); | |||||
if (err < 0) { | |||||
printf("Unable to set start threshold mode for capture: %s\n", snd_strerror(err)); | |||||
return err; | |||||
} | |||||
err = snd_pcm_sw_params_set_stop_threshold(handle, swparams, -1 ); | |||||
if (err < 0) { | |||||
printf("Unable to set start threshold mode for capture: %s\n", snd_strerror(err)); | |||||
return err; | |||||
} | |||||
/* allow the transfer when at least period_size samples can be processed */ | |||||
err = snd_pcm_sw_params_set_avail_min(handle, swparams, 1 ); | |||||
if (err < 0) { | |||||
printf("Unable to set avail min for capture: %s\n", snd_strerror(err)); | |||||
return err; | |||||
} | |||||
/* align all transfers to 1 sample */ | |||||
err = snd_pcm_sw_params_set_xfer_align(handle, swparams, 1); | |||||
if (err < 0) { | |||||
printf("Unable to set transfer align for capture: %s\n", snd_strerror(err)); | |||||
return err; | |||||
} | |||||
/* write the parameters to the playback device */ | |||||
err = snd_pcm_sw_params(handle, swparams); | |||||
if (err < 0) { | |||||
printf("Unable to set sw params for capture: %s\n", snd_strerror(err)); | |||||
return err; | |||||
} | |||||
return 0; | |||||
} | |||||
// ok... i only need this function to communicate with the alsa bloat api... | |||||
static snd_pcm_t *open_audiofd( char *device_name, int capture, int rate, int channels, int period, int nperiods ) { | |||||
int err; | |||||
snd_pcm_t *handle; | |||||
snd_pcm_hw_params_t *hwparams; | |||||
snd_pcm_sw_params_t *swparams; | |||||
snd_pcm_hw_params_alloca(&hwparams); | |||||
snd_pcm_sw_params_alloca(&swparams); | |||||
if ((err = snd_pcm_open(&(handle), device_name, capture ? SND_PCM_STREAM_CAPTURE : SND_PCM_STREAM_PLAYBACK, SND_PCM_NONBLOCK )) < 0) { | |||||
printf("Capture open error: %s\n", snd_strerror(err)); | |||||
return NULL; | |||||
} | |||||
if ((err = set_hwparams(handle, hwparams,SND_PCM_ACCESS_RW_INTERLEAVED, rate, channels, period, nperiods )) < 0) { | |||||
printf("Setting of hwparams failed: %s\n", snd_strerror(err)); | |||||
return NULL; | |||||
} | |||||
if ((err = set_swparams(handle, swparams, period, nperiods)) < 0) { | |||||
printf("Setting of swparams failed: %s\n", snd_strerror(err)); | |||||
return NULL; | |||||
} | |||||
//snd_pcm_start( handle ); | |||||
//snd_pcm_wait( handle, 200 ); | |||||
int num_null_samples = nperiods * period * channels; | |||||
char *tmp = alloca( num_null_samples * formats[format].sample_size ); | |||||
memset( tmp, 0, num_null_samples * formats[format].sample_size ); | |||||
snd_pcm_writei( handle, tmp, num_null_samples ); | |||||
return handle; | |||||
} | |||||
double hann( double x ) | |||||
{ | |||||
return 0.5 * (1.0 - cos( 2*M_PI * x ) ); | |||||
} | |||||
/** | |||||
* The process callback for this JACK application. | |||||
* It is called by JACK at the appropriate times. | |||||
*/ | |||||
int process (jack_nframes_t nframes, void *arg) { | |||||
int rlen; | |||||
int err; | |||||
snd_pcm_sframes_t delay = target_delay; | |||||
int i; | |||||
delay = (num_periods*period_size)-snd_pcm_avail( alsa_handle ) ; | |||||
delay -= jack_frames_since_cycle_start( client ); | |||||
// Do it the hard way. | |||||
// this is for compensating xruns etc... | |||||
if( delay > (target_delay+max_diff) ) { | |||||
snd_pcm_rewind( alsa_handle, delay - target_delay ); | |||||
output_new_delay = (int) delay; | |||||
delay = target_delay; | |||||
// Set the resample_rate... we need to adjust the offset integral, to do this. | |||||
// first look at the PI controller, this code is just a special case, which should never execute once | |||||
// everything is swung in. | |||||
offset_integral = - (resample_mean - static_resample_factor) * catch_factor * catch_factor2; | |||||
// Also clear the array. we are beginning a new control cycle. | |||||
for( i=0; i<smooth_size; i++ ) | |||||
offset_array[i] = 0.0; | |||||
} | |||||
if( delay < (target_delay-max_diff) ) { | |||||
output_new_delay = (int) delay; | |||||
while ((target_delay-delay) > 0) { | |||||
snd_pcm_uframes_t to_write = ((target_delay-delay) > 512) ? 512 : (target_delay-delay); | |||||
snd_pcm_writei( alsa_handle, tmpbuf, to_write ); | |||||
delay += to_write; | |||||
} | |||||
delay = target_delay; | |||||
// Set the resample_rate... we need to adjust the offset integral, to do this. | |||||
offset_integral = - (resample_mean - static_resample_factor) * catch_factor * catch_factor2; | |||||
// Also clear the array. we are beginning a new control cycle. | |||||
for( i=0; i<smooth_size; i++ ) | |||||
offset_array[i] = 0.0; | |||||
} | |||||
/* ok... now we should have target_delay +- max_diff on the alsa side. | |||||
* | |||||
* calculate the number of frames, we want to get. | |||||
*/ | |||||
double offset = delay - target_delay; | |||||
// Save offset. | |||||
offset_array[(offset_differential_index++)% smooth_size ] = offset; | |||||
// Build the mean of the windowed offset array | |||||
// basically fir lowpassing. | |||||
double smooth_offset = 0.0; | |||||
for( i=0; i<smooth_size; i++ ) | |||||
smooth_offset += | |||||
offset_array[ (i + offset_differential_index-1) % smooth_size] * window_array[i]; | |||||
smooth_offset /= (double) smooth_size; | |||||
// this is the integral of the smoothed_offset | |||||
offset_integral += smooth_offset; | |||||
// Clamp offset. | |||||
// the smooth offset still contains unwanted noise | |||||
// which would go straigth onto the resample coeff. | |||||
// it only used in the P component and the I component is used for the fine tuning anyways. | |||||
if( fabs( smooth_offset ) < pclamp ) | |||||
smooth_offset = 0.0; | |||||
// ok. now this is the PI controller. | |||||
// u(t) = K * ( e(t) + 1/T \int e(t') dt' ) | |||||
// K = 1/catch_factor and T = catch_factor2 | |||||
double current_resample_factor = static_resample_factor - smooth_offset / (double) catch_factor - offset_integral / (double) catch_factor / (double)catch_factor2; | |||||
// now quantize this value around resample_mean, so that the noise which is in the integral component doesnt hurt. | |||||
current_resample_factor = floor( (current_resample_factor - resample_mean) * controlquant + 0.5 ) / controlquant + resample_mean; | |||||
// Output "instrumentatio" gonna change that to real instrumentation in a few. | |||||
output_resampling_factor = (float) current_resample_factor; | |||||
output_diff = (float) smooth_offset; | |||||
output_integral = (float) offset_integral; | |||||
output_offset = (float) offset; | |||||
// Clamp a bit. | |||||
if( current_resample_factor < resample_lower_limit ) current_resample_factor = resample_lower_limit; | |||||
if( current_resample_factor > resample_upper_limit ) current_resample_factor = resample_upper_limit; | |||||
// Now Calculate how many samples we need. | |||||
rlen = ceil( ((double)nframes) * current_resample_factor )+2; | |||||
assert( rlen > 2 ); | |||||
// Calculate resample_mean so we can init ourselves to saner values. | |||||
resample_mean = 0.9999 * resample_mean + 0.0001 * current_resample_factor; | |||||
/* | |||||
* now this should do it... | |||||
*/ | |||||
outbuf = alloca( rlen * formats[format].sample_size * num_channels ); | |||||
resampbuf = alloca( rlen * sizeof( float ) ); | |||||
/* | |||||
* render jack ports to the outbuf... | |||||
*/ | |||||
int chn = 0; | |||||
JSList *node = playback_ports; | |||||
JSList *src_node = playback_srcs; | |||||
SRC_DATA src; | |||||
while ( node != NULL) | |||||
{ | |||||
jack_port_t *port = (jack_port_t *) node->data; | |||||
float *buf = jack_port_get_buffer (port, nframes); | |||||
SRC_STATE *src_state = src_node->data; | |||||
src.data_in = buf; | |||||
src.input_frames = nframes; | |||||
src.data_out = resampbuf; | |||||
src.output_frames = rlen; | |||||
src.end_of_input = 0; | |||||
src.src_ratio = current_resample_factor; | |||||
src_process( src_state, &src ); | |||||
formats[format].jack_to_soundcard( outbuf + format[formats].sample_size * chn, resampbuf, src.output_frames_gen, num_channels*format[formats].sample_size, NULL); | |||||
src_node = jack_slist_next (src_node); | |||||
node = jack_slist_next (node); | |||||
chn++; | |||||
} | |||||
// now write the output... | |||||
again: | |||||
err = snd_pcm_writei(alsa_handle, outbuf, src.output_frames_gen); | |||||
//err = snd_pcm_writei(alsa_handle, outbuf, src.output_frames_gen); | |||||
if( err < 0 ) { | |||||
printf( "err = %d\n", err ); | |||||
if (xrun_recovery(alsa_handle, err) < 0) { | |||||
printf("Write error: %s\n", snd_strerror(err)); | |||||
exit(EXIT_FAILURE); | |||||
} | |||||
goto again; | |||||
} | |||||
return 0; | |||||
} | |||||
/** | |||||
* the latency callback. | |||||
* sets up the latencies on the ports. | |||||
*/ | |||||
void | |||||
latency_cb (jack_latency_callback_mode_t mode, void *arg) | |||||
{ | |||||
jack_latency_range_t range; | |||||
JSList *node; | |||||
range.min = range.max = target_delay; | |||||
if (mode == JackCaptureLatency) { | |||||
for (node = capture_ports; node; node = jack_slist_next (node)) { | |||||
jack_port_t *port = node->data; | |||||
jack_port_set_latency_range (port, mode, &range); | |||||
} | |||||
} else { | |||||
for (node = playback_ports; node; node = jack_slist_next (node)) { | |||||
jack_port_t *port = node->data; | |||||
jack_port_set_latency_range (port, mode, &range); | |||||
} | |||||
} | |||||
} | |||||
/** | |||||
* Allocate the necessary jack ports... | |||||
*/ | |||||
void alloc_ports( int n_capture, int n_playback ) { | |||||
int port_flags = JackPortIsOutput | JackPortIsPhysical | JackPortIsTerminal; | |||||
int chn; | |||||
jack_port_t *port; | |||||
char buf[32]; | |||||
capture_ports = NULL; | |||||
for (chn = 0; chn < n_capture; chn++) | |||||
{ | |||||
snprintf (buf, sizeof(buf) - 1, "capture_%u", chn+1); | |||||
port = jack_port_register (client, buf, | |||||
JACK_DEFAULT_AUDIO_TYPE, | |||||
port_flags, 0); | |||||
if (!port) | |||||
{ | |||||
printf( "jacknet_client: cannot register port for %s", buf); | |||||
break; | |||||
} | |||||
capture_srcs = jack_slist_append( capture_srcs, src_new( 4-samplerate_quality, 1, NULL ) ); | |||||
capture_ports = jack_slist_append (capture_ports, port); | |||||
} | |||||
port_flags = JackPortIsInput; | |||||
playback_ports = NULL; | |||||
for (chn = 0; chn < n_playback; chn++) | |||||
{ | |||||
snprintf (buf, sizeof(buf) - 1, "playback_%u", chn+1); | |||||
port = jack_port_register (client, buf, | |||||
JACK_DEFAULT_AUDIO_TYPE, | |||||
port_flags, 0); | |||||
if (!port) | |||||
{ | |||||
printf( "jacknet_client: cannot register port for %s", buf); | |||||
break; | |||||
} | |||||
playback_srcs = jack_slist_append( playback_srcs, src_new( 4-samplerate_quality, 1, NULL ) ); | |||||
playback_ports = jack_slist_append (playback_ports, port); | |||||
} | |||||
} | |||||
/** | |||||
* This is the shutdown callback for this JACK application. | |||||
* It is called by JACK if the server ever shuts down or | |||||
* decides to disconnect the client. | |||||
*/ | |||||
void jack_shutdown (void *arg) { | |||||
exit (1); | |||||
} | |||||
/** | |||||
* be user friendly. | |||||
* be user friendly. | |||||
* be user friendly. | |||||
*/ | |||||
void printUsage() { | |||||
fprintf(stderr, "usage: alsa_out [options]\n" | |||||
"\n" | |||||
" -j <jack name> - client name\n" | |||||
" -d <alsa_device> \n" | |||||
" -c <channels> \n" | |||||
" -p <period_size> \n" | |||||
" -n <num_period> \n" | |||||
" -r <sample_rate> \n" | |||||
" -q <sample_rate quality [0..4]\n" | |||||
" -m <max_diff> \n" | |||||
" -t <target_delay> \n" | |||||
" -i turns on instrumentation\n" | |||||
" -v turns on printouts\n" | |||||
"\n"); | |||||
} | |||||
/** | |||||
* the main function.... | |||||
*/ | |||||
void | |||||
sigterm_handler( int signal ) | |||||
{ | |||||
quit = 1; | |||||
} | |||||
int main (int argc, char *argv[]) { | |||||
char jack_name[30] = "alsa_out"; | |||||
char alsa_device[30] = "hw:0"; | |||||
extern char *optarg; | |||||
extern int optind, optopt; | |||||
int errflg=0; | |||||
int c; | |||||
while ((c = getopt(argc, argv, "ivj:r:c:p:n:d:q:m:t:f:F:C:Q:s:")) != -1) { | |||||
switch(c) { | |||||
case 'j': | |||||
strcpy(jack_name,optarg); | |||||
break; | |||||
case 'r': | |||||
sample_rate = atoi(optarg); | |||||
break; | |||||
case 'c': | |||||
num_channels = atoi(optarg); | |||||
break; | |||||
case 'p': | |||||
period_size = atoi(optarg); | |||||
break; | |||||
case 'n': | |||||
num_periods = atoi(optarg); | |||||
break; | |||||
case 'd': | |||||
strcpy(alsa_device,optarg); | |||||
break; | |||||
case 't': | |||||
target_delay = atoi(optarg); | |||||
break; | |||||
case 'q': | |||||
samplerate_quality = atoi(optarg); | |||||
break; | |||||
case 'm': | |||||
max_diff = atoi(optarg); | |||||
break; | |||||
case 'f': | |||||
catch_factor = atoi(optarg); | |||||
break; | |||||
case 'F': | |||||
catch_factor2 = atoi(optarg); | |||||
break; | |||||
case 'C': | |||||
pclamp = (double) atoi(optarg); | |||||
break; | |||||
case 'Q': | |||||
controlquant = (double) atoi(optarg); | |||||
break; | |||||
case 'v': | |||||
verbose = 1; | |||||
break; | |||||
case 'i': | |||||
instrument = 1; | |||||
break; | |||||
case 's': | |||||
smooth_size = atoi(optarg); | |||||
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); | |||||
} | |||||
if( (samplerate_quality < 0) || (samplerate_quality > 4) ) { | |||||
fprintf (stderr, "invalid samplerate quality\n"); | |||||
return 1; | |||||
} | |||||
if ((client = jack_client_open (jack_name, 0, NULL)) == 0) { | |||||
fprintf (stderr, "jack server not running?\n"); | |||||
return 1; | |||||
} | |||||
/* tell the JACK server to call `process()' whenever | |||||
there is work to be done. | |||||
*/ | |||||
jack_set_process_callback (client, process, 0); | |||||
/* tell the JACK server to call `jack_shutdown()' if | |||||
it ever shuts down, either entirely, or if it | |||||
just decides to stop calling us. | |||||
*/ | |||||
jack_on_shutdown (client, jack_shutdown, 0); | |||||
if (jack_set_latency_callback) | |||||
jack_set_latency_callback (client, latency_cb, 0); | |||||
// get jack sample_rate | |||||
jack_sample_rate = jack_get_sample_rate( client ); | |||||
if( !sample_rate ) | |||||
sample_rate = jack_sample_rate; | |||||
static_resample_factor = (double) sample_rate / (double) jack_sample_rate; | |||||
resample_lower_limit = static_resample_factor * 0.25; | |||||
resample_upper_limit = static_resample_factor * 4.0; | |||||
resample_mean = static_resample_factor; | |||||
offset_array = malloc( sizeof(double) * smooth_size ); | |||||
if( offset_array == NULL ) { | |||||
fprintf( stderr, "no memory for offset_array !!!\n" ); | |||||
exit(20); | |||||
} | |||||
window_array = malloc( sizeof(double) * smooth_size ); | |||||
if( window_array == NULL ) { | |||||
fprintf( stderr, "no memory for window_array !!!\n" ); | |||||
exit(20); | |||||
} | |||||
int i; | |||||
for( i=0; i<smooth_size; i++ ) { | |||||
offset_array[i] = 0.0; | |||||
window_array[i] = hann( (double) i / ((double) smooth_size - 1.0) ); | |||||
} | |||||
jack_buffer_size = jack_get_buffer_size( client ); | |||||
// Setup target delay and max_diff for the normal user, who does not play with them... | |||||
if( !target_delay ) | |||||
target_delay = (num_periods*period_size / 2) - jack_buffer_size/2; | |||||
if( !max_diff ) | |||||
max_diff = target_delay; | |||||
if( max_diff > target_delay ) { | |||||
fprintf( stderr, "target_delay (%d) cant be smaller than max_diff(%d)\n", target_delay, max_diff ); | |||||
exit(20); | |||||
} | |||||
if( (target_delay+max_diff) > (num_periods*period_size) ) { | |||||
fprintf( stderr, "target_delay+max_diff (%d) cant be bigger than buffersize(%d)\n", target_delay+max_diff, num_periods*period_size ); | |||||
exit(20); | |||||
} | |||||
// now open the alsa fd... | |||||
alsa_handle = open_audiofd( alsa_device, 0, sample_rate, num_channels, period_size, num_periods); | |||||
if( alsa_handle == 0 ) | |||||
exit(20); | |||||
printf( "selected sample format: %s\n", formats[format].name ); | |||||
// alloc input ports, which are blasted out to alsa... | |||||
alloc_ports( 0, num_channels ); | |||||
outbuf = malloc( num_periods * period_size * formats[format].sample_size * num_channels ); | |||||
resampbuf = malloc( num_periods * period_size * sizeof( float ) ); | |||||
tmpbuf = malloc( 512 * formats[format].sample_size * num_channels ); | |||||
if ((outbuf == NULL) || (resampbuf == NULL) || (tmpbuf == NULL)) | |||||
{ | |||||
fprintf( stderr, "no memory for buffers.\n" ); | |||||
exit(20); | |||||
} | |||||
/* tell the JACK server that we are ready to roll */ | |||||
if (jack_activate (client)) { | |||||
fprintf (stderr, "cannot activate client"); | |||||
return 1; | |||||
} | |||||
signal( SIGTERM, sigterm_handler ); | |||||
signal( SIGINT, sigterm_handler ); | |||||
if( verbose ) { | |||||
while(!quit) { | |||||
usleep(500000); | |||||
if( output_new_delay ) { | |||||
printf( "delay = %d\n", output_new_delay ); | |||||
output_new_delay = 0; | |||||
} | |||||
printf( "res: %f, \tdiff = %f, \toffset = %f \n", output_resampling_factor, output_diff, output_offset ); | |||||
} | |||||
} else if( instrument ) { | |||||
printf( "# n\tresamp\tdiff\toffseti\tintegral\n"); | |||||
int n=0; | |||||
while(!quit) { | |||||
usleep(1000); | |||||
printf( "%d\t%f\t%f\t%f\t%f\n", n++, output_resampling_factor, output_diff, output_offset, output_integral ); | |||||
} | |||||
} else { | |||||
while(!quit) | |||||
{ | |||||
usleep(500000); | |||||
if( output_new_delay ) { | |||||
printf( "delay = %d\n", output_new_delay ); | |||||
output_new_delay = 0; | |||||
} | |||||
} | |||||
} | |||||
jack_deactivate( client ); | |||||
jack_client_close (client); | |||||
exit (0); | |||||
} | |||||
@@ -1,125 +0,0 @@ | |||||
/* | |||||
* bufsize.c -- change JACK buffer size. | |||||
* | |||||
* Copyright (C) 2003 Jack O'Quin. | |||||
* | |||||
* This program 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. | |||||
* | |||||
* This program 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 this program; if not, write to the Free Software | |||||
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. | |||||
*/ | |||||
#include <stdio.h> | |||||
#include <errno.h> | |||||
#include <unistd.h> | |||||
#include <signal.h> | |||||
#include <stdlib.h> | |||||
#include <string.h> | |||||
#include <jack/jack.h> | |||||
#include <jack/transport.h> | |||||
char *package; /* program name */ | |||||
jack_client_t *client; | |||||
jack_nframes_t nframes; | |||||
int just_print_bufsize=0; | |||||
void jack_shutdown(void *arg) | |||||
{ | |||||
fprintf(stderr, "JACK shut down, exiting ...\n"); | |||||
exit(1); | |||||
} | |||||
void signal_handler(int sig) | |||||
{ | |||||
jack_client_close(client); | |||||
fprintf(stderr, "signal received, exiting ...\n"); | |||||
exit(0); | |||||
} | |||||
void parse_arguments(int argc, char *argv[]) | |||||
{ | |||||
/* basename $0 */ | |||||
package = strrchr(argv[0], '/'); | |||||
if (package == 0) | |||||
package = argv[0]; | |||||
else | |||||
package++; | |||||
if (argc==1) { | |||||
just_print_bufsize = 1; | |||||
return; | |||||
} | |||||
if (argc < 2) { | |||||
fprintf(stderr, "usage: %s <bufsize>\n", package); | |||||
exit(9); | |||||
} | |||||
if (strspn (argv[1], "0123456789") != strlen (argv[1])) { | |||||
fprintf(stderr, "usage: %s <bufsize>\n", package); | |||||
exit(8); | |||||
} | |||||
nframes = strtoul(argv[1], NULL, 0); | |||||
if (errno == ERANGE) { | |||||
fprintf(stderr, "%s: invalid buffer size: %s (range is 1-16384)\n", | |||||
package, argv[1]); | |||||
exit(2); | |||||
} | |||||
if (nframes < 1 || nframes > 16384) { | |||||
fprintf(stderr, "%s: invalid buffer size: %s (range is 1-16384)\n", | |||||
package, argv[1]); | |||||
exit(3); | |||||
} | |||||
} | |||||
void silent_function( const char *ignore ) | |||||
{ | |||||
} | |||||
int main(int argc, char *argv[]) | |||||
{ | |||||
int rc; | |||||
parse_arguments(argc, argv); | |||||
if (just_print_bufsize) | |||||
jack_set_info_function( silent_function ); | |||||
/* become a JACK client */ | |||||
if ((client = jack_client_open(package, JackNullOption, NULL)) == 0) { | |||||
fprintf(stderr, "JACK server not running?\n"); | |||||
exit(1); | |||||
} | |||||
signal(SIGQUIT, signal_handler); | |||||
signal(SIGTERM, signal_handler); | |||||
signal(SIGHUP, signal_handler); | |||||
signal(SIGINT, signal_handler); | |||||
jack_on_shutdown(client, jack_shutdown, 0); | |||||
if (just_print_bufsize) { | |||||
fprintf(stdout, "%d\n", jack_get_buffer_size( client ) ); | |||||
rc=0; | |||||
} | |||||
else | |||||
{ | |||||
rc = jack_set_buffer_size(client, nframes); | |||||
if (rc) | |||||
fprintf(stderr, "jack_set_buffer_size(): %s\n", strerror(rc)); | |||||
} | |||||
jack_client_close(client); | |||||
return rc; | |||||
} |
@@ -1,222 +0,0 @@ | |||||
/* | |||||
Copyright (C) 2002 Jeremy Hall | |||||
This program 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. | |||||
This program 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 this program; if not, write to the Free Software | |||||
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. | |||||
*/ | |||||
#include <stdio.h> | |||||
#include <errno.h> | |||||
#include <unistd.h> | |||||
#include <string.h> | |||||
#include <stdlib.h> | |||||
#include <getopt.h> | |||||
#include <config.h> | |||||
#include <jack/jack.h> | |||||
#include <jack/session.h> | |||||
#define TRUE 1 | |||||
#define FALSE 0 | |||||
void | |||||
show_version (char *my_name) | |||||
{ | |||||
fprintf (stderr, "%s: JACK Audio Connection Kit version " VERSION "\n", my_name); | |||||
} | |||||
void | |||||
show_usage (char *my_name) | |||||
{ | |||||
show_version (my_name); | |||||
fprintf (stderr, "\nusage: %s [options] port1 port2\n", my_name); | |||||
fprintf (stderr, "Connects two JACK ports together.\n\n"); | |||||
fprintf (stderr, " -s, --server <name> Connect to the jack server named <name>\n"); | |||||
fprintf (stderr, " -v, --version Output version information and exit\n"); | |||||
fprintf (stderr, " -h, --help Display this help message\n\n"); | |||||
fprintf (stderr, "For more information see http://jackaudio.org/\n"); | |||||
} | |||||
int | |||||
main (int argc, char *argv[]) | |||||
{ | |||||
jack_client_t *client; | |||||
jack_status_t status; | |||||
char *server_name = NULL; | |||||
int c; | |||||
int option_index; | |||||
jack_options_t options = JackNoStartServer; | |||||
char *my_name = strrchr(argv[0], '/'); | |||||
jack_port_t *src_port = 0; | |||||
jack_port_t *dst_port = 0; | |||||
jack_port_t *port1 = 0; | |||||
jack_port_t *port2 = 0; | |||||
char portA[300]; | |||||
char portB[300]; | |||||
int use_uuid=0; | |||||
int connecting, disconnecting; | |||||
int port1_flags, port2_flags; | |||||
int rc = 1; | |||||
struct option long_options[] = { | |||||
{ "server", 1, 0, 's' }, | |||||
{ "help", 0, 0, 'h' }, | |||||
{ "version", 0, 0, 'v' }, | |||||
{ "uuid", 0, 0, 'u' }, | |||||
{ 0, 0, 0, 0 } | |||||
}; | |||||
while ((c = getopt_long (argc, argv, "s:hvu", 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 'u': | |||||
use_uuid = 1; | |||||
break; | |||||
case 'h': | |||||
show_usage (my_name); | |||||
return 1; | |||||
break; | |||||
case 'v': | |||||
show_version (my_name); | |||||
return 1; | |||||
break; | |||||
default: | |||||
show_usage (my_name); | |||||
return 1; | |||||
break; | |||||
} | |||||
} | |||||
connecting = disconnecting = FALSE; | |||||
if (my_name == 0) { | |||||
my_name = argv[0]; | |||||
} else { | |||||
my_name ++; | |||||
} | |||||
if (strstr(my_name, "disconnect")) { | |||||
disconnecting = 1; | |||||
} else if (strstr(my_name, "connect")) { | |||||
connecting = 1; | |||||
} else { | |||||
fprintf(stderr, "ERROR! client should be called jack_connect or jack_disconnect. client is called %s\n", my_name); | |||||
return 1; | |||||
} | |||||
if (argc < 3) show_usage(my_name); | |||||
/* try to become a client of the JACK server */ | |||||
if ((client = jack_client_open (my_name, options, &status, server_name)) == 0) { | |||||
fprintf (stderr, "jack server not running?\n"); | |||||
return 1; | |||||
} | |||||
/* find the two ports */ | |||||
if( use_uuid ) { | |||||
char *tmpname; | |||||
char *clientname; | |||||
char *portname; | |||||
tmpname = strdup( argv[argc-1] ); | |||||
portname = strchr( tmpname, ':' ); | |||||
portname[0] = '\0'; | |||||
portname+=1; | |||||
clientname = jack_get_client_name_by_uuid( client, tmpname ); | |||||
if( clientname ) { | |||||
snprintf( portA, sizeof(portA), "%s:%s", clientname, portname ); | |||||
jack_free( clientname ); | |||||
} else { | |||||
snprintf( portA, sizeof(portA), "%s", argv[argc-1] ); | |||||
} | |||||
free( tmpname ); | |||||
tmpname = strdup( argv[argc-2] ); | |||||
portname = strchr( tmpname, ':' ); | |||||
portname[0] = '\0'; | |||||
portname+=1; | |||||
clientname = jack_get_client_name_by_uuid( client, tmpname ); | |||||
if( clientname ) { | |||||
snprintf( portB, sizeof(portB), "%s:%s", clientname, portname ); | |||||
jack_free( clientname ); | |||||
} else { | |||||
snprintf( portB, sizeof(portB), "%s", argv[argc-2] ); | |||||
} | |||||
free( tmpname ); | |||||
} else { | |||||
snprintf( portA, sizeof(portA), "%s", argv[argc-1] ); | |||||
snprintf( portB, sizeof(portB), "%s", argv[argc-2] ); | |||||
} | |||||
if ((port1 = jack_port_by_name(client, portA)) == 0) { | |||||
fprintf (stderr, "ERROR %s not a valid port\n", portA); | |||||
goto exit; | |||||
} | |||||
if ((port2 = jack_port_by_name(client, portB)) == 0) { | |||||
fprintf (stderr, "ERROR %s not a valid port\n", portB); | |||||
goto exit; | |||||
} | |||||
port1_flags = jack_port_flags (port1); | |||||
port2_flags = jack_port_flags (port2); | |||||
if (port1_flags & JackPortIsInput) { | |||||
if (port2_flags & JackPortIsOutput) { | |||||
src_port = port2; | |||||
dst_port = port1; | |||||
} | |||||
} else { | |||||
if (port2_flags & JackPortIsInput) { | |||||
src_port = port1; | |||||
dst_port = port2; | |||||
} | |||||
} | |||||
if (!src_port || !dst_port) { | |||||
fprintf (stderr, "arguments must include 1 input port and 1 output port\n"); | |||||
goto exit; | |||||
} | |||||
/* connect the ports. Note: you can't do this before | |||||
the client is activated (this may change in the future). | |||||
*/ | |||||
if (connecting) { | |||||
if (jack_connect(client, jack_port_name(src_port), jack_port_name(dst_port))) { | |||||
goto exit; | |||||
} | |||||
} | |||||
if (disconnecting) { | |||||
if (jack_disconnect(client, jack_port_name(src_port), jack_port_name(dst_port))) { | |||||
goto exit; | |||||
} | |||||
} | |||||
/* everything was ok, so setting exitcode to 0 */ | |||||
rc = 0; | |||||
exit: | |||||
jack_client_close (client); | |||||
exit (rc); | |||||
} | |||||
@@ -1,92 +0,0 @@ | |||||
/* | |||||
Copyright (C) 2007 Paul Davis | |||||
This program 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. | |||||
This program 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 this program; if not, write to the Free Software | |||||
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. | |||||
*/ | |||||
#include <stdio.h> | |||||
#include <errno.h> | |||||
#include <unistd.h> | |||||
#include <string.h> | |||||
#include <stdlib.h> | |||||
#include <jack/jack.h> | |||||
void | |||||
port_callback (jack_port_id_t port, int yn, void* arg) | |||||
{ | |||||
printf ("Port %d %s\n", port, (yn ? "registered" : "unregistered")); | |||||
} | |||||
void | |||||
connect_callback (jack_port_id_t a, jack_port_id_t b, int yn, void* arg) | |||||
{ | |||||
printf ("Ports %d and %d %s\n", a, b, (yn ? "connected" : "disconnected")); | |||||
} | |||||
void | |||||
client_callback (const char* client, int yn, void* arg) | |||||
{ | |||||
printf ("Client %s %s\n", client, (yn ? "registered" : "unregistered")); | |||||
} | |||||
int | |||||
graph_callback (void* arg) | |||||
{ | |||||
printf ("Graph reordered\n"); | |||||
return 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_activate (client)) { | |||||
fprintf (stderr, "cannot activate client"); | |||||
return 1; | |||||
} | |||||
sleep (-1); | |||||
exit (0); | |||||
} | |||||
@@ -1,86 +0,0 @@ | |||||
/* | |||||
* freewheel - start/stop JACK "freewheeling" mode | |||||
* | |||||
* Copyright (C) 2003 Paul Davis. | |||||
* | |||||
* This program 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. | |||||
* | |||||
* This program 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 this program; if not, write to the Free Software | |||||
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. | |||||
*/ | |||||
#include <stdio.h> | |||||
#include <errno.h> | |||||
#include <unistd.h> | |||||
#include <signal.h> | |||||
#include <stdlib.h> | |||||
#include <string.h> | |||||
#include <jack/jack.h> | |||||
#include <jack/transport.h> | |||||
char *package; /* program name */ | |||||
jack_client_t *client; | |||||
int onoff; | |||||
void jack_shutdown(void *arg) | |||||
{ | |||||
fprintf(stderr, "JACK shut down, exiting ...\n"); | |||||
exit(1); | |||||
} | |||||
void signal_handler(int sig) | |||||
{ | |||||
jack_client_close(client); | |||||
fprintf(stderr, "signal received, exiting ...\n"); | |||||
exit(0); | |||||
} | |||||
void parse_arguments(int argc, char *argv[]) | |||||
{ | |||||
if (argc < 2) { | |||||
fprintf(stderr, "usage: %s y|n\n", package); | |||||
exit(9); | |||||
} | |||||
if (argv[1][0] == 'y' || argv[1][0] == 'Y' || argv[1][0] == '1') { | |||||
onoff = 1; | |||||
} else { | |||||
onoff = 0; | |||||
} | |||||
} | |||||
int | |||||
main (int argc, char *argv[]) | |||||
{ | |||||
parse_arguments (argc, argv); | |||||
/* become a JACK client */ | |||||
if ((client = jack_client_open ("freewheel", JackNullOption, NULL)) == 0) { | |||||
fprintf (stderr, "JACK server not running?\n"); | |||||
exit(1); | |||||
} | |||||
signal (SIGQUIT, signal_handler); | |||||
signal (SIGTERM, signal_handler); | |||||
signal (SIGHUP, signal_handler); | |||||
signal (SIGINT, signal_handler); | |||||
jack_on_shutdown (client, jack_shutdown, 0); | |||||
if (jack_set_freewheel (client, onoff)) { | |||||
fprintf (stderr, "failed to reset freewheel mode\n"); | |||||
} | |||||
jack_client_close(client); | |||||
return 0; | |||||
} |
@@ -1,260 +0,0 @@ | |||||
/* | |||||
Copyright (C) 2003-2008 Fons Adriaensen <fons@kokkinizita.net> | |||||
This program 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. | |||||
This program 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 this program; if not, write to the Free Software | |||||
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. | |||||
*/ | |||||
// -------------------------------------------------------------------------------- | |||||
#include <stdlib.h> | |||||
#include <stdio.h> | |||||
#include <math.h> | |||||
#include <unistd.h> | |||||
#include <jack/jack.h> | |||||
struct Freq | |||||
{ | |||||
int p; | |||||
int f; | |||||
float a; | |||||
float xa; | |||||
float ya; | |||||
float xf; | |||||
float yf; | |||||
}; | |||||
struct MTDM | |||||
{ | |||||
double _del; | |||||
double _err; | |||||
int _cnt; | |||||
int _inv; | |||||
struct Freq _freq [5]; | |||||
}; | |||||
struct MTDM * mtdm_new (void) | |||||
{ | |||||
int i; | |||||
struct Freq *F; | |||||
struct MTDM *retval = malloc( sizeof(struct MTDM) ); | |||||
if (retval==NULL) | |||||
return NULL; | |||||
retval->_cnt = 0; | |||||
retval->_inv = 0; | |||||
retval->_freq [0].f = 4096; | |||||
retval->_freq [1].f = 512; | |||||
retval->_freq [2].f = 1088; | |||||
retval->_freq [3].f = 1544; | |||||
retval->_freq [4].f = 2049; | |||||
retval->_freq [0].a = 0.2f; | |||||
retval->_freq [1].a = 0.1f; | |||||
retval->_freq [2].a = 0.1f; | |||||
retval->_freq [3].a = 0.1f; | |||||
retval->_freq [4].a = 0.1f; | |||||
for (i = 0, F = retval->_freq; i < 5; i++, F++) | |||||
{ | |||||
F->p = 128; | |||||
F->xa = F->ya = 0.0f; | |||||
F->xf = F->yf = 0.0f; | |||||
} | |||||
return retval; | |||||
} | |||||
int mtdm_process (struct MTDM *self, size_t len, float *ip, float *op) | |||||
{ | |||||
int i; | |||||
float vip, vop, a, c, s; | |||||
struct Freq *F; | |||||
while (len--) | |||||
{ | |||||
vop = 0.0f; | |||||
vip = *ip++; | |||||
for (i = 0, F = self->_freq; i < 5; i++, F++) | |||||
{ | |||||
a = 2 * (float) M_PI * (F->p & 65535) / 65536.0; | |||||
F->p += F->f; | |||||
c = cosf (a); | |||||
s = -sinf (a); | |||||
vop += F->a * s; | |||||
F->xa += s * vip; | |||||
F->ya += c * vip; | |||||
} | |||||
*op++ = vop; | |||||
if (++(self->_cnt) == 16) | |||||
{ | |||||
for (i = 0, F = self->_freq; i < 5; i++, F++) | |||||
{ | |||||
F->xf += 1e-3f * (F->xa - F->xf + 1e-20); | |||||
F->yf += 1e-3f * (F->ya - F->yf + 1e-20); | |||||
F->xa = F->ya = 0.0f; | |||||
} | |||||
self->_cnt = 0; | |||||
} | |||||
} | |||||
return 0; | |||||
} | |||||
int mtdm_resolve (struct MTDM *self) | |||||
{ | |||||
int i, k, m; | |||||
double d, e, f0, p; | |||||
struct Freq *F = self->_freq; | |||||
if (hypot (F->xf, F->yf) < 0.01) return -1; | |||||
d = atan2 (F->yf, F->xf) / (2 * M_PI); | |||||
if (self->_inv) d += 0.5f; | |||||
if (d > 0.5f) d -= 1.0f; | |||||
f0 = self->_freq [0].f; | |||||
m = 1; | |||||
self->_err = 0.0; | |||||
for (i = 0; i < 4; i++) | |||||
{ | |||||
F++; | |||||
p = atan2 (F->yf, F->xf) / (2 * M_PI) - d * F->f / f0; | |||||
if (self->_inv) p += 0.5f; | |||||
p -= floor (p); | |||||
p *= 8; | |||||
k = (int)(floor (p + 0.5)); | |||||
e = fabs (p - k); | |||||
if (e > self->_err) self->_err = e; | |||||
if (e > 0.4) return 1; | |||||
d += m * (k & 7); | |||||
m *= 8; | |||||
} | |||||
self->_del = 16 * d; | |||||
return 0; | |||||
} | |||||
void mtdm_invert (struct MTDM *self) | |||||
{ | |||||
self->_inv ^= 1; | |||||
} | |||||
// -------------------------------------------------------------------------------- | |||||
static struct MTDM *mtdm; | |||||
static jack_client_t *jack_handle; | |||||
static jack_port_t *jack_capt; | |||||
static jack_port_t *jack_play; | |||||
jack_latency_range_t capture_latency = {-1, -1}; | |||||
jack_latency_range_t playback_latency = {-1, -1}; | |||||
void | |||||
latency_cb (jack_latency_callback_mode_t mode, void *arg) | |||||
{ | |||||
jack_latency_range_t range; | |||||
range.min = range.max = 0; | |||||
if (mode == JackCaptureLatency) { | |||||
jack_port_set_latency_range (jack_play, mode, &range); | |||||
jack_port_get_latency_range (jack_capt, mode, &range); | |||||
if ((range.min != capture_latency.min) || (range.max != capture_latency.max)) { | |||||
capture_latency = range; | |||||
printf ("new capture latency: [%d, %d]\n", range.min, range.max); | |||||
} | |||||
} else { | |||||
jack_port_set_latency_range (jack_capt, mode, &range); | |||||
jack_port_get_latency_range (jack_play, mode, &range); | |||||
if ((range.min != playback_latency.min) || (range.max != playback_latency.max)) { | |||||
playback_latency = range; | |||||
printf ("new playback latency: [%d, %d]\n", range.min, range.max); | |||||
} | |||||
} | |||||
} | |||||
int jack_callback (jack_nframes_t nframes, void *arg) | |||||
{ | |||||
float *ip, *op; | |||||
ip = (float *)(jack_port_get_buffer (jack_capt, nframes)); | |||||
op = (float *)(jack_port_get_buffer (jack_play, nframes)); | |||||
mtdm_process (mtdm, nframes, ip, op); | |||||
return 0; | |||||
} | |||||
int main (int ac, char *av []) | |||||
{ | |||||
float t; | |||||
jack_status_t s; | |||||
mtdm = mtdm_new(); | |||||
jack_handle = jack_client_open ("jack_delay", JackNoStartServer, &s); | |||||
if (jack_handle == 0) | |||||
{ | |||||
fprintf (stderr, "Can't connect to Jack, is the server running ?\n"); | |||||
exit (1); | |||||
} | |||||
jack_set_process_callback (jack_handle, jack_callback, 0); | |||||
if (jack_set_latency_callback) | |||||
jack_set_latency_callback (jack_handle, latency_cb, 0); | |||||
jack_capt = jack_port_register (jack_handle, "in", JACK_DEFAULT_AUDIO_TYPE, JackPortIsInput, 0); | |||||
jack_play = jack_port_register (jack_handle, "out", JACK_DEFAULT_AUDIO_TYPE, JackPortIsOutput, 0); | |||||
t = 1000.0f / jack_get_sample_rate (jack_handle); | |||||
if (jack_activate (jack_handle)) | |||||
{ | |||||
fprintf(stderr, "Can't activate Jack"); | |||||
return 1; | |||||
} | |||||
while (1) | |||||
{ | |||||
#ifdef WIN32 | |||||
Sleep (250); | |||||
#else | |||||
usleep (250000); | |||||
#endif | |||||
if (mtdm_resolve (mtdm) < 0) printf ("Signal below threshold...\n"); | |||||
else | |||||
{ | |||||
jack_nframes_t systemic_latency; | |||||
if (mtdm->_err > 0.3) | |||||
{ | |||||
mtdm_invert ( mtdm ); | |||||
mtdm_resolve ( mtdm ); | |||||
} | |||||
systemic_latency = (jack_nframes_t) floor (mtdm->_del - (capture_latency.max + playback_latency.max)); | |||||
printf ("%10.3lf frames %10.3lf ms total roundtrip latency\n\textra loopback latency: %u frames\n\tuse %u for the backend arguments -I and -O", mtdm->_del, mtdm->_del * t, | |||||
systemic_latency, systemic_latency/2); | |||||
if (mtdm->_err > 0.2) printf (" ??"); | |||||
if (mtdm->_inv) printf (" Inv"); | |||||
printf ("\n"); | |||||
} | |||||
} | |||||
return 0; | |||||
} | |||||
// -------------------------------------------------------------------------------- |
@@ -1,170 +0,0 @@ | |||||
#include <stdio.h> | |||||
#include <stdlib.h> | |||||
#include <string.h> | |||||
#include <signal.h> | |||||
#include <unistd.h> | |||||
#include <getopt.h> | |||||
#include <jack/jack.h> | |||||
#include <jack/intclient.h> | |||||
jack_client_t *client; | |||||
jack_intclient_t intclient; | |||||
char *client_name; | |||||
char *intclient_name; | |||||
char *load_name; | |||||
char *load_init = NULL; | |||||
char *server_name = NULL; | |||||
int wait_opt = 0; | |||||
void | |||||
signal_handler (int sig) | |||||
{ | |||||
jack_status_t status; | |||||
fprintf (stderr, "signal received, unloading..."); | |||||
status = jack_internal_client_unload (client, intclient); | |||||
if (status & JackFailure) | |||||
fprintf (stderr, "(failed), status = 0x%2.0x\n", status); | |||||
else | |||||
fprintf (stderr, "(succeeded)\n"); | |||||
jack_client_close (client); | |||||
exit (0); | |||||
} | |||||
void | |||||
show_usage () | |||||
{ | |||||
fprintf (stderr, "usage: %s [ options ] client-name [ load-name " | |||||
"[ init-string]]\n\noptions:\n", client_name); | |||||
fprintf (stderr, | |||||
"\t-h, --help \t\t print help message\n" | |||||
"\t-i, --init string\t initialize string\n" | |||||
"\t-s, --server name\t select JACK server\n" | |||||
"\t-w, --wait \t\t wait for signal, then unload\n" | |||||
"\n" | |||||
); | |||||
} | |||||
int | |||||
parse_args (int argc, char *argv[]) | |||||
{ | |||||
int c; | |||||
int option_index = 0; | |||||
char *short_options = "hi:s:w"; | |||||
struct option long_options[] = { | |||||
{ "help", 0, 0, 'h' }, | |||||
{ "init", required_argument, 0, 'i' }, | |||||
{ "server", required_argument, 0, 's' }, | |||||
{ "wait", 0, 0, 'w' }, | |||||
{ 0, 0, 0, 0 } | |||||
}; | |||||
client_name = strrchr(argv[0], '/'); | |||||
if (client_name == NULL) { | |||||
client_name = argv[0]; | |||||
} else { | |||||
client_name++; | |||||
} | |||||
while ((c = getopt_long (argc, argv, short_options, long_options, | |||||
&option_index)) >= 0) { | |||||
switch (c) { | |||||
case 'i': | |||||
load_init = optarg; | |||||
break; | |||||
case 's': | |||||
server_name = optarg; | |||||
break; | |||||
case 'w': | |||||
wait_opt = 1; | |||||
break; | |||||
case 'h': | |||||
default: | |||||
show_usage (); | |||||
return 1; | |||||
} | |||||
} | |||||
if (optind == argc) { /* no positional args? */ | |||||
show_usage (); | |||||
return 1; | |||||
} | |||||
if (optind < argc) | |||||
load_name = intclient_name = argv[optind++]; | |||||
if (optind < argc) | |||||
load_name = argv[optind++]; | |||||
if (optind < argc) | |||||
load_init = argv[optind++]; | |||||
//fprintf (stderr, "client-name = `%s', load-name = `%s', " | |||||
// "load-init = `%s', wait = %d\n", | |||||
// intclient_name, load_name, load_init, wait_opt); | |||||
return 0; /* args OK */ | |||||
} | |||||
int | |||||
main (int argc, char *argv[]) | |||||
{ | |||||
jack_status_t status; | |||||
/* parse and validate command arguments */ | |||||
if (parse_args (argc, argv)) | |||||
exit (1); /* invalid command line */ | |||||
/* first, become a JACK client */ | |||||
client = jack_client_open (client_name, JackServerName, | |||||
&status, server_name); | |||||
if (client == NULL) { | |||||
fprintf (stderr, "jack_client_open() failed, " | |||||
"status = 0x%2.0x\n", status); | |||||
if (status & JackServerFailed) { | |||||
fprintf (stderr, "Unable to connect to JACK server\n"); | |||||
} | |||||
exit (1); | |||||
} | |||||
if (status & JackServerStarted) { | |||||
fprintf (stderr, "JACK server started\n"); | |||||
} | |||||
if (status & JackNameNotUnique) { | |||||
client_name = jack_get_client_name(client); | |||||
fprintf (stderr, "unique name `%s' assigned\n", client_name); | |||||
} | |||||
/* then, load the internal client */ | |||||
intclient = jack_internal_client_load (client, intclient_name, | |||||
(JackLoadName|JackLoadInit), | |||||
&status, load_name, load_init); | |||||
if (status & JackFailure) { | |||||
fprintf (stderr, "could not load %s, status = 0x%2.0x\n", | |||||
load_name, status); | |||||
return 2; | |||||
} | |||||
if (status & JackNameNotUnique) { | |||||
intclient_name = | |||||
jack_get_internal_client_name (client, intclient); | |||||
fprintf (stderr, "unique internal client name `%s' assigned\n", | |||||
intclient_name); | |||||
} | |||||
fprintf (stdout, "%s is running.\n", load_name); | |||||
if (wait_opt) { | |||||
/* define a signal handler to unload the client, then | |||||
* wait for it to exit */ | |||||
signal (SIGQUIT, signal_handler); | |||||
signal (SIGTERM, signal_handler); | |||||
signal (SIGHUP, signal_handler); | |||||
signal (SIGINT, signal_handler); | |||||
while (1) { | |||||
sleep (1); | |||||
} | |||||
} | |||||
return 0; | |||||
} | |||||
@@ -1,76 +0,0 @@ | |||||
#include <string.h> | |||||
#include <stdlib.h> | |||||
#include <stdio.h> | |||||
#include <jack/jack.h> | |||||
#include <jack/intclient.h> | |||||
int | |||||
main (int argc, char *argv[]) | |||||
{ | |||||
char *my_name; | |||||
char *client_name; | |||||
jack_client_t *client; | |||||
jack_status_t status; | |||||
jack_intclient_t intclient; | |||||
/* validate args */ | |||||
if ((argc < 2) || (argc > 3)) { | |||||
fprintf (stderr, "usage: %s client-name [ server-name ]]\n", | |||||
argv[0]); | |||||
return 1; | |||||
} | |||||
/* use `basename $0` for my own client name */ | |||||
my_name = strrchr(argv[0], '/'); | |||||
if (my_name == 0) { | |||||
my_name = argv[0]; | |||||
} else { | |||||
my_name++; | |||||
} | |||||
/* first, become a JACK client */ | |||||
if (argc > 2) { | |||||
client = jack_client_open (my_name, | |||||
(JackServerName|JackNoStartServer), | |||||
&status, argv[2]); | |||||
} else { | |||||
client = jack_client_open (my_name, JackNoStartServer, &status); | |||||
} | |||||
if (client == NULL) { | |||||
if (status & JackServerFailed) { | |||||
fprintf (stderr, "JACK server not running.\n"); | |||||
} else { | |||||
fprintf (stderr, "JACK open failed, " | |||||
"status = 0x%2.0x\n", status); | |||||
} | |||||
exit (1); | |||||
} | |||||
/* then, get the internal client handle */ | |||||
client_name = argv[1]; | |||||
intclient = jack_internal_client_handle (client, client_name, &status); | |||||
if (status & JackFailure) { | |||||
fprintf (stderr, "client %s not found.\n", client_name); | |||||
exit (2); | |||||
} | |||||
/* now, unload the internal client */ | |||||
status = jack_internal_client_unload (client, intclient); | |||||
if (status & JackFailure) { | |||||
if (status & JackNoSuchClient) { | |||||
fprintf (stderr, "client %s is gone.\n", | |||||
client_name); | |||||
} else { | |||||
fprintf (stderr, "could not unload %s, " | |||||
"returns 0x%2.0x\n", client_name, status); | |||||
} | |||||
exit (3); | |||||
} else { | |||||
fprintf (stdout, "%s unloaded.\n", client_name); | |||||
} | |||||
return 0; | |||||
} | |||||
@@ -1,120 +0,0 @@ | |||||
#include <stdio.h> | |||||
#include <stdlib.h> | |||||
#include <unistd.h> | |||||
#include <string.h> | |||||
#include <getopt.h> | |||||
#include <signal.h> | |||||
#include <time.h> | |||||
#include <config.h> | |||||
#include <jack/jack.h> | |||||
char * my_name; | |||||
jack_client_t *client; | |||||
unsigned int wait_timeout = 1000; | |||||
void | |||||
show_version (void) | |||||
{ | |||||
fprintf (stderr, "%s: JACK Audio Connection Kit version " VERSION "\n", | |||||
my_name); | |||||
} | |||||
void | |||||
show_usage (void) | |||||
{ | |||||
show_version (); | |||||
fprintf (stderr, "\nUsage: %s [options]\n", my_name); | |||||
fprintf (stderr, "this is a test client, which just sleeps in its process_cb to simulate cpu load\n"); | |||||
fprintf (stderr, "options:\n"); | |||||
fprintf (stderr, " -t, --timeout Wait timeout in seconds\n"); | |||||
fprintf (stderr, " -h, --help Display this help message\n"); | |||||
fprintf (stderr, " --version Output version information and exit\n\n"); | |||||
fprintf (stderr, "For more information see http://jackaudio.org/\n"); | |||||
} | |||||
void jack_shutdown(void *arg) | |||||
{ | |||||
fprintf(stderr, "JACK shut down, exiting ...\n"); | |||||
exit(1); | |||||
} | |||||
void signal_handler(int sig) | |||||
{ | |||||
jack_client_close(client); | |||||
fprintf(stderr, "signal received, exiting ...\n"); | |||||
exit(0); | |||||
} | |||||
int | |||||
process_cb (jack_nframes_t nframes, void *arg) | |||||
{ | |||||
jack_time_t now = jack_get_time(); | |||||
jack_time_t wait = now + wait_timeout; | |||||
while (jack_get_time() < wait) ; | |||||
return 0; | |||||
} | |||||
int | |||||
main (int argc, char *argv[]) | |||||
{ | |||||
int c; | |||||
int option_index; | |||||
struct option long_options[] = { | |||||
{ "timeout", 1, 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, "t:hv", long_options, &option_index)) >= 0) { | |||||
switch (c) { | |||||
case 't': | |||||
wait_timeout = atoi(optarg); | |||||
break; | |||||
case 'h': | |||||
show_usage (); | |||||
return 1; | |||||
break; | |||||
case 'v': | |||||
show_version (); | |||||
return 1; | |||||
break; | |||||
default: | |||||
show_usage (); | |||||
return 1; | |||||
break; | |||||
} | |||||
} | |||||
/* try to open server in a loop. breaking under certein conditions */ | |||||
client = jack_client_open( "load_test", JackNullOption, NULL ); | |||||
signal(SIGQUIT, signal_handler); | |||||
signal(SIGTERM, signal_handler); | |||||
signal(SIGHUP, signal_handler); | |||||
signal(SIGINT, signal_handler); | |||||
jack_on_shutdown(client, jack_shutdown, 0); | |||||
jack_set_process_callback( client, process_cb, NULL ); | |||||
jack_activate (client); | |||||
sleep( -1 ); | |||||
exit (0); | |||||
} |
@@ -1,229 +0,0 @@ | |||||
#include <stdio.h> | |||||
#include <stdlib.h> | |||||
#include <unistd.h> | |||||
#include <string.h> | |||||
#include <getopt.h> | |||||
#include <config.h> | |||||
#include <jack/jack.h> | |||||
char * my_name; | |||||
void | |||||
show_version (void) | |||||
{ | |||||
fprintf (stderr, "%s: JACK Audio Connection Kit version " VERSION "\n", | |||||
my_name); | |||||
} | |||||
void | |||||
show_usage (void) | |||||
{ | |||||
show_version (); | |||||
fprintf (stderr, "\nUsage: %s [options] [filter string]\n", my_name); | |||||
fprintf (stderr, "List active Jack ports, and optionally display extra information.\n"); | |||||
fprintf (stderr, "Optionally filter ports which match ALL strings provided after any options.\n\n"); | |||||
fprintf (stderr, "Display options:\n"); | |||||
fprintf (stderr, " -s, --server <name> Connect to the jack server named <name>\n"); | |||||
fprintf (stderr, " -A, --aliases List aliases for each port\n"); | |||||
fprintf (stderr, " -c, --connections List connections to/from each port\n"); | |||||
fprintf (stderr, " -l, --latency Display per-port latency in frames at each port\n"); | |||||
fprintf (stderr, " -L, --latency Display total latency in frames at each port\n"); | |||||
fprintf (stderr, " -p, --properties Display port properties. Output may include:\n" | |||||
" input|output, can-monitor, physical, terminal\n\n"); | |||||
fprintf (stderr, " -t, --type Display port type\n"); | |||||
fprintf (stderr, " -h, --help Display this help message\n"); | |||||
fprintf (stderr, " --version Output version information and exit\n\n"); | |||||
fprintf (stderr, "For more information see http://jackaudio.org/\n"); | |||||
} | |||||
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; | |||||
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. */ | |||||
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); | |||||
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]); | |||||
jack_port_t *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 = %" PRIu32 " 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); | |||||
} | |||||
} | |||||
} | |||||
if (ports) | |||||
jack_free (ports); | |||||
jack_client_close (client); | |||||
exit (0); | |||||
} |
@@ -1,114 +0,0 @@ | |||||
#include <stdio.h> | |||||
#include <unistd.h> | |||||
#include <assert.h> | |||||
#include <jack/jack.h> | |||||
#include <jack/midiport.h> | |||||
static jack_port_t* port; | |||||
static void | |||||
describe (jack_midi_event_t* event, char* buffer, size_t buflen) | |||||
{ | |||||
assert (buflen > 0); | |||||
buffer[0] = '\0'; | |||||
if (event->size == 0) { | |||||
return; | |||||
} | |||||
int type = event->buffer[0] & 0xf0; | |||||
int channel = event->buffer[0] & 0xf; | |||||
switch (type) { | |||||
case 0x90: | |||||
assert (event->size == 3); | |||||
snprintf (buffer, buflen, "note on (channel %d): pitch %d, velocity %d", channel, event->buffer[1], event->buffer[2]); | |||||
break; | |||||
case 0x80: | |||||
assert (event->size == 3); | |||||
snprintf (buffer, buflen, "note off (channel %d): pitch %d, velocity %d", channel, event->buffer[1], event->buffer[2]); | |||||
break; | |||||
case 0xb0: | |||||
assert (event->size == 3); | |||||
snprintf (buffer, buflen, "control change (channel %d): controller %d, value %d", channel, event->buffer[1], event->buffer[2]); | |||||
break; | |||||
default: | |||||
break; | |||||
} | |||||
} | |||||
int | |||||
process (jack_nframes_t frames, void* arg) | |||||
{ | |||||
void* buffer; | |||||
jack_nframes_t N; | |||||
jack_nframes_t i; | |||||
char description[256]; | |||||
buffer = jack_port_get_buffer (port, frames); | |||||
assert (buffer); | |||||
N = jack_midi_get_event_count (buffer); | |||||
for (i = 0; i < N; ++i) { | |||||
jack_midi_event_t event; | |||||
int r; | |||||
r = jack_midi_event_get (&event, buffer, i); | |||||
if (r == 0) { | |||||
size_t j; | |||||
printf ("%d:", event.time); | |||||
for (j = 0; j < event.size; ++j) { | |||||
printf (" %x", event.buffer[j]); | |||||
} | |||||
describe (&event, description, sizeof (description)); | |||||
printf (" %s", description); | |||||
printf ("\n"); | |||||
} | |||||
} | |||||
return 0; | |||||
} | |||||
int | |||||
main (int argc, char* argv[]) | |||||
{ | |||||
jack_client_t* client; | |||||
char const default_name[] = "midi-monitor"; | |||||
char const * client_name; | |||||
int r; | |||||
if (argc == 2) { | |||||
client_name = argv[1]; | |||||
} else { | |||||
client_name = default_name; | |||||
} | |||||
client = jack_client_open (client_name, JackNullOption, NULL); | |||||
if (client == NULL) { | |||||
fprintf (stderr, "Could not create JACK client.\n"); | |||||
exit (EXIT_FAILURE); | |||||
} | |||||
jack_set_process_callback (client, process, 0); | |||||
port = jack_port_register (client, "input", JACK_DEFAULT_MIDI_TYPE, JackPortIsInput, 0); | |||||
if (port == NULL) { | |||||
fprintf (stderr, "Could not register port.\n"); | |||||
exit (EXIT_FAILURE); | |||||
} | |||||
r = jack_activate (client); | |||||
if (r != 0) { | |||||
fprintf (stderr, "Could not activate client.\n"); | |||||
exit (EXIT_FAILURE); | |||||
} | |||||
sleep (-1); | |||||
return 0; | |||||
} |
@@ -1,46 +0,0 @@ | |||||
#include <stdio.h> | |||||
#include <unistd.h> | |||||
#include <stdlib.h> | |||||
#include <string.h> | |||||
#include <jack/jack.h> | |||||
#define TRUE 1 | |||||
#define FALSE 0 | |||||
int | |||||
main (int argc, char *argv[]) | |||||
{ | |||||
jack_client_t *client; | |||||
char *my_name = strrchr(argv[0], '/'); | |||||
if (my_name == 0) { | |||||
my_name = argv[0]; | |||||
} else { | |||||
my_name ++; | |||||
} | |||||
if (argc != 2) { | |||||
fprintf (stderr, "Usage: %s client\n", my_name); | |||||
return 1; | |||||
} | |||||
if ((client = jack_client_open ("input monitoring", JackNullOption, NULL)) == 0) { | |||||
fprintf (stderr, "jack server not running?\n"); | |||||
return 1; | |||||
} | |||||
if (jack_port_request_monitor_by_name (client, argv[1], TRUE)) { | |||||
fprintf (stderr, "could not enable monitoring for %s\n", argv[1]); | |||||
jack_client_close (client); | |||||
return 1; | |||||
} | |||||
sleep (30); | |||||
if (jack_port_request_monitor_by_name (client, argv[1], FALSE)) { | |||||
fprintf (stderr, "could not disable monitoring for %s\n", argv[1]); | |||||
} | |||||
jack_client_close (client); | |||||
exit (0); | |||||
} | |||||
@@ -1,783 +0,0 @@ | |||||
/* | |||||
NetJack Client | |||||
Copyright (C) 2008 Marc-Olivier Barre <marco@marcochapeau.org> | |||||
Copyright (C) 2008 Pieter Palmers <pieterpalmers@users.sourceforge.net> | |||||
Copyright (C) 2006 Torben Hohn <torbenh@gmx.de> | |||||
This program 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. | |||||
This program 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 this program; if not, write to the Free Software | |||||
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. | |||||
*/ | |||||
/** @file netsource.c | |||||
* | |||||
* @brief This client connects a remote slave JACK to a local JACK server assumed to be the master | |||||
*/ | |||||
#include "config.h" | |||||
#include <stdio.h> | |||||
#include <errno.h> | |||||
#include <unistd.h> | |||||
#include <stdlib.h> | |||||
#include <string.h> | |||||
#include <signal.h> | |||||
#ifdef WIN32 | |||||
#include <winsock2.h> | |||||
#include <malloc.h> | |||||
#else | |||||
#include <netinet/in.h> | |||||
#include <netdb.h> | |||||
#include <sys/socket.h> | |||||
#endif | |||||
/* These two required by FreeBSD. */ | |||||
#include <sys/types.h> | |||||
#include <jack/jack.h> | |||||
//#include <net_driver.h> | |||||
#include <netjack_packet.h> | |||||
#if HAVE_SAMPLERATE | |||||
#include <samplerate.h> | |||||
#endif | |||||
#if HAVE_CELT | |||||
#include <celt/celt.h> | |||||
#endif | |||||
#include <math.h> | |||||
JSList *capture_ports = NULL; | |||||
JSList *capture_srcs = NULL; | |||||
int capture_channels = 0; | |||||
int capture_channels_audio = 2; | |||||
int capture_channels_midi = 1; | |||||
JSList *playback_ports = NULL; | |||||
JSList *playback_srcs = NULL; | |||||
int playback_channels = 0; | |||||
int playback_channels_audio = 2; | |||||
int playback_channels_midi = 1; | |||||
int dont_htonl_floats = 0; | |||||
int latency = 5; | |||||
jack_nframes_t factor = 1; | |||||
int bitdepth = 0; | |||||
int mtu = 1400; | |||||
int reply_port = 0; | |||||
int bind_port = 0; | |||||
int redundancy = 1; | |||||
jack_client_t *client; | |||||
packet_cache * packcache = 0; | |||||
int state_connected = 0; | |||||
int state_latency = 0; | |||||
int state_netxruns = 0; | |||||
int state_currentframe = 0; | |||||
int state_recv_packet_queue_time = 0; | |||||
int quit=0; | |||||
int outsockfd; | |||||
int insockfd; | |||||
#ifdef WIN32 | |||||
struct sockaddr_in destaddr; | |||||
struct sockaddr_in bindaddr; | |||||
#else | |||||
struct sockaddr destaddr; | |||||
struct sockaddr bindaddr; | |||||
#endif | |||||
int sync_state; | |||||
jack_transport_state_t last_transport_state; | |||||
int framecnt = 0; | |||||
int cont_miss = 0; | |||||
int freewheeling = 0; | |||||
/** | |||||
* This Function allocates all the I/O Ports which are added the lists. | |||||
*/ | |||||
void | |||||
alloc_ports (int n_capture_audio, int n_playback_audio, int n_capture_midi, int n_playback_midi) | |||||
{ | |||||
int port_flags = JackPortIsOutput; | |||||
int chn; | |||||
jack_port_t *port; | |||||
char buf[32]; | |||||
capture_ports = NULL; | |||||
/* Allocate audio capture channels */ | |||||
for (chn = 0; chn < n_capture_audio; chn++) | |||||
{ | |||||
snprintf (buf, sizeof (buf) - 1, "capture_%u", chn + 1); | |||||
port = jack_port_register (client, buf, JACK_DEFAULT_AUDIO_TYPE, port_flags, 0); | |||||
if (!port) | |||||
{ | |||||
printf( "jack_netsource: cannot register %s port\n", buf); | |||||
break; | |||||
} | |||||
if( bitdepth == 1000 ) { | |||||
#if HAVE_CELT | |||||
#if HAVE_CELT_API_0_7 || HAVE_CELT_API_0_8 | |||||
CELTMode *celt_mode = celt_mode_create( jack_get_sample_rate( client ), jack_get_buffer_size(client), NULL ); | |||||
capture_srcs = jack_slist_append(capture_srcs, celt_decoder_create( celt_mode, 1, NULL ) ); | |||||
#else | |||||
CELTMode *celt_mode = celt_mode_create( jack_get_sample_rate( client ), 1, jack_get_buffer_size(client), NULL ); | |||||
capture_srcs = jack_slist_append(capture_srcs, celt_decoder_create( celt_mode ) ); | |||||
#endif | |||||
#endif | |||||
} else { | |||||
#if HAVE_SAMPLERATE | |||||
capture_srcs = jack_slist_append (capture_srcs, src_new (SRC_LINEAR, 1, NULL)); | |||||
#endif | |||||
} | |||||
capture_ports = jack_slist_append (capture_ports, port); | |||||
} | |||||
/* Allocate midi capture channels */ | |||||
for (chn = n_capture_audio; chn < n_capture_midi + n_capture_audio; chn++) | |||||
{ | |||||
snprintf (buf, sizeof (buf) - 1, "capture_%u", chn + 1); | |||||
port = jack_port_register (client, buf, JACK_DEFAULT_MIDI_TYPE, port_flags, 0); | |||||
if (!port) | |||||
{ | |||||
printf ("jack_netsource: cannot register %s port\n", buf); | |||||
break; | |||||
} | |||||
capture_ports = jack_slist_append(capture_ports, port); | |||||
} | |||||
/* Allocate audio playback channels */ | |||||
port_flags = JackPortIsInput; | |||||
playback_ports = NULL; | |||||
for (chn = 0; chn < n_playback_audio; chn++) | |||||
{ | |||||
snprintf (buf, sizeof (buf) - 1, "playback_%u", chn + 1); | |||||
port = jack_port_register (client, buf, JACK_DEFAULT_AUDIO_TYPE, port_flags, 0); | |||||
if (!port) | |||||
{ | |||||
printf ("jack_netsource: cannot register %s port\n", buf); | |||||
break; | |||||
} | |||||
if( bitdepth == 1000 ) { | |||||
#if HAVE_CELT | |||||
#if HAVE_CELT_API_0_7 || HAVE_CELT_API_0_8 | |||||
CELTMode *celt_mode = celt_mode_create( jack_get_sample_rate (client), jack_get_buffer_size(client), NULL ); | |||||
playback_srcs = jack_slist_append(playback_srcs, celt_encoder_create( celt_mode, 1, NULL ) ); | |||||
#else | |||||
CELTMode *celt_mode = celt_mode_create( jack_get_sample_rate (client), 1, jack_get_buffer_size(client), NULL ); | |||||
playback_srcs = jack_slist_append(playback_srcs, celt_encoder_create( celt_mode ) ); | |||||
#endif | |||||
#endif | |||||
} else { | |||||
#if HAVE_SAMPLERATE | |||||
playback_srcs = jack_slist_append (playback_srcs, src_new (SRC_LINEAR, 1, NULL)); | |||||
#endif | |||||
} | |||||
playback_ports = jack_slist_append (playback_ports, port); | |||||
} | |||||
/* Allocate midi playback channels */ | |||||
for (chn = n_playback_audio; chn < n_playback_midi + n_playback_audio; chn++) | |||||
{ | |||||
snprintf (buf, sizeof (buf) - 1, "playback_%u", chn + 1); | |||||
port = jack_port_register (client, buf, JACK_DEFAULT_MIDI_TYPE, port_flags, 0); | |||||
if (!port) | |||||
{ | |||||
printf ("jack_netsource: cannot register %s port\n", buf); | |||||
break; | |||||
} | |||||
playback_ports = jack_slist_append (playback_ports, port); | |||||
} | |||||
} | |||||
/** | |||||
* The Sync callback... sync state is set elsewhere... | |||||
* we will see if this is working correctly. | |||||
* i dont really believe in it yet. | |||||
*/ | |||||
int | |||||
sync_cb (jack_transport_state_t state, jack_position_t *pos, void *arg) | |||||
{ | |||||
static int latency_count = 0; | |||||
int retval = sync_state; | |||||
if (! state_connected) { | |||||
return 1; | |||||
} | |||||
if (latency_count) { | |||||
latency_count--; | |||||
retval = 0; | |||||
} | |||||
else if (state == JackTransportStarting && last_transport_state != JackTransportStarting) | |||||
{ | |||||
retval = 0; | |||||
latency_count = latency - 1; | |||||
} | |||||
last_transport_state = state; | |||||
return retval; | |||||
} | |||||
void | |||||
freewheel_cb (int starting, void *arg) | |||||
{ | |||||
freewheeling = starting; | |||||
} | |||||
int deadline_goodness=0; | |||||
/** | |||||
* The process callback for this JACK application. | |||||
* It is called by JACK at the appropriate times. | |||||
*/ | |||||
int | |||||
process (jack_nframes_t nframes, void *arg) | |||||
{ | |||||
jack_nframes_t net_period; | |||||
int rx_bufsize, tx_bufsize; | |||||
jack_default_audio_sample_t *buf; | |||||
jack_port_t *port; | |||||
JSList *node; | |||||
int chn; | |||||
int size, i; | |||||
const char *porttype; | |||||
int input_fd; | |||||
jack_position_t local_trans_pos; | |||||
uint32_t *packet_buf_tx, *packet_bufX; | |||||
uint32_t *rx_packet_ptr; | |||||
jack_time_t packet_recv_timestamp; | |||||
if( bitdepth == 1000 ) | |||||
net_period = (factor * jack_get_buffer_size(client) * 1024 / jack_get_sample_rate(client) / 8)&(~1) ; | |||||
else | |||||
net_period = (float) nframes / (float) factor; | |||||
rx_bufsize = get_sample_size (bitdepth) * capture_channels * net_period + sizeof (jacknet_packet_header); | |||||
tx_bufsize = get_sample_size (bitdepth) * playback_channels * net_period + sizeof (jacknet_packet_header); | |||||
/* Allocate a buffer where both In and Out Buffer will fit */ | |||||
packet_buf_tx = alloca (tx_bufsize); | |||||
jacknet_packet_header *pkthdr_tx = (jacknet_packet_header *) packet_buf_tx; | |||||
/* | |||||
* for latency==0 we need to send out the packet before we wait on the reply. | |||||
* but this introduces a cycle of latency, when netsource is connected to itself. | |||||
* so we send out before read only in zero latency mode. | |||||
* | |||||
*/ | |||||
if( latency == 0 ) { | |||||
/* reset packet_bufX... */ | |||||
packet_bufX = packet_buf_tx + sizeof (jacknet_packet_header) / sizeof (jack_default_audio_sample_t); | |||||
/* ---------- Send ---------- */ | |||||
render_jack_ports_to_payload (bitdepth, playback_ports, playback_srcs, nframes, | |||||
packet_bufX, net_period, dont_htonl_floats); | |||||
/* fill in packet hdr */ | |||||
pkthdr_tx->transport_state = jack_transport_query (client, &local_trans_pos); | |||||
pkthdr_tx->transport_frame = local_trans_pos.frame; | |||||
pkthdr_tx->framecnt = framecnt; | |||||
pkthdr_tx->latency = latency; | |||||
pkthdr_tx->reply_port = reply_port; | |||||
pkthdr_tx->sample_rate = jack_get_sample_rate (client); | |||||
pkthdr_tx->period_size = nframes; | |||||
/* playback for us is capture on the other side */ | |||||
pkthdr_tx->capture_channels_audio = playback_channels_audio; | |||||
pkthdr_tx->playback_channels_audio = capture_channels_audio; | |||||
pkthdr_tx->capture_channels_midi = playback_channels_midi; | |||||
pkthdr_tx->playback_channels_midi = capture_channels_midi; | |||||
pkthdr_tx->mtu = mtu; | |||||
if( freewheeling!= 0 ) | |||||
pkthdr_tx->sync_state = (jack_nframes_t)MASTER_FREEWHEELS; | |||||
else | |||||
pkthdr_tx->sync_state = (jack_nframes_t)deadline_goodness; | |||||
//printf("goodness=%d\n", deadline_goodness ); | |||||
packet_header_hton (pkthdr_tx); | |||||
if (cont_miss < 3*latency+5) { | |||||
int r; | |||||
for( r=0; r<redundancy; r++ ) | |||||
netjack_sendto (outsockfd, (char *) packet_buf_tx, tx_bufsize, 0, &destaddr, sizeof (destaddr), mtu); | |||||
} | |||||
else if (cont_miss > 50+5*latency) | |||||
{ | |||||
state_connected = 0; | |||||
packet_cache_reset_master_address( packcache ); | |||||
//printf ("Frame %d \tRealy too many packets missed (%d). Let's reset the counter\n", framecnt, cont_miss); | |||||
cont_miss = 0; | |||||
} | |||||
} | |||||
/* | |||||
* ok... now the RECEIVE code. | |||||
* | |||||
*/ | |||||
if( reply_port ) | |||||
input_fd = insockfd; | |||||
else | |||||
input_fd = outsockfd; | |||||
// for latency == 0 we can poll. | |||||
if( (latency == 0) || (freewheeling!=0) ) { | |||||
jack_time_t deadline = jack_get_time() + 1000000 * jack_get_buffer_size(client)/jack_get_sample_rate(client); | |||||
// Now loop until we get the right packet. | |||||
while(1) { | |||||
jack_nframes_t got_frame; | |||||
if ( ! netjack_poll_deadline( input_fd, deadline, jack_get_time ) ) | |||||
break; | |||||
packet_cache_drain_socket(packcache, input_fd, jack_get_time); | |||||
if (packet_cache_get_next_available_framecnt( packcache, framecnt - latency, &got_frame )) | |||||
if( got_frame == (framecnt - latency) ) | |||||
break; | |||||
} | |||||
} else { | |||||
// normally: | |||||
// only drain socket. | |||||
packet_cache_drain_socket(packcache, input_fd, jack_get_time); | |||||
} | |||||
size = packet_cache_retreive_packet_pointer( packcache, framecnt - latency, (char**)&rx_packet_ptr, rx_bufsize, &packet_recv_timestamp ); | |||||
/* First alternative : we received what we expected. Render the data | |||||
* to the JACK ports so it can be played. */ | |||||
if (size == rx_bufsize) | |||||
{ | |||||
uint32_t *packet_buf_rx = rx_packet_ptr; | |||||
jacknet_packet_header *pkthdr_rx = (jacknet_packet_header *) packet_buf_rx; | |||||
packet_bufX = packet_buf_rx + sizeof (jacknet_packet_header) / sizeof (jack_default_audio_sample_t); | |||||
// calculate how much time there would have been, if this packet was sent at the deadline. | |||||
int recv_time_offset = (int) (jack_get_time() - packet_recv_timestamp); | |||||
packet_header_ntoh (pkthdr_rx); | |||||
deadline_goodness = recv_time_offset - (int)pkthdr_rx->latency; | |||||
//printf( "deadline goodness = %d ---> off: %d\n", deadline_goodness, recv_time_offset ); | |||||
if (cont_miss) | |||||
{ | |||||
//printf("Frame %d \tRecovered from dropouts\n", framecnt); | |||||
cont_miss = 0; | |||||
} | |||||
render_payload_to_jack_ports (bitdepth, packet_bufX, net_period, | |||||
capture_ports, capture_srcs, nframes, dont_htonl_floats); | |||||
state_currentframe = framecnt; | |||||
state_recv_packet_queue_time = recv_time_offset; | |||||
state_connected = 1; | |||||
sync_state = pkthdr_rx->sync_state; | |||||
packet_cache_release_packet( packcache, framecnt - latency ); | |||||
} | |||||
/* Second alternative : we've received something that's not | |||||
* as big as expected or we missed a packet. We render silence | |||||
* to the ouput ports */ | |||||
else | |||||
{ | |||||
jack_nframes_t latency_estimate; | |||||
if( packet_cache_find_latency( packcache, framecnt, &latency_estimate ) ) | |||||
//if( (state_latency == 0) || (latency_estimate < state_latency) ) | |||||
state_latency = latency_estimate; | |||||
// Set the counters up. | |||||
state_currentframe = framecnt; | |||||
//state_latency = framecnt - pkthdr->framecnt; | |||||
state_netxruns += 1; | |||||
//printf ("Frame %d \tPacket missed or incomplete (expected: %d bytes, got: %d bytes)\n", framecnt, rx_bufsize, size); | |||||
//printf ("Frame %d \tPacket missed or incomplete\n", framecnt); | |||||
cont_miss += 1; | |||||
chn = 0; | |||||
node = capture_ports; | |||||
while (node != NULL) | |||||
{ | |||||
port = (jack_port_t *) node->data; | |||||
buf = jack_port_get_buffer (port, nframes); | |||||
porttype = jack_port_type (port); | |||||
if (strncmp (porttype, JACK_DEFAULT_AUDIO_TYPE, jack_port_type_size ()) == 0) | |||||
for (i = 0; i < nframes; i++) | |||||
buf[i] = 0.0; | |||||
else if (strncmp (porttype, JACK_DEFAULT_MIDI_TYPE, jack_port_type_size ()) == 0) | |||||
jack_midi_clear_buffer (buf); | |||||
node = jack_slist_next (node); | |||||
chn++; | |||||
} | |||||
} | |||||
if( latency != 0 ) { | |||||
/* reset packet_bufX... */ | |||||
packet_bufX = packet_buf_tx + sizeof (jacknet_packet_header) / sizeof (jack_default_audio_sample_t); | |||||
/* ---------- Send ---------- */ | |||||
render_jack_ports_to_payload (bitdepth, playback_ports, playback_srcs, nframes, | |||||
packet_bufX, net_period, dont_htonl_floats); | |||||
/* fill in packet hdr */ | |||||
pkthdr_tx->transport_state = jack_transport_query (client, &local_trans_pos); | |||||
pkthdr_tx->transport_frame = local_trans_pos.frame; | |||||
pkthdr_tx->framecnt = framecnt; | |||||
pkthdr_tx->latency = latency; | |||||
pkthdr_tx->reply_port = reply_port; | |||||
pkthdr_tx->sample_rate = jack_get_sample_rate (client); | |||||
pkthdr_tx->period_size = nframes; | |||||
/* playback for us is capture on the other side */ | |||||
pkthdr_tx->capture_channels_audio = playback_channels_audio; | |||||
pkthdr_tx->playback_channels_audio = capture_channels_audio; | |||||
pkthdr_tx->capture_channels_midi = playback_channels_midi; | |||||
pkthdr_tx->playback_channels_midi = capture_channels_midi; | |||||
pkthdr_tx->mtu = mtu; | |||||
if( freewheeling!= 0 ) | |||||
pkthdr_tx->sync_state = (jack_nframes_t)MASTER_FREEWHEELS; | |||||
else | |||||
pkthdr_tx->sync_state = (jack_nframes_t)deadline_goodness; | |||||
//printf("goodness=%d\n", deadline_goodness ); | |||||
packet_header_hton (pkthdr_tx); | |||||
if (cont_miss < 3*latency+5) { | |||||
int r; | |||||
for( r=0; r<redundancy; r++ ) | |||||
netjack_sendto (outsockfd, (char *) packet_buf_tx, tx_bufsize, 0, &destaddr, sizeof (destaddr), mtu); | |||||
} | |||||
else if (cont_miss > 50+5*latency) | |||||
{ | |||||
state_connected = 0; | |||||
packet_cache_reset_master_address( packcache ); | |||||
//printf ("Frame %d \tRealy too many packets missed (%d). Let's reset the counter\n", framecnt, cont_miss); | |||||
cont_miss = 0; | |||||
} | |||||
} | |||||
framecnt++; | |||||
return 0; | |||||
} | |||||
/** | |||||
* This is the shutdown callback for this JACK application. | |||||
* It is called by JACK if the server ever shuts down or | |||||
* decides to disconnect the client. | |||||
*/ | |||||
void | |||||
jack_shutdown (void *arg) | |||||
{ | |||||
exit (1); | |||||
} | |||||
void | |||||
init_sockaddr_in (struct sockaddr_in *name , const char *hostname , uint16_t port) | |||||
{ | |||||
name->sin_family = AF_INET ; | |||||
name->sin_port = htons (port); | |||||
if (hostname) | |||||
{ | |||||
struct hostent *hostinfo = gethostbyname (hostname); | |||||
if (hostinfo == NULL) { | |||||
fprintf (stderr, "init_sockaddr_in: unknown host: %s.\n", hostname); | |||||
fflush( stderr ); | |||||
} | |||||
#ifdef WIN32 | |||||
name->sin_addr.s_addr = inet_addr( hostname ); | |||||
#else | |||||
name->sin_addr = *(struct in_addr *) hostinfo->h_addr ; | |||||
#endif | |||||
} | |||||
else | |||||
name->sin_addr.s_addr = htonl (INADDR_ANY) ; | |||||
} | |||||
void | |||||
printUsage () | |||||
{ | |||||
fprintf (stderr, "usage: jack_netsource [options]\n" | |||||
"\n" | |||||
" -h this help text\n" | |||||
" -H <slave host> - Host name of the slave JACK\n" | |||||
" -o <num channels> - Number of audio playback channels\n" | |||||
" -i <num channels> - Number of audio capture channels\n" | |||||
" -O <num channels> - Number of midi playback channels\n" | |||||
" -I <num channels> - Number of midi capture channels\n" | |||||
" -n <periods> - Network latency in JACK periods\n" | |||||
" -p <port> - UDP port that the slave is listening on\n" | |||||
" -r <reply port> - UDP port that we are listening on\n" | |||||
" -B <bind port> - reply port, for use in NAT environments\n" | |||||
" -b <bitdepth> - Set transport to use 16bit or 8bit\n" | |||||
" -c <kbits> - Use CELT encoding with <kbits> kbits per channel\n" | |||||
" -m <mtu> - Assume this mtu for the link\n" | |||||
" -R <N> - Redundancy: send out packets N times.\n" | |||||
" -e - skip host-to-network endianness conversion\n" | |||||
" -N <jack name> - Reports a different name to jack\n" | |||||
" -s <server name> - The name of the local jack server\n" | |||||
"\n"); | |||||
} | |||||
void | |||||
sigterm_handler( int signal ) | |||||
{ | |||||
quit = 1; | |||||
} | |||||
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:")) != -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 supprt\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 ) | |||||
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); | |||||
} |
@@ -1,85 +0,0 @@ | |||||
/* | |||||
* smaplerate.c -- get current samplerate | |||||
* | |||||
* Copyright (C) 2003 Jack O'Quin. | |||||
* | |||||
* This program 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. | |||||
* | |||||
* This program 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 this program; if not, write to the Free Software | |||||
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. | |||||
*/ | |||||
#include <stdio.h> | |||||
#include <errno.h> | |||||
#include <unistd.h> | |||||
#include <signal.h> | |||||
#include <stdlib.h> | |||||
#include <string.h> | |||||
#include <jack/jack.h> | |||||
#include <jack/transport.h> | |||||
char *package; /* program name */ | |||||
jack_client_t *client; | |||||
void jack_shutdown(void *arg) | |||||
{ | |||||
fprintf(stderr, "JACK shut down, exiting ...\n"); | |||||
exit(1); | |||||
} | |||||
void signal_handler(int sig) | |||||
{ | |||||
jack_client_close(client); | |||||
fprintf(stderr, "signal received, exiting ...\n"); | |||||
exit(0); | |||||
} | |||||
void parse_arguments(int argc, char *argv[]) | |||||
{ | |||||
/* basename $0 */ | |||||
package = strrchr(argv[0], '/'); | |||||
if (package == 0) | |||||
package = argv[0]; | |||||
else | |||||
package++; | |||||
if (argc==1) { | |||||
return; | |||||
} | |||||
fprintf(stderr, "usage: %s\n", package); | |||||
exit(9); | |||||
} | |||||
int main(int argc, char *argv[]) | |||||
{ | |||||
parse_arguments(argc, argv); | |||||
/* become a JACK client */ | |||||
if ((client = jack_client_open(package, JackNullOption, NULL)) == 0) { | |||||
fprintf(stderr, "JACK server not running?\n"); | |||||
exit(1); | |||||
} | |||||
signal(SIGQUIT, signal_handler); | |||||
signal(SIGTERM, signal_handler); | |||||
signal(SIGHUP, signal_handler); | |||||
signal(SIGINT, signal_handler); | |||||
jack_on_shutdown(client, jack_shutdown, 0); | |||||
fprintf(stdout, "%d\n", jack_get_sample_rate( client ) ); | |||||
jack_client_close(client); | |||||
return 0; | |||||
} |
@@ -1,181 +0,0 @@ | |||||
/* | |||||
* session_notify.c -- ultra minimal session manager | |||||
* | |||||
* Copyright (C) 2010 Torben Hohn. | |||||
* | |||||
* This program 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. | |||||
* | |||||
* This program 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 this program; if not, write to the Free Software | |||||
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. | |||||
*/ | |||||
#include <stdio.h> | |||||
#include <errno.h> | |||||
#include <unistd.h> | |||||
#include <signal.h> | |||||
#include <stdlib.h> | |||||
#include <string.h> | |||||
#include <jack/jack.h> | |||||
#include <jack/jslist.h> | |||||
#include <jack/transport.h> | |||||
#include <jack/session.h> | |||||
char *package; /* program name */ | |||||
jack_client_t *client; | |||||
jack_session_event_type_t notify_type; | |||||
char *save_path = NULL; | |||||
void jack_shutdown(void *arg) | |||||
{ | |||||
fprintf(stderr, "JACK shut down, exiting ...\n"); | |||||
exit(1); | |||||
} | |||||
void signal_handler(int sig) | |||||
{ | |||||
jack_client_close(client); | |||||
fprintf(stderr, "signal received, exiting ...\n"); | |||||
exit(0); | |||||
} | |||||
void parse_arguments(int argc, char *argv[]) | |||||
{ | |||||
/* basename $0 */ | |||||
package = strrchr(argv[0], '/'); | |||||
if (package == 0) | |||||
package = argv[0]; | |||||
else | |||||
package++; | |||||
if (argc==2) { | |||||
if( !strcmp( argv[1], "quit" ) ) { | |||||
notify_type = JackSessionSaveAndQuit; | |||||
return; | |||||
} | |||||
} | |||||
if (argc==3) { | |||||
if( !strcmp( argv[1], "save" ) ) { | |||||
notify_type = JackSessionSave; | |||||
save_path = argv[2]; | |||||
return; | |||||
} | |||||
} | |||||
fprintf(stderr, "usage: %s quit|save [path]\n", package); | |||||
exit(9); | |||||
} | |||||
typedef struct { | |||||
char name[32]; | |||||
char uuid[16]; | |||||
} uuid_map_t; | |||||
JSList *uuid_map = NULL; | |||||
void add_uuid_mapping( const char *uuid ) { | |||||
char *clientname = jack_get_client_name_by_uuid( client, uuid ); | |||||
if( !clientname ) { | |||||
printf( "error... cant find client for uuid" ); | |||||
return; | |||||
} | |||||
uuid_map_t *mapping = malloc( sizeof(uuid_map_t) ); | |||||
snprintf( mapping->uuid, sizeof(mapping->uuid), "%s", uuid ); | |||||
snprintf( mapping->name, sizeof(mapping->name), "%s", clientname ); | |||||
uuid_map = jack_slist_append( uuid_map, mapping ); | |||||
} | |||||
char *map_port_name_to_uuid_port( const char *port_name ) | |||||
{ | |||||
JSList *node; | |||||
char retval[300]; | |||||
char *port_component = strchr( port_name,':' ); | |||||
char *client_component = strdup( port_name ); | |||||
strchr( client_component, ':' )[0] = '\0'; | |||||
sprintf( retval, "%s", port_name ); | |||||
for( node=uuid_map; node; node=jack_slist_next(node) ) { | |||||
uuid_map_t *mapping = node->data; | |||||
if( !strcmp( mapping->name, client_component ) ) { | |||||
sprintf( retval, "%s%s", mapping->uuid, port_component ); | |||||
break; | |||||
} | |||||
} | |||||
return strdup(retval); | |||||
} | |||||
int main(int argc, char *argv[]) | |||||
{ | |||||
parse_arguments(argc, argv); | |||||
jack_session_command_t *retval; | |||||
int k,i,j; | |||||
/* become a JACK client */ | |||||
if ((client = jack_client_open(package, JackNullOption, NULL)) == 0) { | |||||
fprintf(stderr, "JACK server not running?\n"); | |||||
exit(1); | |||||
} | |||||
signal(SIGQUIT, signal_handler); | |||||
signal(SIGTERM, signal_handler); | |||||
signal(SIGHUP, signal_handler); | |||||
signal(SIGINT, signal_handler); | |||||
jack_on_shutdown(client, jack_shutdown, 0); | |||||
jack_activate(client); | |||||
retval = jack_session_notify( client, NULL, notify_type, save_path ); | |||||
for(i=0; retval[i].uuid; i++ ) { | |||||
printf( "export SESSION_DIR=\"%s%s/\"\n", save_path, retval[i].client_name ); | |||||
printf( "%s &\n", retval[i].command ); | |||||
add_uuid_mapping(retval[i].uuid); | |||||
} | |||||
printf( "sleep 10\n" ); | |||||
for(k=0; retval[k].uuid; k++ ) { | |||||
char* port_regexp = alloca( jack_client_name_size()+3 ); | |||||
char* client_name = jack_get_client_name_by_uuid( client, retval[k].uuid ); | |||||
snprintf( port_regexp, jack_client_name_size()+3, "%s:.*", client_name ); | |||||
jack_free(client_name); | |||||
const char **ports = jack_get_ports( client, port_regexp, NULL, 0 ); | |||||
if( !ports ) { | |||||
continue; | |||||
} | |||||
for (i = 0; ports[i]; ++i) { | |||||
const char **connections; | |||||
if ((connections = jack_port_get_all_connections (client, jack_port_by_name(client, ports[i]))) != 0) { | |||||
for (j = 0; connections[j]; j++) { | |||||
char *src = map_port_name_to_uuid_port( ports[i] ); | |||||
char *dst = map_port_name_to_uuid_port( connections[j] ); | |||||
printf( "jack_connect -u \"%s\" \"%s\"\n", src, dst ); | |||||
} | |||||
jack_free (connections); | |||||
} | |||||
} | |||||
jack_free(ports); | |||||
} | |||||
jack_session_commands_free(retval); | |||||
jack_client_close(client); | |||||
return 0; | |||||
} |
@@ -1,481 +0,0 @@ | |||||
/* | |||||
* transport.c -- JACK transport master example client. | |||||
* | |||||
* Copyright (C) 2003 Jack O'Quin. | |||||
* | |||||
* This program 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. | |||||
* | |||||
* This program 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 this program; if not, write to the Free Software | |||||
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. | |||||
*/ | |||||
#include <stdio.h> | |||||
#include <errno.h> | |||||
#include <unistd.h> | |||||
#include <signal.h> | |||||
#include <stdlib.h> | |||||
#include <string.h> | |||||
#include <readline/readline.h> | |||||
#include <readline/history.h> | |||||
#include <jack/jack.h> | |||||
#include <jack/transport.h> | |||||
char *package; /* program name */ | |||||
int done = 0; | |||||
jack_client_t *client; | |||||
/* Time and tempo variables. These are global to the entire, | |||||
* transport timeline. There is no attempt to keep a true tempo map. | |||||
* The default time signature is: "march time", 4/4, 120bpm | |||||
*/ | |||||
float time_beats_per_bar = 4.0; | |||||
float time_beat_type = 4.0; | |||||
double time_ticks_per_beat = 1920.0; | |||||
double time_beats_per_minute = 120.0; | |||||
volatile int time_reset = 1; /* true when time values change */ | |||||
volatile int avr_set = 0; | |||||
float audio_frames_per_video_frame; | |||||
/* JACK timebase callback. | |||||
* | |||||
* Runs in the process thread. Realtime, must not wait. | |||||
*/ | |||||
void timebase(jack_transport_state_t state, jack_nframes_t nframes, | |||||
jack_position_t *pos, int new_pos, void *arg) | |||||
{ | |||||
double min; /* minutes since frame 0 */ | |||||
long abs_tick; /* ticks since frame 0 */ | |||||
long abs_beat; /* beats since frame 0 */ | |||||
if (new_pos || time_reset) { | |||||
pos->valid = JackPositionBBT; | |||||
pos->beats_per_bar = time_beats_per_bar; | |||||
pos->beat_type = time_beat_type; | |||||
pos->ticks_per_beat = time_ticks_per_beat; | |||||
pos->beats_per_minute = time_beats_per_minute; | |||||
time_reset = 0; /* time change complete */ | |||||
/* Compute BBT info from frame number. This is relatively | |||||
* simple here, but would become complex if we supported tempo | |||||
* or time signature changes at specific locations in the | |||||
* transport timeline. | |||||
*/ | |||||
min = pos->frame / ((double) pos->frame_rate * 60.0); | |||||
abs_tick = min * pos->beats_per_minute * pos->ticks_per_beat; | |||||
abs_beat = abs_tick / pos->ticks_per_beat; | |||||
pos->bar = abs_beat / pos->beats_per_bar; | |||||
pos->beat = abs_beat - (pos->bar * pos->beats_per_bar) + 1; | |||||
pos->tick = abs_tick - (abs_beat * pos->ticks_per_beat); | |||||
pos->bar_start_tick = pos->bar * pos->beats_per_bar * | |||||
pos->ticks_per_beat; | |||||
pos->bar++; /* adjust start to bar 1 */ | |||||
#if 0 | |||||
/* some debug code... */ | |||||
fprintf(stderr, "\nnew position: %" PRIu32 "\tBBT: %3" | |||||
PRIi32 "|%" PRIi32 "|%04" PRIi32 "\n", | |||||
pos->frame, pos->bar, pos->beat, pos->tick); | |||||
#endif | |||||
} else { | |||||
/* Compute BBT info based on previous period. */ | |||||
pos->tick += | |||||
nframes * pos->ticks_per_beat * pos->beats_per_minute | |||||
/ (pos->frame_rate * 60); | |||||
while (pos->tick >= pos->ticks_per_beat) { | |||||
pos->tick -= pos->ticks_per_beat; | |||||
if (++pos->beat > pos->beats_per_bar) { | |||||
pos->beat = 1; | |||||
++pos->bar; | |||||
pos->bar_start_tick += | |||||
pos->beats_per_bar | |||||
* pos->ticks_per_beat; | |||||
} | |||||
} | |||||
} | |||||
if (avr_set) { | |||||
pos->valid |= JackAudioVideoRatio; | |||||
pos->audio_frames_per_video_frame = audio_frames_per_video_frame; | |||||
} | |||||
} | |||||
void jack_shutdown(void *arg) | |||||
{ | |||||
#if defined(RL_READLINE_VERSION) && RL_READLINE_VERSION >= 0x0400 | |||||
rl_cleanup_after_signal(); | |||||
#endif | |||||
fprintf(stderr, "JACK shut down, exiting ...\n"); | |||||
exit(1); | |||||
} | |||||
void signal_handler(int sig) | |||||
{ | |||||
jack_client_close(client); | |||||
fprintf(stderr, "signal received, exiting ...\n"); | |||||
exit(0); | |||||
} | |||||
/* Command functions: see commands[] table following. */ | |||||
void com_activate(char *arg) | |||||
{ | |||||
if (jack_activate(client)) { | |||||
fprintf(stderr, "cannot activate client"); | |||||
} | |||||
} | |||||
void com_deactivate(char *arg) | |||||
{ | |||||
if (jack_deactivate(client)) { | |||||
fprintf(stderr, "cannot deactivate client"); | |||||
} | |||||
} | |||||
void com_exit(char *arg) | |||||
{ | |||||
done = 1; | |||||
} | |||||
void com_help(char *); /* forward declaration */ | |||||
void com_locate(char *arg) | |||||
{ | |||||
jack_nframes_t frame = 0; | |||||
if (*arg != '\0') | |||||
frame = atoi(arg); | |||||
jack_transport_locate(client, frame); | |||||
} | |||||
void com_master(char *arg) | |||||
{ | |||||
int cond = (*arg != '\0'); | |||||
if (jack_set_timebase_callback(client, cond, timebase, NULL) != 0) | |||||
fprintf(stderr, "Unable to take over timebase.\n"); | |||||
} | |||||
void com_play(char *arg) | |||||
{ | |||||
jack_transport_start(client); | |||||
} | |||||
void com_release(char *arg) | |||||
{ | |||||
jack_release_timebase(client); | |||||
} | |||||
void com_stop(char *arg) | |||||
{ | |||||
jack_transport_stop(client); | |||||
} | |||||
/* Change the tempo for the entire timeline, not just from the current | |||||
* location. */ | |||||
void com_tempo(char *arg) | |||||
{ | |||||
float tempo = 120.0; | |||||
if (*arg != '\0') | |||||
tempo = atof(arg); | |||||
time_beats_per_minute = tempo; | |||||
time_reset = 1; | |||||
} | |||||
/* Set sync timeout in seconds. */ | |||||
void com_timeout(char *arg) | |||||
{ | |||||
double timeout = 2.0; | |||||
if (*arg != '\0') | |||||
timeout = atof(arg); | |||||
jack_set_sync_timeout(client, (jack_time_t) (timeout*1000000)); | |||||
} | |||||
/* Change the tempo for the entire timeline, not just from the current | |||||
* location. */ | |||||
void com_av_ratio(char *arg) | |||||
{ | |||||
float avr = 0; | |||||
if (*arg != '\0') | |||||
avr = atof(arg); | |||||
audio_frames_per_video_frame = avr; | |||||
avr_set = 1; | |||||
} | |||||
/* Command parsing based on GNU readline info examples. */ | |||||
typedef void cmd_function_t(char *); /* command function type */ | |||||
/* Transport command table. */ | |||||
typedef struct { | |||||
char *name; /* user printable name */ | |||||
cmd_function_t *func; /* function to call */ | |||||
char *doc; /* documentation */ | |||||
} command_t; | |||||
/* command table must be in alphabetical order */ | |||||
command_t commands[] = { | |||||
{"activate", com_activate, "Call jack_activate()"}, | |||||
{"avr", com_av_ratio, "Set audio/video frame ratio <audio frames per video frame>"}, | |||||
{"exit", com_exit, "Exit transport program"}, | |||||
{"deactivate", com_deactivate, "Call jack_deactivate()"}, | |||||
{"help", com_help, "Display help text [<command>]"}, | |||||
{"locate", com_locate, "Locate to frame <position>"}, | |||||
{"master", com_master, "Become timebase master " | |||||
"[<conditionally>]"}, | |||||
{"play", com_play, "Start transport rolling"}, | |||||
{"quit", com_exit, "Synonym for `exit'"}, | |||||
{"release", com_release, "Release timebase"}, | |||||
{"stop", com_stop, "Stop transport"}, | |||||
{"tempo", com_tempo, "Set beat tempo <beats_per_min>"}, | |||||
{"timeout", com_timeout, "Set sync timeout in <seconds>"}, | |||||
{"?", com_help, "Synonym for `help'" }, | |||||
{(char *)NULL, (cmd_function_t *)NULL, (char *)NULL } | |||||
}; | |||||
command_t *find_command(char *name) | |||||
{ | |||||
register int i; | |||||
size_t namelen; | |||||
if ((name == NULL) || (*name == '\0')) | |||||
return ((command_t *)NULL); | |||||
namelen = strlen(name); | |||||
for (i = 0; commands[i].name; i++) | |||||
if (strncmp(name, commands[i].name, namelen) == 0) { | |||||
/* make sure the match is unique */ | |||||
if ((commands[i+1].name) && | |||||
(strncmp(name, commands[i+1].name, namelen) == 0)) | |||||
return ((command_t *)NULL); | |||||
else | |||||
return (&commands[i]); | |||||
} | |||||
return ((command_t *)NULL); | |||||
} | |||||
void com_help(char *arg) | |||||
{ | |||||
register int i; | |||||
command_t *cmd; | |||||
if (!*arg) { | |||||
/* print help for all commands */ | |||||
for (i = 0; commands[i].name; i++) { | |||||
printf("%s\t\t%s.\n", commands[i].name, | |||||
commands[i].doc); | |||||
} | |||||
} else if ((cmd = find_command(arg))) { | |||||
printf("%s\t\t%s.\n", cmd->name, cmd->doc); | |||||
} else { | |||||
int printed = 0; | |||||
printf("No `%s' command. Valid command names are:\n", arg); | |||||
for (i = 0; commands[i].name; i++) { | |||||
/* Print in six columns. */ | |||||
if (printed == 6) { | |||||
printed = 0; | |||||
printf ("\n"); | |||||
} | |||||
printf ("%s\t", commands[i].name); | |||||
printed++; | |||||
} | |||||
printf("\n\nTry `help [command]\' for more information.\n"); | |||||
} | |||||
} | |||||
void execute_command(char *line) | |||||
{ | |||||
register int i; | |||||
command_t *command; | |||||
char *word; | |||||
/* Isolate the command word. */ | |||||
i = 0; | |||||
while (line[i] && whitespace(line[i])) | |||||
i++; | |||||
word = line + i; | |||||
while (line[i] && !whitespace(line[i])) | |||||
i++; | |||||
if (line[i]) | |||||
line[i++] = '\0'; | |||||
command = find_command(word); | |||||
if (!command) { | |||||
fprintf(stderr, "%s: No such command. There is `help\'.\n", | |||||
word); | |||||
return; | |||||
} | |||||
/* Get argument to command, if any. */ | |||||
while (whitespace(line[i])) | |||||
i++; | |||||
word = line + i; | |||||
/* invoke the command function. */ | |||||
(*command->func)(word); | |||||
} | |||||
/* Strip whitespace from the start and end of string. */ | |||||
char *stripwhite(char *string) | |||||
{ | |||||
register char *s, *t; | |||||
s = string; | |||||
while (whitespace(*s)) | |||||
s++; | |||||
if (*s == '\0') | |||||
return s; | |||||
t = s + strlen (s) - 1; | |||||
while (t > s && whitespace(*t)) | |||||
t--; | |||||
*++t = '\0'; | |||||
return s; | |||||
} | |||||
char *dupstr(char *s) | |||||
{ | |||||
char *r = malloc(strlen(s) + 1); | |||||
strcpy(r, s); | |||||
return r; | |||||
} | |||||
/* Readline generator function for command completion. */ | |||||
char *command_generator (const char *text, int state) | |||||
{ | |||||
static int list_index, len; | |||||
char *name; | |||||
/* If this is a new word to complete, initialize now. This | |||||
includes saving the length of TEXT for efficiency, and | |||||
initializing the index variable to 0. */ | |||||
if (!state) { | |||||
list_index = 0; | |||||
len = strlen (text); | |||||
} | |||||
/* Return the next name which partially matches from the | |||||
command list. */ | |||||
while ((name = commands[list_index].name)) { | |||||
list_index++; | |||||
if (strncmp(name, text, len) == 0) | |||||
return dupstr(name); | |||||
} | |||||
return (char *) NULL; /* No names matched. */ | |||||
} | |||||
void command_loop() | |||||
{ | |||||
char *line, *cmd; | |||||
char prompt[32]; | |||||
snprintf(prompt, sizeof(prompt), "%s> ", package); | |||||
/* Allow conditional parsing of the ~/.inputrc file. */ | |||||
rl_readline_name = package; | |||||
/* Define a custom completion function. */ | |||||
rl_completion_entry_function = command_generator; | |||||
/* Read and execute commands until the user quits. */ | |||||
while (!done) { | |||||
line = readline(prompt); | |||||
if (line == NULL) { /* EOF? */ | |||||
printf("\n"); /* close out prompt */ | |||||
done = 1; | |||||
break; | |||||
} | |||||
/* Remove leading and trailing whitespace from the line. */ | |||||
cmd = stripwhite(line); | |||||
/* If anything left, add to history and execute it. */ | |||||
if (*cmd) | |||||
{ | |||||
add_history(cmd); | |||||
execute_command(cmd); | |||||
} | |||||
free(line); /* realine() called malloc() */ | |||||
} | |||||
} | |||||
int main(int argc, char *argv[]) | |||||
{ | |||||
jack_status_t status; | |||||
/* basename $0 */ | |||||
package = strrchr(argv[0], '/'); | |||||
if (package == 0) | |||||
package = argv[0]; | |||||
else | |||||
package++; | |||||
/* open a connection to the JACK server */ | |||||
client = jack_client_open (package, JackNullOption, &status); | |||||
if (client == NULL) { | |||||
fprintf (stderr, "jack_client_open() failed, " | |||||
"status = 0x%2.0x\n", status); | |||||
return 1; | |||||
} | |||||
signal(SIGQUIT, signal_handler); | |||||
signal(SIGTERM, signal_handler); | |||||
signal(SIGHUP, signal_handler); | |||||
signal(SIGINT, signal_handler); | |||||
jack_on_shutdown(client, jack_shutdown, 0); | |||||
if (jack_activate(client)) { | |||||
fprintf(stderr, "cannot activate client"); | |||||
return 1; | |||||
} | |||||
/* execute commands until done */ | |||||
command_loop(); | |||||
jack_client_close(client); | |||||
exit(0); | |||||
} |
@@ -1,204 +0,0 @@ | |||||
/** @file simple_client.c | |||||
* | |||||
* @brief This simple client demonstrates the basic features of JACK | |||||
* as they would be used by many applications. | |||||
*/ | |||||
#include <stdio.h> | |||||
#include <errno.h> | |||||
#include <unistd.h> | |||||
#include <stdlib.h> | |||||
#include <string.h> | |||||
#include <jack/jack.h> | |||||
jack_port_t *input_port; | |||||
jack_port_t *output_port; | |||||
jack_client_t *client; | |||||
/* a simple state machine for this client */ | |||||
volatile enum { | |||||
Init, | |||||
Run, | |||||
Exit | |||||
} client_state = Init; | |||||
/** | |||||
* The process callback for this JACK application is called in a | |||||
* special realtime thread once for each audio cycle. | |||||
* | |||||
* This client follows a simple rule: when the JACK transport is | |||||
* running, copy the input port to the output. When it stops, exit. | |||||
*/ | |||||
int | |||||
_process (jack_nframes_t nframes) | |||||
{ | |||||
jack_default_audio_sample_t *in, *out; | |||||
jack_transport_state_t ts = jack_transport_query(client, NULL); | |||||
if (ts == JackTransportRolling) { | |||||
if (client_state == Init) | |||||
client_state = Run; | |||||
in = jack_port_get_buffer (input_port, nframes); | |||||
out = jack_port_get_buffer (output_port, nframes); | |||||
memcpy (out, in, | |||||
sizeof (jack_default_audio_sample_t) * nframes); | |||||
} else if (ts == JackTransportStopped) { | |||||
if (client_state == Run) | |||||
client_state = Exit; | |||||
} | |||||
return 0; | |||||
} | |||||
int | |||||
process (jack_nframes_t nframes, void* arg) | |||||
{ | |||||
jack_client_t* client = (jack_client_t*) arg; | |||||
while ((nframes = jack_thread_wait (client, _process (nframes))) != 0); | |||||
return 0; | |||||
} | |||||
/** | |||||
* JACK calls this shutdown_callback if the server ever shuts down or | |||||
* decides to disconnect the client. | |||||
*/ | |||||
void | |||||
jack_shutdown (void *arg) | |||||
{ | |||||
exit (1); | |||||
} | |||||
int | |||||
main (int argc, char *argv[]) | |||||
{ | |||||
const char **ports; | |||||
const char *client_name; | |||||
const char *server_name = NULL; | |||||
jack_options_t options = JackNullOption; | |||||
jack_status_t status; | |||||
if (argc >= 2) { /* client name specified? */ | |||||
client_name = argv[1]; | |||||
if (argc >= 3) { /* server name specified? */ | |||||
server_name = argv[2]; | |||||
options |= JackServerName; | |||||
} | |||||
} else { /* use basename of argv[0] */ | |||||
client_name = strrchr(argv[0], '/'); | |||||
if (client_name == 0) { | |||||
client_name = argv[0]; | |||||
} else { | |||||
client_name++; | |||||
} | |||||
} | |||||
/* open a client connection to 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", status); | |||||
if (status & JackServerFailed) { | |||||
fprintf (stderr, "Unable to connect to JACK server\n"); | |||||
} | |||||
exit (1); | |||||
} | |||||
if (status & JackServerStarted) { | |||||
fprintf (stderr, "JACK server started\n"); | |||||
} | |||||
if (status & JackNameNotUnique) { | |||||
client_name = jack_get_client_name(client); | |||||
fprintf (stderr, "unique name `%s' assigned\n", client_name); | |||||
} | |||||
/* tell the JACK server to call `process()' whenever | |||||
there is work to be done. | |||||
*/ | |||||
jack_set_process_callback (client, process, client); | |||||
/* tell the JACK server to call `jack_shutdown()' if | |||||
it ever shuts down, either entirely, or if it | |||||
just decides to stop calling us. | |||||
*/ | |||||
jack_on_shutdown (client, jack_shutdown, 0); | |||||
/* display the current sample rate. | |||||
*/ | |||||
printf ("engine sample rate: %" PRIu32 "\n", | |||||
jack_get_sample_rate (client)); | |||||
/* create two ports */ | |||||
input_port = jack_port_register (client, "input", | |||||
JACK_DEFAULT_AUDIO_TYPE, | |||||
JackPortIsInput, 0); | |||||
output_port = jack_port_register (client, "output", | |||||
JACK_DEFAULT_AUDIO_TYPE, | |||||
JackPortIsOutput, 0); | |||||
if ((input_port == NULL) || (output_port == NULL)) { | |||||
fprintf(stderr, "no more JACK ports available\n"); | |||||
exit (1); | |||||
} | |||||
/* Tell the JACK server that we are ready to roll. Our | |||||
* process() callback will start running now. */ | |||||
if (jack_activate (client)) { | |||||
fprintf (stderr, "cannot activate client"); | |||||
exit (1); | |||||
} | |||||
/* Connect the ports. You can't do this before the client is | |||||
* activated, because we can't make connections to clients | |||||
* that aren't running. Note the confusing (but necessary) | |||||
* orientation of the driver backend ports: playback ports are | |||||
* "input" to the backend, and capture ports are "output" from | |||||
* it. | |||||
*/ | |||||
ports = jack_get_ports (client, NULL, NULL, | |||||
JackPortIsPhysical|JackPortIsOutput); | |||||
if (ports == NULL) { | |||||
fprintf(stderr, "no physical capture ports\n"); | |||||
exit (1); | |||||
} | |||||
if (jack_connect (client, ports[0], jack_port_name (input_port))) { | |||||
fprintf (stderr, "cannot connect input ports\n"); | |||||
} | |||||
free (ports); | |||||
ports = jack_get_ports (client, NULL, NULL, | |||||
JackPortIsPhysical|JackPortIsInput); | |||||
if (ports == NULL) { | |||||
fprintf(stderr, "no physical playback ports\n"); | |||||
exit (1); | |||||
} | |||||
if (jack_connect (client, jack_port_name (output_port), ports[0])) { | |||||
fprintf (stderr, "cannot connect output ports\n"); | |||||
} | |||||
free (ports); | |||||
/* keep running until the transport stops */ | |||||
while (client_state != Exit) { | |||||
sleep (1); | |||||
} | |||||
jack_client_close (client); | |||||
exit (0); | |||||
} |
@@ -1,157 +0,0 @@ | |||||
#include <stdio.h> | |||||
#include <stdlib.h> | |||||
#include <unistd.h> | |||||
#include <string.h> | |||||
#include <getopt.h> | |||||
#include <time.h> | |||||
#include <config.h> | |||||
#include <jack/jack.h> | |||||
char * my_name; | |||||
void | |||||
show_version (void) | |||||
{ | |||||
fprintf (stderr, "%s: JACK Audio Connection Kit version " VERSION "\n", | |||||
my_name); | |||||
} | |||||
void | |||||
show_usage (void) | |||||
{ | |||||
show_version (); | |||||
fprintf (stderr, "\nUsage: %s [options]\n", my_name); | |||||
fprintf (stderr, "Check for jack existence, or wait, until it either quits, or gets started\n"); | |||||
fprintf (stderr, "options:\n"); | |||||
fprintf (stderr, " -s, --server <name> Connect to the jack server named <name>\n"); | |||||
fprintf (stderr, " -w, --wait Wait for server to become available\n"); | |||||
fprintf (stderr, " -q, --quit Wait until server is quit\n"); | |||||
fprintf (stderr, " -c, --check Check wether server is running\n"); | |||||
fprintf (stderr, " -t, --timeout Wait timeout in seconds\n"); | |||||
fprintf (stderr, " -h, --help Display this help message\n"); | |||||
fprintf (stderr, " --version Output version information and exit\n\n"); | |||||
fprintf (stderr, "For more information see http://jackaudio.org/\n"); | |||||
} | |||||
void silent_function( const char *ignore ) | |||||
{ | |||||
} | |||||
int | |||||
main (int argc, char *argv[]) | |||||
{ | |||||
jack_client_t *client; | |||||
jack_status_t status; | |||||
jack_options_t options = JackNoStartServer; | |||||
int c; | |||||
int option_index; | |||||
char *server_name = NULL; | |||||
int wait_for_start = 0; | |||||
int wait_for_quit = 0; | |||||
int just_check = 0; | |||||
int wait_timeout = 0; | |||||
time_t start_timestamp; | |||||
struct option long_options[] = { | |||||
{ "server", 1, 0, 's' }, | |||||
{ "wait", 0, 0, 'w' }, | |||||
{ "quit", 0, 0, 'q' }, | |||||
{ "check", 0, 0, 'c' }, | |||||
{ "timeout", 1, 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:wqct:hv", 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 'w': | |||||
wait_for_start = 1; | |||||
break; | |||||
case 'q': | |||||
wait_for_quit = 1; | |||||
break; | |||||
case 'c': | |||||
just_check = 1; | |||||
break; | |||||
case 't': | |||||
wait_timeout = atoi(optarg); | |||||
break; | |||||
case 'h': | |||||
show_usage (); | |||||
return 1; | |||||
break; | |||||
case 'v': | |||||
show_version (); | |||||
return 1; | |||||
break; | |||||
default: | |||||
show_usage (); | |||||
return 1; | |||||
break; | |||||
} | |||||
} | |||||
/* try to open server in a loop. breaking under certein conditions */ | |||||
start_timestamp = time( NULL ); | |||||
jack_set_info_function( silent_function ); | |||||
while(1) { | |||||
client = jack_client_open ("wait", options, &status, server_name); | |||||
/* check for some real error and bail out */ | |||||
if( (client == NULL) && !(status & JackServerFailed) ) { | |||||
fprintf (stderr, "jack_client_open() failed, " | |||||
"status = 0x%2.0x\n", status); | |||||
return 1; | |||||
} | |||||
if( client == NULL ) { | |||||
if( wait_for_quit ) { | |||||
fprintf( stdout, "server is gone\n" ); | |||||
break; | |||||
} | |||||
if( just_check ) { | |||||
fprintf( stdout, "not running\n" ); | |||||
break; | |||||
} | |||||
} else { | |||||
jack_client_close( client ); | |||||
if( wait_for_start ) { | |||||
fprintf( stdout, "server is available\n" ); | |||||
break; | |||||
} | |||||
if( just_check ) { | |||||
fprintf( stdout, "running\n" ); | |||||
break; | |||||
} | |||||
} | |||||
if( wait_timeout ) { | |||||
if( (time( NULL ) - start_timestamp) > wait_timeout ) { | |||||
fprintf( stdout, "timeout\n" ); | |||||
break; | |||||
} | |||||
} | |||||
// Wait a second, and repeat | |||||
sleep(1); | |||||
} | |||||
exit (0); | |||||
} |