git-svn-id: http://subversion.jackaudio.org/jack/jack2/trunk/jackmp@2349 0c269be4-1314-0410-8aa9-9f06e86f4224tags/1.90
@@ -46,6 +46,11 @@ example_programs = { | |||||
'jack_zombie' : 'zombie.c', | 'jack_zombie' : 'zombie.c', | ||||
'jack_load' : 'ipload.c', | 'jack_load' : 'ipload.c', | ||||
'jack_unload' : 'ipunload.c', | 'jack_unload' : 'ipunload.c', | ||||
'jack_showtime' : 'showtime.c', | |||||
'jack_alias' : 'alias.c', | |||||
'jack_bufsize' : 'bufsize.c', | |||||
'jack_evmon' : 'evmon.c', | |||||
'jack_monitor_client' : 'monitor_client.c', | |||||
} | } | ||||
example_libs = { | example_libs = { | ||||
@@ -0,0 +1,118 @@ | |||||
#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; | |||||
} |
@@ -0,0 +1,96 @@ | |||||
/* | |||||
* 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; | |||||
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) { | |||||
fprintf(stderr, "usage: %s <bufsize>\n", package); | |||||
exit(9); | |||||
} | |||||
nframes = strtoul(argv[1], NULL, 0); | |||||
if (errno == ERANGE) { | |||||
fprintf(stderr, "%s: invalid buffer size: %s\n", | |||||
package, argv[1]); | |||||
exit(2); | |||||
} | |||||
} | |||||
int main(int argc, char *argv[]) | |||||
{ | |||||
int rc; | |||||
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); | |||||
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; | |||||
} |
@@ -0,0 +1,351 @@ | |||||
/* | |||||
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 <signal.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; | |||||
jack_client_t *client; | |||||
static void signal_handler(int sig) | |||||
{ | |||||
jack_client_close(client); | |||||
fprintf(stderr, "signal received, exiting ...\n"); | |||||
exit(0); | |||||
} | |||||
static 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; | |||||
} | |||||
static 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; | |||||
} | |||||
static void | |||||
jack_shutdown (void *arg) | |||||
{ | |||||
fprintf (stderr, "JACK shutdown\n"); | |||||
// exit (0); | |||||
abort(); | |||||
} | |||||
static 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); | |||||
} | |||||
info->duration *= sf_info.samplerate; | |||||
info->can_capture = 0; | |||||
pthread_create (&info->thread_id, NULL, disk_thread, info); | |||||
} | |||||
static 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; | |||||
} | |||||
} | |||||
static 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_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); | |||||
/* install a signal handler to properly quits jack client */ | |||||
signal(SIGQUIT, signal_handler); | |||||
signal(SIGTERM, signal_handler); | |||||
signal(SIGHUP, signal_handler); | |||||
signal(SIGINT, signal_handler); | |||||
run_disk_thread (&thread_info); | |||||
jack_client_close (client); | |||||
jack_ringbuffer_free (rb); | |||||
exit (0); | |||||
} |
@@ -0,0 +1,114 @@ | |||||
/* | |||||
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> | |||||
#ifndef WIN32 | |||||
#include <unistd.h> | |||||
#endif | |||||
#include <string.h> | |||||
#include <signal.h> | |||||
#include <stdlib.h> | |||||
#include <jack/jack.h> | |||||
jack_client_t *client; | |||||
static void signal_handler(int sig) | |||||
{ | |||||
jack_client_close(client); | |||||
fprintf(stderr, "signal received, exiting ...\n"); | |||||
exit(0); | |||||
} | |||||
static void | |||||
port_callback (jack_port_id_t port, int yn, void* arg) | |||||
{ | |||||
printf ("Port %d %s\n", port, (yn ? "registered" : "unregistered")); | |||||
} | |||||
static 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")); | |||||
} | |||||
static void | |||||
client_callback (const char* client, int yn, void* arg) | |||||
{ | |||||
printf ("Client %s %s\n", client, (yn ? "registered" : "unregistered")); | |||||
} | |||||
static int | |||||
graph_callback (void* arg) | |||||
{ | |||||
printf ("Graph reordered\n"); | |||||
return 0; | |||||
} | |||||
int | |||||
main (int argc, char *argv[]) | |||||
{ | |||||
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; | |||||
} | |||||
#ifdef WIN32 | |||||
signal(SIGINT, signal_handler); | |||||
signal(SIGABRT, signal_handler); | |||||
signal(SIGTERM, signal_handler); | |||||
#else | |||||
signal(SIGQUIT, signal_handler); | |||||
signal(SIGTERM, signal_handler); | |||||
signal(SIGHUP, signal_handler); | |||||
signal(SIGINT, signal_handler); | |||||
#endif | |||||
sleep (-1); | |||||
exit (0); | |||||
} | |||||
@@ -0,0 +1,246 @@ | |||||
/* | |||||
* 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 <signal.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; | |||||
jack_client_t *client; | |||||
static void signal_handler(int sig) | |||||
{ | |||||
jack_client_close(client); | |||||
fprintf(stderr, "signal received, exiting ...\n"); | |||||
exit(0); | |||||
} | |||||
static 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; | |||||
} | |||||
static void | |||||
jack_shutdown (void *arg) | |||||
{ | |||||
exit (1); | |||||
} | |||||
int | |||||
main (int argc, char *argv[]) | |||||
{ | |||||
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"; | |||||
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); | |||||
/* install a signal handler to properly quits jack client */ | |||||
signal(SIGQUIT, signal_handler); | |||||
signal(SIGTERM, signal_handler); | |||||
signal(SIGHUP, signal_handler); | |||||
signal(SIGINT, signal_handler); | |||||
/* 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); | |||||
} |
@@ -0,0 +1,46 @@ | |||||
#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); | |||||
} | |||||
@@ -9,7 +9,7 @@ | |||||
jack_client_t *client; | jack_client_t *client; | ||||
void | |||||
static void | |||||
showtime () | showtime () | ||||
{ | { | ||||
jack_position_t current; | jack_position_t current; | ||||
@@ -19,9 +19,7 @@ showtime () | |||||
transport_state = jack_transport_query (client, ¤t); | transport_state = jack_transport_query (client, ¤t); | ||||
frame_time = jack_frame_time (client); | frame_time = jack_frame_time (client); | ||||
//printf ("frame: %7" PRIu32 " @ %" PRIu32 "\t", current.frame, frame_time); | |||||
printf ("frame = %ld frame_time = %ld usecs = %lld \t", current.frame, frame_time, current.usecs); | |||||
printf ("frame = %u frame_time = %u usecs = %lld \t", current.frame, frame_time, current.usecs); | |||||
switch (transport_state) { | switch (transport_state) { | ||||
case JackTransportStopped: | case JackTransportStopped: | ||||
@@ -47,7 +45,7 @@ showtime () | |||||
printf ("\n"); | printf ("\n"); | ||||
} | } | ||||
void | |||||
static void | |||||
jack_shutdown (void *arg) | jack_shutdown (void *arg) | ||||
{ | { | ||||
exit (1); | exit (1); | ||||
@@ -66,7 +64,7 @@ main (int argc, char *argv[]) | |||||
{ | { | ||||
/* try to become a client of the JACK server */ | /* try to become a client of the JACK server */ | ||||
if ((client = jack_client_new ("showtime")) == 0) { | |||||
if ((client = jack_client_open ("showtime", JackNullOption, NULL)) == 0) { | |||||
fprintf (stderr, "jack server not running?\n"); | fprintf (stderr, "jack server not running?\n"); | ||||
return 1; | return 1; | ||||
} | } | ||||