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_load' : 'ipload.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 = { | |||
| @@ -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; | |||
| void | |||
| static void | |||
| showtime () | |||
| { | |||
| jack_position_t current; | |||
| @@ -19,9 +19,7 @@ showtime () | |||
| transport_state = jack_transport_query (client, ¤t); | |||
| 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) { | |||
| case JackTransportStopped: | |||
| @@ -47,7 +45,7 @@ showtime () | |||
| printf ("\n"); | |||
| } | |||
| void | |||
| static void | |||
| jack_shutdown (void *arg) | |||
| { | |||
| exit (1); | |||
| @@ -66,7 +64,7 @@ main (int argc, char *argv[]) | |||
| { | |||
| /* 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"); | |||
| return 1; | |||
| } | |||