jack-tools-20101210.orig/0000755000175000017500000000000011536646636013775 5ustar jonasjonasjack-tools-20101210.orig/jack.record.c0000644000175000017500000002010711536646636016326 0ustar jonasjonas/***** jack.record.c - (c) rohan drape, 2003-2006 *****/ #include #include #include #include #include #include #include "common/failure.h" #include "common/file.h" #include "common/jack-client.h" #include "common/jack-port.h" #include "common/jack-ringbuffer.h" #include "common/memory.h" #include "common/observe-signal.h" #include "common/print.h" #include "common/signal-interleave.h" #include "common/sound-file.h" struct recorder { int buffer_bytes; int buffer_samples; int buffer_frames; int minimal_frames; float timer_seconds; int timer_frames; int timer_counter; float sample_rate; float *d_buffer; float *j_buffer; float *u_buffer; int file_format; SNDFILE **sound_file; int multiple_sound_files; int channels; jack_port_t **input_port; float **in; jack_ringbuffer_t *ring_buffer; pthread_t disk_thread; int pipe[2]; }; void write_to_disk(struct recorder *d, int nframes) { if(d->multiple_sound_files) { float *p = d->u_buffer; signal_uninterleave(p, d->d_buffer, nframes, d->channels); int i; for(i = 0; i < d->channels; i++) { xsf_write_float(d->sound_file[i], p, (sf_count_t)nframes); p += nframes; } } else { int nsamples = nframes * d->channels; xsf_write_float(d->sound_file[0], d->d_buffer, (sf_count_t)nsamples); } } void *disk_thread_procedure(void *PTR) { struct recorder *d = (struct recorder *) PTR; while(!observe_end_of_process()) { /* Wait for data at the ring buffer. */ int nbytes = d->minimal_frames * sizeof(float) * d->channels; nbytes = jack_ringbuffer_wait_for_read(d->ring_buffer, nbytes, d->pipe[0]); /* Drop excessive data to not overflow the local buffer. */ if(nbytes > d->buffer_bytes) { eprintf("jack.record: impossible condition, read space.\n"); nbytes = d->buffer_bytes; } /* Read data from the ring buffer. */ jack_ringbuffer_read(d->ring_buffer, (char *) d->d_buffer, nbytes); /* Do write operation. The sample count *must* be an integral number of frames. */ int nframes = (nbytes / sizeof(float))/ d->channels; write_to_disk(d, nframes); /* Handle timer */ d->timer_counter += nframes; if(d->timer_frames > 0 && d->timer_counter >= d->timer_frames) { return NULL; } } return NULL; } /* Write data from the JACK input ports to the ring buffer. If the disk thread is late, ie. the ring buffer is full, print an error and halt the client. */ int process(jack_nframes_t nframes, void *PTR) { struct recorder *d = (struct recorder *) PTR; int nsamples = nframes * d->channels; int nbytes = nsamples * sizeof(float); /* Get port data buffers. */ int i; for(i = 0; i < d->channels; i++) { d->in[i] = (float *) jack_port_get_buffer(d->input_port[i], nframes); } /* Check period size is workable. If the buffer is large, ie 4096 frames, this should never be of practical concern. */ if(nbytes >= d->buffer_bytes) { eprintf("jack.record: period size exceeds limit\n"); FAILURE; return 1; } /* Check that there is adequate space in the ringbuffer. */ int space = (int) jack_ringbuffer_write_space(d->ring_buffer); if(space < nbytes) { eprintf("jack.record: overflow error, %d > %d\n", nbytes, space); FAILURE; return 1; } /* Interleave input to buffer and copy into ringbuffer. */ signal_interleave_to(d->j_buffer, (const float **)d->in, nframes, d->channels); int err = jack_ringbuffer_write(d->ring_buffer, (char *) d->j_buffer, (size_t) nbytes); if(err != nbytes) { eprintf("jack.record: error writing to ringbuffer, %d != %d\n", err, nbytes); FAILURE; return 1; } /* Poke the disk thread to indicate data is on the ring buffer. */ char b = 1; xwrite(d->pipe[1], &b, 1); return 0; } void usage(void) { eprintf("Usage: jack.record [ options ] sound-file\n"); eprintf(" -b N : Ring buffer size in frames (default=4096).\n"); eprintf(" -f N : File format (default=0x10006).\n"); eprintf(" -m N : Minimal disk read size in frames (default=32).\n"); eprintf(" -n N : Number of channels (default=2).\n"); eprintf(" -s : Write to multiple single channel sound files.\n"); eprintf(" -t N : Set a timer to record for N seconds (default=-1).\n"); FAILURE; } int main(int argc, char *argv[]) { observe_signals (); struct recorder d; d.buffer_frames = 4096; d.minimal_frames = 32; d.channels = 2; d.timer_seconds = -1.0; d.timer_counter = 0; d.file_format = SF_FORMAT_WAV | SF_FORMAT_FLOAT; d.multiple_sound_files = 0; int c; while((c = getopt(argc, argv, "b:f:hm:n:st:")) != -1) { switch(c) { case 'b': d.buffer_frames = (int) strtol(optarg, NULL, 0); break; case 'f': d.file_format = (int) strtol(optarg, NULL, 0); break; case 'h': usage (); break; case 'm': d.minimal_frames = (int) strtol(optarg, NULL, 0); break; case 'n': d.channels = (int) strtol(optarg, NULL, 0); break; case 's': d.multiple_sound_files = 1; break; case 't': d.timer_seconds = (float) strtod(optarg, NULL); break; default: eprintf("jack.record: illegal option, %c\n", c); usage (); break; } } if(optind != argc - 1) { usage (); } /* Allocate channel based data. */ if(d.channels < 1) { eprintf("jack.record: illegal number of channels: %d\n", d.channels); FAILURE; } d.in = xmalloc(d.channels * sizeof(float *)); d.sound_file = xmalloc(d.channels * sizeof(SNDFILE *)); d.input_port = xmalloc(d.channels * sizeof(jack_port_t *)); /* Connect to JACK. */ jack_client_t *client = jack_client_unique("jack.record"); jack_set_error_function(jack_client_minimal_error_handler); jack_on_shutdown(client, jack_client_minimal_shutdown_handler, 0); jack_set_process_callback(client, process, &d); d.sample_rate = jack_get_sample_rate(client); /* Setup timer. */ if(d.timer_seconds < 0.0) { d.timer_frames = -1; } else { d.timer_frames = d.timer_seconds * d.sample_rate; } /* Create sound file. */ SF_INFO sfinfo; sfinfo.samplerate = (int) d.sample_rate; sfinfo.frames = 0; sfinfo.format = d.file_format; if(d.multiple_sound_files) { if(!strstr(argv[optind], "%d")) { eprintf("jack.record: illegal template, '%s'\n", argv[optind]); usage (); } sfinfo.channels = 1; int i; for(i = 0; i < d.channels; i++) { char name[512]; snprintf(name, 512, argv[optind], i); d.sound_file[i] = xsf_open(name, SFM_WRITE, &sfinfo); } } else { sfinfo.channels = d.channels; d.sound_file[0] = xsf_open(argv[optind], SFM_WRITE, &sfinfo); } /* Allocate buffers. */ d.buffer_samples = d.buffer_frames * d.channels; d.buffer_bytes = d.buffer_samples * sizeof(float); d.d_buffer = xmalloc(d.buffer_bytes); d.j_buffer = xmalloc(d.buffer_bytes); d.u_buffer = xmalloc(d.buffer_bytes); d.ring_buffer = jack_ringbuffer_create(d.buffer_bytes); /* Create communication pipe. */ xpipe(d.pipe); /* Start disk thread. */ pthread_create (&(d.disk_thread), NULL, disk_thread_procedure, &d); /* Create input ports and activate client. */ jack_port_make_standard(client, d.input_port, d.channels, false); jack_client_activate(client); /* Wait for disk thread to end, which it does when it reaches the end of the file or is interrupted. */ pthread_join(d.disk_thread, NULL); /* Close sound file, free ring buffer, close JACK connection, close pipe, free data buffers, indicate success. */ jack_client_close(client); if(d.multiple_sound_files) { int i; for(i = 0; i < d.channels; i++) { sf_close(d.sound_file[i]); } } else { sf_close(d.sound_file[0]); } jack_ringbuffer_free(d.ring_buffer); close(d.pipe[0]); close(d.pipe[1]); free(d.d_buffer); free(d.j_buffer); free(d.u_buffer); free(d.in); free(d.input_port); free(d.sound_file); return EXIT_SUCCESS; } jack-tools-20101210.orig/config/0000755000175000017500000000000011536646636015242 5ustar jonasjonasjack-tools-20101210.orig/jack.record.text0000644000175000017500000000414611536646636017075 0ustar jonasjonasJACK.RECORD(1) ============== Rohan Drape NAME ---- jack.record - JACK Capture Client SYNOPSIS -------- jack.record [options] sound-file OPTIONS ------- *-b* : Set the disk buffer size in frames (default=4096). This value must be a power of two. If the JACK period size at any time exceeds this value the recorder will halt. *-f* : Set the file format (default=0x10006). The number is a bitwise-or of two values, the first describes the file type, the second the data type. The default value of 0x10000 | 0x00006 describes a thirty-two bit floating point WAV file. *-m* : Set the minimal disk transfer size in frames (default=32). This is an optimization switch. *-n* : Set the number of input channels to create (default=2). *-s* : Capture to a set of single channel sound files. The sound file name must be a valid template. *-t* : Set a timer to stop the recording after the specified number of seconds (default=-1). DESCRIPTION ----------- jack.record is a light-weight JACK capture client to write an arbitrary number of channels to disk. It implements no connection logic, use jack.plumbing(1) instead. If the default mode a single multiple channel sound file is written. If the *-s* option is given a set of single channel sound files are written. In this case the sound file name must be a valid template, the substring %d is replaced with the channel number counting from zero. jack.record will write files in any format supported by libsndfile. The table below shows the most common file format masks. For other values see the file 'sndfile.h'. Format Code Description ------ ---- ----------- SF_FORMAT_WAV 0x10000 Microsoft WAV format SF_FORMAT_AIFF 0x20000 Apple/SGI AIFF format SF_FORMAT_PCM_16 0x00002 Signed 16 bit data SF_FORMAT_PCM_24 0x00003 Signed 24 bit data SF_FORMAT_PCM_32 0x00004 Signed 32 bit data SF_FORMAT_FLOAT 0x00006 32 bit float data AUTHOR ------ Rohan Drape SEE ALSO -------- jackd(1), libsndfile(3) jack-tools-20101210.orig/.boring0000644000175000017500000000042611536646636015260 0ustar jonasjonas.deps .libs .*\.o$ aclocal.m4 autom4te.cache config/.* config.log config.status configure common/\.deps common/.*\.o common/Makefile jack\.dl$ jack\.osc$ jack\.play$ jack\.plumbing$ jack\.record$ jack\.scope$ jack\.transport$ jack\.udp$ libcommon.a libtool Makefile.in Makefile jack-tools-20101210.orig/Makefile.am0000644000175000017500000000356311536646636016040 0ustar jonasjonasMAINTAINERCLEANFILES = aclocal.m4 \ config.guess \ config.log \ config.status \ config.sub \ configure \ depcomp \ install-sh \ ltmain.sh \ Makefile.in \ missing \ mkinstalldirs SUBDIRS = common bin_PROGRAMS = jack.dl \ jack.osc \ jack.play \ jack.plumbing \ jack.record \ jack.scope \ jack.transport \ jack.udp jack_dl_SOURCES = jack.dl.c jack_dl_LDADD = common/libcommon.a $(JACK_LIBS) $(LIBLO_LIBS) jack_dl_CFLAGS = $(AM_CFLAGS) $(JACK_CFLAGS) $(LIBLO_CFLAGS) jack_dl_includedir = $(includedir) jack_dl_include_HEADERS = jack.dl.h jack_osc_SOURCES = jack.osc.c jack_osc_LDADD = common/libcommon.a $(JACK_LIBS) jack_osc_CFLAGS = $(AM_CFLAGS) $(JACK_CFLAGS) jack_play_SOURCES = jack.play.c jack_play_LDADD = common/libcommon.a $(JACK_LIBS) $(SNDFILE_LIBS) $(SRC_LIBS) jack_play_CFLAGS = $(AM_CFLAGS) $(JACK_CFLAGS) $(SNDFILE_CFLAGS) $(SRC_CFLAGS) jack_plumbing_SOURCES = jack.plumbing.c jack_plumbing_LDADD = common/libcommon.a $(JACK_LIBS) jack_plumbing_CFLAGS = $(AM_CFLAGS) $(JACK_CFLAGS) jack_record_SOURCES = jack.record.c jack_record_LDADD = common/libcommon.a $(JACK_LIBS) $(SNDFILE_LIBS) jack_record_CFLAGS = $(AM_CFLAGS) $(JACK_CFLAGS) $(SNDFILE_CFLAGS) jack_scope_SOURCES = jack.scope.c jack_scope_LDADD = common/libcommon.a $(JACK_LIBS) $(X11_LIBS) $(XEXT_LIBS) jack_scope_CFLAGS = $(AM_CFLAGS) $(JACK_CFLAGS) $(X11_CFLAGS) $(XEXT_CFLAGS) jack_transport_SOURCES = jack.transport.c jack_transport_LDADD = common/libcommon.a $(JACK_LIBS) -lncurses jack_transport_CFLAGS = $(AM_CFLAGS) $(JACK_CFLAGS) jack_udp_SOURCES = jack.udp.c jack_udp_LDADD = common/libcommon.a $(JACK_LIBS) jack_udp_CFLAGS = $(AM_CFLAGS) $(JACK_CFLAGS) docs_ASCIIDOC = jack.osc.text \ jack.play.text \ jack.plumbing.text \ jack.record.text \ jack.scope.text \ jack.transport.text \ jack.udp.text EXTRA_DIST = $(docs_ASCIIDOC) help/sin.c help/sin.scm jack-tools-20101210.orig/jack.transport.c0000644000175000017500000000606711536646636017115 0ustar jonasjonas/***** jack.transport.c - (c) rohan drape, 2006-2008 *****/ #include #include #include #include #include #include #include #include struct transport { bool rolling; double time; double incr; double skip; jack_client_t *jk; }; void finish(int sig) { endwin(); exit(0); } void shutdown(void *PTR) { exit(1); } void getcmd(const char *prompt, char *result, int n) { move(2,0); addstr(prompt); echo(); getnstr(result, n); noecho(); halfdelay(1); move(2,0); clrtoeol(); } double getnum(const char *prompt) { char tmp[512]; getcmd(prompt, tmp, 512); return strtod(tmp, NULL); } void mvaddtime(int x, int y, double t) { char tmp[512]; time_t a = floor(t); struct tm *b = gmtime(&a); strftime(tmp, 512, "%H:%M:%S", b); mvaddstr(x, y, tmp); } void locate(struct transport *t) { jack_nframes_t frame = t->time * jack_get_sample_rate(t->jk); jack_transport_locate(t->jk, frame); } void offset(struct transport *t, double o) { t->time += o; if(t->time < 0.0) { t->time = 0.0; } locate(t); } int main(int argc, char **argv) { struct transport t; t.rolling = false; t.time = 0.0; t.incr = 5.0; t.skip = 60.0; t.jk = jack_client_open("jack.transport", JackNullOption, NULL); if(t.jk) { jack_on_shutdown(t.jk, shutdown, 0); jack_activate(t.jk); } else { fprintf(stderr, "jack.transport: could not connect to jack.\n"); exit(1); } signal(SIGINT, finish); initscr(); keypad(stdscr, TRUE); nonl(); halfdelay(1); noecho(); while (1) { int c; jack_transport_state_t s; jack_position_t p; s = jack_transport_query(t.jk , &p); t.rolling = s & JackTransportRolling; t.time = (double)p.frame / (double)p.frame_rate; c = getch(); switch(c) { case 'r': erase(); refresh(); break; case ' ': if(t.rolling) { jack_transport_stop(t.jk); } else { jack_transport_start(t.jk); } break; case '>': case KEY_RIGHT: offset(&t, t.incr); break; case '.': case KEY_UP: offset(&t, t.skip); break; case '<': case KEY_LEFT: offset(&t, -t.incr); break; case KEY_DOWN: case ',': offset(&t, -t.skip); break; case 'z': case KEY_SLEFT: t.time = 0.0; locate(&t); break; case 'i': t.incr = getnum("Set increment: "); break; /* A little bit clever, start typing a number to enter locate mode... */ case '0': case '1': case '2': case '3': case '4': case '5': case '6': case '7': case '8': case '9': ungetch(c); case 'l': t.time = getnum("Locate to: "); locate(&t); break; case 'q': finish(SIGINT); break; case ERR: break; } mvaddstr(0, 0, "jack.transport - (c) rohan drape, 2006-2008"); mvaddch(1, 0, t.rolling ? ACS_RARROW : ACS_BLOCK); mvaddtime(1, 4, t.time); } jack_client_close(t.jk); endwin(); return 0; } jack-tools-20101210.orig/jack.plumbing.text0000644000175000017500000000540311536646636017431 0ustar jonasjonasJACK.PLUMBING(1) =============== Rohan Drape NAME ---- jack.plumbing - JACK Plumbing Daemon SYNOPSIS -------- jack.plumbing [options] [rule-files] OPTIONS ------- *-d* : Do not operate as a daemon. *-o* : Do not load ordinary rule files. *-q* : Quiet operation. *-u* : Set the time, in micro-seconds, that must elapse after a connection notification to indicate the end of a notification set (default=30000). This is an optimization switch. DESCRIPTION ----------- jack.plumbing maintains a set of port connection rules and manages these as clients register ports with JACK. Port names are implicitly bounded regular expressions and support sub-expression patterns. There are four rules: connect, disconnect, also-connect and connect-exclusive. (connect "SuperCollider:out_(.*)" "system:playback_\1") This connect rule ensures that whenever scsynth(1) is running any output ports it registers are connected to appropriate ALSA playback ports. The connect rule only makes a connection if none already exist. (also-connect "system:playback_1" "jack.udp-[0-9]*:in_1") This also-connect rule ensures that when jack.udp(1) is running in send mode all signals that are ordinarily sent to the local audio interface will also be sent to the network destination. The also-connect aliasing applies to both the left and right hand side of connect rules. (connect-exclusive "SuperCollider:out_(.*)" "ardour:sc3_in_\1/in 1") This connect-exclusive rule ensures that if SuperCollider and an ardour(1) session with appropriate tracks are both running that SuperCollider gets connected to ardour and disconnected from everything else. This type of connection daemon has the following advantages over both environment variables and command line arguments: * it does not require any client connection support or logic at all * it provides a uniform user interface to all clients * it has a somewhat declarative style This type of daemon is very lightweight and non-intrusive: it requires no arguments, it runs from an unprivileged thread, if the rule set is empty it is a no-op, it does not write any files, it does not require any modification to clients or to how clients are started. When a set of port registrations is made it checks the modification time of the rule set files, '/etc/jack.plumbing' and '~/.jack.plumbing', and any files specified by the user, rereads the rule set if it has been updated, then makes the JACK graph obey the rules. Any lines beginning with a semi-colon are ignored. The rule set is sorted, disconnect rules are applied first, then connect rules, then connect-exclusive rules. FILES ----- * /etc/jack.plumbing * ~/.jack.plumbing AUTHOR ------ Written by Rohan Drape SEE ALSO -------- jackd(1) jack-tools-20101210.orig/jack.dl.text0000644000175000017500000000207511536646636016215 0ustar jonasjonasJACK.DL(1) ========== Rohan Drape NAME ---- jack.dl - JACK shared library dsp loader SYNOPSIS -------- jack.dl [options] OPTIONS ------- *-c* : Set the number of input and output channels (default=8). *-g* : Set the number of graph slots (default=8). *-k* : Set the number of control buses (default=64). *-p* : Set the udp port number (default=57190). DESCRIPTION ----------- jack.dl loads dsp algorithms from shared libraries. Commands are sent as OSC packets over a UDP connection. jack.dl allows data flow code generators to be used as interactively. Clients load dsp graphs by sending a "graph load" packet: /g_load index object-file where index is an integer and object-file a file name. jack.dl implements only a subset of the OSC protocol. In particular it does not implement the patten matching rules and does not implement a scheduler for incoming messages. jack.dl drops all unrecognized incoming packets. AUTHOR ------ Rohan Drape SEE ALSO -------- jackd(1), OSC(7) jack-tools-20101210.orig/README0000644000175000017500000000145411536646636014661 0ustar jonasjonasjack.* - jackd[1] utilities jack.dl - load dsp algorithms from shared libraries jack.osc - jack <-> open sound control (osc[4]) daemon jack.play - soundfile[2] playback jack.plumbing - plumbing daemon jack.record - soundfile recording jack.scope - plain X oscilloscope jack.transport - minimalist ncurses jack transport jack.udp - jack over udp client (obsolete, see netjack[3]) Documentation is in asciidoc[5] format. To build type: for i in *.text ; do asciidoc $i; done [1] http://jackaudio.org/ [2] http://mega-nerd.com/libsndfile/ [3] http://netjack.org/ [4] http://opensoundcontrol.org/ [5] http://www.methods.co.nz/asciidoc/ (c) rohan drape 2003-2010 gpl, http://www.gnu.org/copyleft/ with contributions by jeremy hall see darcs history for details jack-tools-20101210.orig/help/0000755000175000017500000000000011536646636014725 5ustar jonasjonasjack-tools-20101210.orig/help/sin.scm0000644000175000017500000000135111536646636016222 0ustar jonasjonas(define with-jackdl (lambda (f) (let* ((fd (udp:open "127.0.0.1" 57190)) (r (f fd))) (udp:close fd) r))) (define g-load (lambda (i s) (message "/g_load" (list i s)))) (define p-set1 (lambda (g i n) (message "/p_set1" (list g i n)))) (define set-sin (lambda (g f a p) (with-jackdl (lambda (fd) (send fd (p-set1 g 0 f)) (send fd (p-set1 g 1 a)) (send fd (p-set1 g 2 p)))))) (with-jackdl (lambda (fd) (for-each (lambda (g) (send fd (g-load g "/home/rohan/sw/jack.*/help/sin.so"))) (list 0 1 2)))) (set-sin (i-random 0 3) (random 220 880) (random 0.1 0.25) (random 0 1)) (with-jackdl (lambda (fd) (send fd quit))) jack-tools-20101210.orig/help/scope.scm0000644000175000017500000000062111536646636016541 0ustar jonasjonas(import (sosc)) (define fd (udp:open "127.0.0.1" 57140)) (define set-scope (lambda (cmd arg) (send fd (list cmd arg)))) (set-scope "/frames" 1024) (set-scope "/delay" (/ 1000.0 24.0)) (set-scope "/mode" "signal") (set-scope "/style" "fill") (set-scope "/style" "line") (set-scope "/style" "dot") (set-scope "/mode" "embed") (set-scope "/incr" 0.1) (set-scope "/embed" 64) (udp:close fd) jack-tools-20101210.orig/help/sin.c0000644000175000017500000000342711536646636015670 0ustar jonasjonas/* gcc -shared -I ~/include sin.c -o sin.so */ #include #include #include struct sinosc { float f; /* frequency */ float a; /* amplitude */ float p; /* pan */ float phase; /* oscillator phase */ }; #define TWO_PI (2 * M_PI) /* convert frequency in hertz to phase increment in radians */ float hz_to_incr(float hz, float sr) { return (TWO_PI / sr) * hz; } /* increment phase within (0,2pi) */ float step_phasor(float *phase, float incr) { *phase += incr; if(*phase > TWO_PI) { *phase -= TWO_PI; } } /* allocate state data and initialize private control data */ void *dsp_init(struct world *w, int g) { struct sinosc *s = malloc(sizeof(struct sinosc)); s->phase = 0.0; s->f = 440.0; s->a = 0.1; s->p = 0.5; w_p_set1(w, g, 0, s->f); w_p_set1(w, g, 1, s->a); w_p_set1(w, g, 2, s->p); return (void*)s; } /* process nf frames of data */ void dsp_step(struct world *w, int g, void *ptr, int nf) { int i; struct sinosc *s = (struct sinosc *)ptr; /* load state */ float f = s->f; float a = s->a; float p = s->p; float phase = s->phase; /* read control values */ float fe = w_p_get1(w, g, 0); float ae = w_p_get1(w, g, 1); float pe = w_p_get1(w, g, 2); /* calculate control increments */ float fi = (fe - f) / (float)nf; float ai = (ae - a) / (float)nf; float pi = (pe - p) / (float)nf; for(i = 0; i < nf; i++) { /* algorithm */ float n = sinf(phase) * a; w_out2(w, i, n * p, n * (1 - p)); float incr = hz_to_incr(f, w_sr(w)); step_phasor(&phase, incr); /* apply control increments */ f += fi; a += ai; p += pi; } /* store state */ s->f = fe; s->a = ae; s->p = pe; s->phase = phase; } jack-tools-20101210.orig/jack.play.c0000644000175000017500000002707211536646636016025 0ustar jonasjonas/***** jack.play.c - (c) rohan drape, 2003-2010 *****/ #include #include #include #include #include #include #include #include #include #include #include "common/failure.h" #include "common/file.h" #include "common/int.h" #include "common/jack-client.h" #include "common/jack-ringbuffer.h" #include "common/jack-port.h" #include "common/jack-transport.h" #include "common/memory.h" #include "common/observe-signal.h" #include "common/print.h" #include "common/sound-file.h" struct player_opt { int buffer_frames; int minimal_frames; i64 seek_request; bool transport_aware; int unique_name; double src_ratio; int rb_request_frames; int converter; char client_name[64]; }; struct player { int buffer_bytes; int buffer_samples; float *d_buffer; float *j_buffer; float *k_buffer; SNDFILE *sound_file; int channels; jack_port_t **output_port; float **out; jack_ringbuffer_t *rb; pthread_t disk_thread; int pipe[2]; jack_client_t *client; SRC_STATE *src; struct player_opt o; }; /* Read the sound file from disk and write to the ring buffer until the end of file, at which point return. */ void *disk_proc(void *PTR) { struct player *d = (struct player *)PTR; while(!observe_end_of_process()) { /* Handle seek request. */ if(d->o.seek_request >= 0) { sf_count_t err = sf_seek(d->sound_file, (sf_count_t)d->o.seek_request, SEEK_SET); if(err == -1) { eprintf("jack.play: seek request failed, %ld\n", (long)d->o.seek_request); } d->o.seek_request = -1; } /* Wait for write space at the ring buffer. */ int nbytes = d->o.minimal_frames * sizeof(float) * d->channels; nbytes = jack_ringbuffer_wait_for_write(d->rb, nbytes, d->pipe[0]); /* Do not overflow the local buffer. */ if(nbytes > d->buffer_bytes) { eprintf("jack.play: impossible condition, write space.\n"); nbytes = d->buffer_bytes; } /* Read sound file data, which *must* be frame aligned. */ int nframes =(nbytes / sizeof(float))/ d->channels; int nsamples = nframes * d->channels; sf_count_t err = xsf_read_float(d->sound_file, d->d_buffer, (sf_count_t)nsamples); if(err == 0) { if(d->o.transport_aware) { memset(d->d_buffer, 0, nsamples * sizeof(float)); err = nsamples; } else { return NULL; } } /* Write data to ring buffer. */ jack_ringbuffer_write(d->rb, (char *)d->d_buffer, (size_t)err * sizeof(float)); } return NULL; } int sync_handler(jack_transport_state_t state, jack_position_t *position, void *PTR) { struct player *d = PTR; d->o.seek_request = (i64)position->frame; return 1; } void signal_set(float **s, int n, int c, float z) { int j; for(j = 0; j < c; j++) { int i; for(i = 0; i < n; i++) { s[j][i] = z; } } } /* Write data from the ring buffer to the JACK output ports. If the disk thread is late, ie. the ring buffer is empty print a warning and zero the output ports. */ int signal_proc(jack_nframes_t nframes, void *PTR) { struct player *d = (struct player *)PTR; int nsamples = nframes * d->channels; int nbytes = nsamples * sizeof(float); /* Ensure the period size is workable. */ if(nbytes >= d->buffer_bytes) { eprintf("jack.play: period size exceeds limit\n"); FAILURE; return 1; } /* Get port data buffers. */ int i,j; for(i = 0; i < d->channels; i++) { d->out[i] = (float *)jack_port_get_buffer(d->output_port[i], nframes); } /* Write silence if the transport is stopped. If stopped the disk thread will sleep and signals will be ignored, so check here also. */ if(d->o.transport_aware && !jack_transport_is_rolling(d->client)) { if(observe_end_of_process ()) { FAILURE; return 1; } else { signal_set(d->out, nframes, d->channels, 0.0); return 0; } } /* Get data from sample rate converter, this returns the number of frames acquired. */ long err = src_callback_read (d->src, d->o.src_ratio, (long)nframes, d->j_buffer); if(err==0) { eprintf("jack.play: sample rate converter failed: %s\n", src_strerror(src_error(d->src))); FAILURE; } /* Uninterleave available data to the output buffers. */ for(i = 0; i < err; i++) { for(j = 0; j < d->channels; j++) { d->out[j][i] = d->j_buffer[(i*d->channels)+j]; } } /* If any sample data is unavailable inform the user and zero the output buffers. The print statement is not correct, a this should set a flag and have another thread take appropriate action. */ if(err < nframes) { eprintf("jack.play: disk thread late (%ld < %d)\n", err, nframes); for(i = err; i < nframes; i++) { for(j = 0; j < d->channels; j++) { d->out[j][i] = 0.0; } } } /* Indicate to the disk thread that the ring buffer has been read from. This is done by writing a single byte to a communication pipe. Once the disk thread gets so far ahead that the ring buffer is full it reads this communication channel to wait for space to become available. So long as PIPE_BUF is not a pathologically small value this write operation is atomic and will not block. The number of bytes that can accumulate in the pipe is a factor of the relative sizes of the ring buffer and the process callback, but should in no case be very large. */ char b = 1; xwrite(d->pipe[1], &b, 1); return 0; } void usage(void) { eprintf("Usage: jack.play [ options ] sound-file...\n"); eprintf(" -b N : Ring buffer size in frames (default=4096).\n"); eprintf(" -c N : ID of conversion algorithm (default=2, SRC_SINC_FASTEST).\n"); eprintf(" -i N : Initial disk seek in frames (default=0).\n"); eprintf(" -m N : Minimal disk read size in frames (default=32).\n"); eprintf(" -q N : Frames to request from ring buffer (default=64).\n"); eprintf(" -r N : Resampling ratio multiplier (default=1.0).\n"); eprintf(" -t : Jack transport awareness.\n"); FAILURE; } /* Get data from ring buffer. Return number of frames read. This could check the read size first, but then would still need to check the actual result size, and therefore have two error cases. Since there is no alternative but to drop sample data in any case it does not matter much. */ long read_input_from_rb(void *PTR, float **buf) { struct player *d = PTR; int nsamples = d->channels * d->o.rb_request_frames; int nbytes = (size_t)nsamples * sizeof(float); int err = jack_ringbuffer_read(d->rb, (char *)d->k_buffer, nbytes); err /= d->channels * sizeof(float); *buf = d->k_buffer; /* SRC locks up if we return zero here, return a silent frame */ if(err==0) { eprintf("jack.play: ringbuffer empty... zeroing data\n"); memset(d->k_buffer, 0, (size_t)nsamples * sizeof(float)); err = d->o.rb_request_frames; } return (long)err; } int jackplay(const char *file_name, struct player_opt o) { struct player d; d.o = o; observe_signals (); /* Open sound file. */ SF_INFO sfinfo; d.sound_file = xsf_open(file_name, SFM_READ, &sfinfo); d.channels = sfinfo.channels; /* Allocate channel based data. */ if(d.channels < 1) { eprintf("jack.play: illegal number of channels in file: %d\n", d.channels); FAILURE; } d.out = xmalloc(d.channels * sizeof(float *)); d.output_port = xmalloc(d.channels * sizeof(jack_port_t *)); /* Allocate buffers. */ d.buffer_samples = d.o.buffer_frames * d.channels; d.buffer_bytes = d.buffer_samples * sizeof(float); d.d_buffer = xmalloc(d.buffer_bytes); d.j_buffer = xmalloc(d.buffer_bytes); d.k_buffer = xmalloc(d.buffer_bytes); d.rb = jack_ringbuffer_create(d.buffer_bytes); /* Setup sample rate conversion. */ int err; d.src = src_callback_new (read_input_from_rb, d.o.converter, d.channels, &err, &d); if(!d.src) { eprintf("jack.play: sample rate conversion setup failed: %s\n", src_strerror(err)); FAILURE; } /* Create communication pipe. */ xpipe(d.pipe); /* Become a client of the JACK server. */ if(d.o.unique_name) { d.client = jack_client_unique_store(d.o.client_name); } else { d.client = jack_client_open(d.o.client_name,JackNullOption,NULL); } if(!d.client) { eprintf("jack.play: could not create jack client: %s", d.o.client_name); FAILURE; } /* Start disk thread, the priority number is a random guess.... */ jack_client_create_thread (d.client, &(d.disk_thread), 50, true, disk_proc, &d); /* Set error, process and shutdown handlers. */ jack_set_error_function(jack_client_minimal_error_handler); jack_on_shutdown(d.client, jack_client_minimal_shutdown_handler, 0); if(d.o.transport_aware) { jack_set_sync_callback(d.client, sync_handler, &d); } jack_set_process_callback(d.client, signal_proc, &d); /* Inform the user of sample-rate mismatch. */ int osr = jack_get_sample_rate(d.client); int isr = sfinfo.samplerate; if(osr != isr) { d.o.src_ratio *= (osr / isr); eprintf("jack.play: resampling, sample rate of file != server, %d != %d\n", isr, osr); } /* Create output ports, connect if env variable set and activate client. */ jack_port_make_standard(d.client, d.output_port, d.channels, true); jack_client_activate(d.client); char *dst_pattern = getenv("JACK_PLAY_CONNECT_TO"); if (dst_pattern) { char src_pattern[128]; snprintf(src_pattern,128,"%s:out_%%d",d.o.client_name); jack_port_connect_pattern(d.client,d.channels,src_pattern,dst_pattern); } /* Wait for disk thread to end, which it does when it reaches the end of the file or is interrupted. */ pthread_join(d.disk_thread, NULL); /* Close sound file, free ring buffer, close JACK connection, close pipe, free data buffers, indicate success. */ jack_client_close(d.client); sf_close(d.sound_file); jack_ringbuffer_free(d.rb); close(d.pipe[0]); close(d.pipe[1]); free(d.d_buffer); free(d.j_buffer); free(d.k_buffer); free(d.out); free(d.output_port); src_delete(d.src); return 0; } int main(int argc, char *argv[]) { struct player_opt o; int c; o.buffer_frames = 4096; o.minimal_frames = 32; o.seek_request = -1; o.transport_aware = false; o.unique_name = true; o.src_ratio = 1.0; o.rb_request_frames = 64; o.converter = SRC_SINC_FASTEST; strncpy(o.client_name, "jack.play", 64); while((c = getopt(argc, argv, "b:c:hi:m:n:q:r:tu")) != -1) { switch(c) { case 'b': o.buffer_frames = (int)strtol(optarg, NULL, 0); break; case 'c': o.converter = (int)strtol(optarg, NULL, 0); break; case 'h': usage (); break; case 'i': o.seek_request = (i64)strtol(optarg, NULL, 0); break; case 'm': o.minimal_frames = (int)strtoll(optarg, NULL, 0); break; case 'n': strncpy(o.client_name, optarg, 64); eprintf("jack client name: %s\n", o.client_name); break; case 'q': o.rb_request_frames = strtol(optarg, NULL, 0); break; case 'r': o.src_ratio = strtod(optarg, NULL); break; case 't': o.transport_aware = true; case 'u': o.unique_name = false; break; default: eprintf("jack.play: illegal option, %c\n", c); usage (); break; } } if(optind > argc - 1) { usage (); } int i; for(i = optind; i < argc; i++) { printf("jack.play: %s\n", argv[i]); jackplay(argv[i], o); } return EXIT_SUCCESS; } jack-tools-20101210.orig/jack.udp.text0000644000175000017500000000271211536646636016404 0ustar jonasjonasJACK.UDP(1) =========== Rohan Drape NAME ---- jack.udp - JACK UDP Transport Client SYNOPSIS -------- jack.udp [options] send|recv OPTIONS ------- *-b* : Set the ring buffer size in frames (default=4096). *-c* : Set the client name (default=jack.udp-PID). *-n* : Set the number of channels, and therefore the number of JACK ports (default=2). *-p* : Set the port number (default=57160). *-r* : The remote host name, for use in send mode (default="127.0.0.1"). DESCRIPTION ----------- jack.udp is a UDP audio transport mechansim for JACK. The send mode reads signals from a set of JACK input ports and sends UDP packets to the indicated port at the indicated host at a rate determined by the local JACK daemon. The recv mode reads incoming packets at the indi- cated port and writes the incoming data to a set of JACK output ports at a rate that is determined by the local JACK daemon. This transport mechanism is unreliable. Both send and recv clients will report buffer overflow and underflow occurences, and recv clients will report dropped and out-of-order packets, and shutdown on channel mismatch packets. In practice this mechanism can be made highly reli- able over local networks. jack.udp implements no connection logic, use jack.plumbing(1) instead. EXAMPLE ------- 192.0.0.1:~$ jack.udp -r 192.0.0.2 send 192.0.0.2:~$ jack.udp recv AUTHOR ------ Rohan Drape SEE ALSO -------- jackd(1) jack-tools-20101210.orig/jack.dl.c0000644000175000017500000001220411536646636015446 0ustar jonasjonas/***** jack.dl.c - (c) rohan drape, 2003-2008 *****/ #include #include #include #include #include #include #include #include #include #include #include "common/jack-port.h" #include "jack.dl.h" void fail(char *s) { fprintf(stderr, s); exit(EXIT_FAILURE); } int dsp_run(jack_nframes_t nf, void *ptr) { struct world *w = (struct world *)ptr; for(int i = 0; i < w->nc; i++) { w->in[i] = (float *)jack_port_get_buffer(w->ip[i], nf); } for(int i = 0; i < w->nc; i++) { w->out[i] = (float *)jack_port_get_buffer(w->op[i], nf); memset(w->out[i], 0, nf * sizeof(float)); } for(int i = 0; i < w->ng; i++) { if(w->ga[i]) { w->dsp_step[i](w, i, w->st[i], nf); } } return 0; } void osc_error(int n, const char *m, const char *p) { fprintf(stderr,"jack.dl: error %d in path %s: %s\n", n, p, m); } #define break_on(x,s) \ if(x){ \ fprintf(stderr,"jack.dl: %s: %s, %d\n", s, __FILE__, __LINE__); \ return 0; \ } int osc_g_load(const char *p, const char *t, lo_arg **a, int n, void *d, void *u) { struct world *w = (struct world *)u; int g = a[0]->i; break_on(g >= w->ng, "graph index"); w->ga[g] = false; char *s = &a[1]->s; if(w->gh[g]) break_on(dlclose(w->gh[g]), dlerror()); w->gh[g] = dlopen(s, RTLD_LAZY); break_on(!w->gh[g], dlerror()); w->dsp_init[g] = dlsym(w->gh[g], "dsp_init"); w->dsp_step[g] = dlsym(w->gh[g], "dsp_step"); w->st[g] = w->dsp_init[g](w, g); w->ga[g] = true; fprintf(stderr,"g_load: %d, %s\n", g, s); return 0; } int osc_g_unload(const char *p, const char *t, lo_arg **a, int n, void *d, void *u) { struct world *w = (struct world *)u; int g = a[0]->i; break_on(g >= w->ng, "graph index"); w->ga[g] = false; if(w->gh[g]) break_on(dlclose(w->gh[g]), dlerror()); w->gh[g] = NULL; if(w->st[g]) free(w->st[g]); fprintf(stderr,"g_unload: %d\n", g); return 0; } int osc_c_set1(const char *p, const char *t, lo_arg **a, int n, void *d, void *u) { struct world *w = (struct world *)u; int i = a[0]->i; break_on(i >= w->nk, "control index"); w_c_set1(w, i, a[1]->f); fprintf(stderr,"c_set1: %d, %f\n", i, a[1]->f); return 0; } int osc_b_alloc(const char *p, const char *t, lo_arg **a, int n, void *d, void *u) { struct world *w = (struct world *)u; int i = a[0]->i; break_on(i >= w->nb, "buffer index"); /*if(w->bd[i]) free(w->bd[i]);*/ int l = a[1]->i; w->bl[i] = 0; w->bd[i] = calloc(l, sizeof(float)); w->bl[i] = l; fprintf(stderr,"b_alloc: %d, %d\n", i, l); return 0; } int osc_p_set1(const char *p, const char *t, lo_arg **a, int n, void *d, void *u) { struct world *w = (struct world *)u; int g = a[0]->i; break_on(g >= w->ng, "graph index"); int i = a[1]->i; break_on(i >= w->nk, "control index"); w_p_set1(w, g, i, a[2]->f); fprintf(stderr,"p_set1: %d, %d, %f\n", g, i, a[2]->f); return 0; } int osc_quit(const char *p, const char *t, lo_arg **a, int n, void *d, void *u) { struct world *w = (struct world *)u; w->ef = true; return 0; } void world_init(struct world *w, int ng, int nc, int nk, int nb) { w->ng = ng; w->nc = nc; w->nk = nk; w->nb = nb; w->dsp_init = calloc(w->ng, sizeof(void *)); w->dsp_step = calloc(w->ng, sizeof(void *)); w->st = calloc(w->ng, sizeof(void *)); w->p_ctl = malloc(w->ng * sizeof(float *)); for(int i = 0; i < w->ng; i++) { w->p_ctl[i] = calloc(w->nk, sizeof(float)); } w->ga = calloc(w->ng, sizeof(bool)); w->gh = calloc(w->ng, sizeof(void *)); w->ip = malloc(w->nc * sizeof(jack_port_t *)); w->op = malloc(w->nc * sizeof(jack_port_t *)); w->in = malloc(w->nc * sizeof(float *)); w->out = malloc(w->nc * sizeof(float *)); w->ctl = calloc(w->nk, sizeof(float)); w->bl = calloc(w->nb, sizeof(int)); w->bd = calloc(w->ng, sizeof(float*)); w->ef = false; w->c = jack_client_open("jack.dl",JackNullOption,NULL); if(!w->c) fail("could not create jack client\n"); jack_set_process_callback(w->c, dsp_run, w); w->sr = (float)jack_get_sample_rate(w->c); jack_port_make_standard(w->c, w->ip, w->nc, false); jack_port_make_standard(w->c, w->op, w->nc, true); } int main(int argc, char **argv) { struct world w; lo_server_thread osc; world_init(&w, 8, 8, 64, 8); osc = lo_server_thread_new("57190", osc_error); lo_server_thread_add_method(osc, "/c_set1", "if", osc_c_set1, &w); lo_server_thread_add_method(osc, "/p_set1", "iif", osc_p_set1, &w); lo_server_thread_add_method(osc, "/g_load", "is", osc_g_load, &w); lo_server_thread_add_method(osc, "/g_unload", "i", osc_g_unload, &w); lo_server_thread_add_method(osc, "/b_alloc", "ii", osc_b_alloc, &w); lo_server_thread_add_method(osc, "/quit", NULL, osc_quit, &w); lo_server_thread_start(osc); if(jack_activate(w.c)) fail("jack.dl: jack_activate() failed\n"); while(!w.ef) { struct timespec t = {0, 100000000}; nanosleep(&t, NULL); } jack_client_close(w.c); lo_server_thread_free(osc); return EXIT_SUCCESS; } jack-tools-20101210.orig/jack.plumbing.c0000644000175000017500000004156011536646636016673 0ustar jonasjonas/***** jack.plumbing.c - (c) rohan drape, 2003-2010 *****/ #include #include #include #include #include #include #include #include #include #include #include #include #include "common/file.h" #include "common/jack-client.h" #include "common/jack-port.h" #include "common/print.h" #include "common/xregcomp.h" #include "common/time-timespec.h" #define MAX_SETS 8 #define MAX_RULES 512 #define MAX_STR 512 #define MAX_SUBEXP 4 #define DEFAULT_DELAY 30000 #define SYS_RULESET "/etc/jack.plumbing" enum action { ignore, disconnect, connect, connect_exclusive, also_connect, }; struct rule { enum action command; char left[MAX_STR]; regex_t left_c; char right[MAX_STR]; }; struct plumber { struct rule r[MAX_RULES]; /* The rule set. */ int n; /* Number of rules. */ char i[MAX_SETS][MAX_STR]; /* Rule set filenames. */ int g; /* Number of rule set files. */ jack_client_t *j; /* JACK client. */ pthread_t t; /* Plumbing thread. */ pthread_mutex_t lock; pthread_cond_t cond; int w; /* Do not send wakeup unless TRUE. */ time_t m; /* Time that the rule set was last modified. */ unsigned long u; /* Number of usecs to defer for connections. */ int d; /* Run as daeomon. */ int o; /* Include ordinary rule files. */ int q; /* Quiet operation. */ }; /* Send message to stderr. */ static void inform(struct plumber *p, char *s, ...) { if(p->q) { return; } va_list ap; va_start(ap, s); vfprintf(stderr, s, ap); va_end(ap); eprintf("\n"); } /* Parse a plumbing command name. */ static enum action parse_command(const char *s) { if(strcmp(s, "connect") == 0) { return connect; } else if(strcmp(s, "connect-exclusive") == 0) { return connect_exclusive; } else if(strcmp(s, "disconnect") == 0) { return disconnect; } if(strcmp(s, "also-connect") == 0) { return also_connect; } else { return ignore; } } /* Return TRUE iff the LHS of `c' is pre-compiled. */ static bool precompile_rule_p(enum action c) { return c == disconnect || c == connect || c == connect_exclusive; } /* Add a rule to the rule set. If required pre-compiled LHS. */ static void add_rule_to_set(struct plumber *p, enum action command, const char *left, const char *right) { inform(p, "Add rule: '%d', '%s' - '%s'.", command, left, right); p->r[p->n].command = command; snprintf(p->r[p->n].left, MAX_STR, "^%s$", left); if(precompile_rule_p(p->r[p->n].command)) { xregcomp(&(p->r[p->n].left_c), p->r[p->n].left, REG_EXTENDED); } snprintf(p->r[p->n].right, MAX_STR, "^%s$", right); p->n += 1; } /* Clear all rules. If required free pre-compiled LHS. */ static void clear_rule_set(struct plumber *p) { int i; for(i = 0; i < p->n; i++) { if(precompile_rule_p(p->r[i].command)) { regfree(&(p->r[i].left_c)); } } p->n = 0; } /* Parse the rule at `s' to `p'. This is a pretend parser... */ static void acquire_rule_string(struct plumber *p, const char *s) { if(s[0] == ';' || s[0] == '\0') { return; } if(p->n >= MAX_RULES) { inform(p, "Rule lost, too many rules: '%s'.", s); return; } char s_command[MAX_STR], s_left[MAX_STR], s_right[MAX_STR]; int err = sscanf(s, "(%s \"%[^\"]\" \"%[^\"]\")", s_command, s_left, s_right); if(err != 3) { inform(p, "Rule lost, scan failed: '%s'.", s); return; } inform(p, "Rule accepted: '%s', '%s' - '%s'.", s_command, s_left, s_right); add_rule_to_set(p, parse_command(s_command), s_left, s_right); } /* Read in the rules from `f'. */ static void acquire_rule_file(struct plumber *p, const char *f) { FILE *fp = fopen(f, "r"); if(!fp) { inform(p, "Rule file inaccessible: '%s'.", f); return; } char s[MAX_STR]; while(fgets(s, MAX_STR, fp)) { s[strlen(s)-1] = '\0'; acquire_rule_string(p, s); } fclose(fp); return; } /* Append `f' to the list of known rule files. */ static void append_rule_file(struct plumber *p, char *f, ...) { if(p->g >= MAX_SETS) { inform(p, "Rule file discarded, too many rule files: `%s', %d", f, p->g); return; } va_list ap; va_start(ap, f); vsnprintf(p->i[p->g], MAX_STR, f, ap); va_end(ap); inform(p, "Append rule file: '%s'", p->i[p->g]); p->g += 1; p->m = 0; } /* Load the `n' rule files at `f'. */ static void append_rule_file_list(struct plumber *p, char **f, int n) { int i; for(i = 0; i < n; i++) { append_rule_file(p, f[i]); } } /* Load the system wide and user specific rule files. */ static void append_ordinary_rule_files(struct plumber *p) { append_rule_file(p, SYS_RULESET); append_rule_file(p, "%s/.jack.plumbing", getenv("HOME")); } /* Add implicit connect rules at `p'. */ static void process_also_connect_rules(struct plumber *p) { int i; for(i = 0; i < p->n; i++) { if(p->r[i].command == also_connect) { struct rule a = p->r[i]; int j; for(j = 0; j < p->n; j++) { if(p->r[j].command == connect) { struct rule c = p->r[j]; if(strcmp(a.left, c.right) == 0) { add_rule_to_set(p, connect, c.left, a.right); } if(strcmp(a.left, c.left) == 0) { add_rule_to_set(p, connect, a.right, c.right); } } } } } } static void post_process_rule_set(struct plumber *p) { process_also_connect_rules(p); } /* Returns TRUE iff the rule file `f' is modified after `m'. */ static bool rule_file_is_modified_p(struct plumber *p, const char *f, time_t m) { if(!file_exists_p(f)) { inform(p, "Rule file does not exist: '%s'.", f); return false; } time_t mtime = stat_mtime(f); if(mtime <= m) { dprintf("Rule file not modified: '%s'.", f); return false; } return true; } /* Returns TRUE if any of the rule files at `p' are modified. */ static bool any_rule_file_modified_p(struct plumber *p) { int i; for(i = 0; i < p->g; i++) { if(rule_file_is_modified_p(p, p->i[i], p->m)) { return true; } } return false; } /* Consult all rule files. If any is modified clear the rule set and re-read all files. */ static void acquire_rule_set(struct plumber *p) { if(!any_rule_file_modified_p(p)) { return; } clear_rule_set(p); int i; for(i = 0; i < p->g; i++) { acquire_rule_file(p, p->i[i]); } post_process_rule_set(p); p->m = time(NULL); } /* If the LHS matches return TRUE and write subexp. */ static bool left_applies_p(regex_t *l, const char *p_l, regmatch_t *subexp) { return regexec(l, p_l, MAX_SUBEXP, subexp, 0) == 0; } /* Make the right hand side (rhs) regular expression by replacing the escape sequence '\1' at `right' with the submatch at `left' indicated by `a' and `b'. */ static void make_rhs(const char *left, int a, int b, const char *right, char *rhs) { char *replace_p = strchr(right, '\\'); if(!replace_p) { strcpy (rhs, right); return; } int copy_n = replace_p - right; int after_n = strlen(right)- copy_n - 2; int insert_n =(b - a); memcpy(rhs, right, copy_n); memcpy(rhs + copy_n, left + a, insert_n); memcpy(rhs + copy_n + insert_n, right + copy_n + 2, after_n); rhs[ copy_n + insert_n + after_n ] = '\0'; } /* If the RHS matches return TRUE. */ static bool right_applies_p(const char *p_l, const char *r, const char *p_r, regmatch_t *subexp) { char rhs[MAX_STR]; if(subexp[1].rm_so >= 0) { make_rhs(p_l, subexp[1].rm_so, subexp[1].rm_eo, r, rhs); } else { strcpy(rhs, r); } regex_t rr; xregcomp(&rr, rhs, REG_NOSUB | REG_EXTENDED); int err = regexec(&rr, p_r, 0, NULL, 0); regfree(&rr); return err == 0; } /* The traversal macros bind the values `left' and `right' over `body'. TRAVERSE_CONNECTIONS binds for every existing connection that matches the rule, TRAVERSE_LISTS binds for all possible connections that match the rule. */ #define TRAVERSE_CONNECTIONS(p,r,p_left,body) \ int i; \ regmatch_t subexp[MAX_SUBEXP]; \ for(i = 0; p_left[i]; i++) { \ if(left_applies_p(&(r->left_c), p_left[i], subexp)) { \ jack_port_t *port = jack_port_by_name(p->j, p_left[i]); \ const char **c = jack_port_get_all_connections(p->j, port); \ if(c) { \ int j; \ for(j = 0; c[j]; j++) { \ if(right_applies_p(p_left[i], r->right, \ c[j], subexp)) { \ const char *left = p_left[i]; \ const char *right = c[j]; \ body; \ } \ } \ free(c); \ } \ } \ } #define TRAVERSE_LISTS(r,p_left,p_right,body) \ int i; \ regmatch_t subexp[MAX_SUBEXP]; \ for(i = 0; p_left[i]; i++) { \ if(left_applies_p(&(r->left_c), p_left[i], subexp)) { \ int j; \ for(j = 0; p_right[j]; j++) { \ if(right_applies_p(p_left[i], r->right, \ p_right[j], subexp)) { \ const char *left = p_left[i]; \ const char *right = p_right[j]; \ body; \ } \ } \ } \ } static void apply_disconnect_rule(struct plumber *p, struct rule *r, const char **p_left, const char **p_right) { TRAVERSE_CONNECTIONS(p, r, p_left, inform(p, "Disconnect: '%s' -> '%s'.", left, right); jack_port_disconnect_named(p->j, left, right)); } static void apply_connect_rule(struct plumber *p, struct rule *r, const char **p_left, const char **p_right) { TRAVERSE_LISTS(r, p_left, p_right, if(!jack_port_is_connected_p(p->j, left, right)) { inform(p, "Connect: '%s' -> '%s'.", left, right); jack_port_connect_named(p->j, left, right); }); } static void apply_connect_exclusive_rule(struct plumber *p, struct rule *r, const char **p_left, const char **p_right) { TRAVERSE_LISTS(r, p_left, p_right, jack_port_clear_all_connections(p->j, left); jack_port_clear_all_connections(p->j, right); inform(p, "Connect-exclusive: '%s' -> '%s'.", left, right); jack_port_connect_named(p->j, left, right);); } #define TRAVERSE_RULE_SET(p,class) \ for(i = 0; i < p->n; i++) { \ if(p->r[i].command == class) { \ apply_##class##_rule(p, &(p->r[i]), p_left, p_right); \ } \ } /* Run the set of plumbing rules. */ static void apply_rule_set(struct plumber *p) { acquire_rule_set(p); const char **p_left, **p_right; p_left = jack_get_ports(p->j, NULL, NULL, JackPortIsOutput); p_right = jack_get_ports(p->j, NULL, NULL, JackPortIsInput); if(p_left && p_right) { int i; TRAVERSE_RULE_SET(p, disconnect); TRAVERSE_RULE_SET(p, connect); TRAVERSE_RULE_SET(p, connect_exclusive); } if(p_left) { free(p_left); } if(p_right) { free(p_right); } } /* Port notifications tend to arrive in sets, when one is signaled the plumber enters a sleep loop only continuing when the notifications stop arriving. The `w' field is -1 when not in a set, >1 when requests are arriving and zero when a set is ended. */ static void wait_on_connection_set(struct plumber *p) { eprintf("sem_waiting %d\n",p->w); pthread_cond_wait(&p->cond, &p->lock); eprintf("wake w %d\n",p->w); while(p->w > 0) { struct timespec t; t = usec_to_timespec(p-> u); p->w = 0; nanosleep(&t, NULL); eprintf("sleeping %d\n",p->w); } eprintf ("out of while loop\n"); } static void * plumbing_daemon(void *PTR) { struct plumber *p = (struct plumber*) PTR; pthread_mutex_lock (&p->lock); while(1) { wait_on_connection_set(p); apply_rule_set(p); p->w = -1; } pthread_mutex_unlock(&p->lock); return NULL; } #define SEND_WAKEUP \ if(p->w < 0) { \ pthread_mutex_lock(&p->lock); \ pthread_cond_signal(&p->cond); \ eprintf("sem_posted\n"); \ p->w = 1; \ pthread_mutex_unlock(&p->lock); \ } \ p->w += 1; static void on_registration(jack_port_id_t a, int b, void *PTR) { struct plumber *p = (struct plumber*) PTR; eprintf("%s: notification received\n", __func__); SEND_WAKEUP; } static int on_reorder(void *PTR) { struct plumber *p = (struct plumber*) PTR; eprintf("%s: notification received\n", __func__); SEND_WAKEUP; return 0; } static void init_plumber_defaults(struct plumber *p) { p->g = 0; p->n = 0; p->w = -1; p->m = 0; p->u = DEFAULT_DELAY; p->d = 1; p->o = 1; p->q = 0; pthread_mutex_init(&p->lock, NULL); pthread_cond_init(&p->cond, NULL); } static void init_plumber_connection(struct plumber *p) { p->j = jack_client_unique("jack.plumbing"); } static void finalize_plumber(struct plumber *p) { jack_client_close(p->j); pthread_cond_destroy(&p->cond); pthread_mutex_destroy(&p->lock); } #ifdef HAVE_SYS_INOTIFY_H #include #define INOTIFY_BUFLEN (5*(100 + sizeof(struct inotify_event))) static void watch_inotify(struct plumber *p) { int fd = inotify_init(); if(fd < 0) { perror("inotify_init"); exit(1); } char buf[INOTIFY_BUFLEN]; while(1) { int i; for(i=0; ig; i++) { if(inotify_add_watch(fd, p->i[i], IN_MODIFY) < 0) { eprintf("Cannot watch '%s': %s\n", p->i[i], strerror(errno)); } } eprintf("inotify read\n"); int len = read(fd, buf, INOTIFY_BUFLEN); if(len < 0 && EINTR) { continue; } if(len < 0) { perror("reading from inotify fd"); } eprintf("inotify notification received\n"); SEND_WAKEUP } } #else static void watch_inotify(struct plumber *p) { } #endif static void as_daemon(struct plumber *p) { pthread_create(&(p->t), NULL, plumbing_daemon, p); jack_set_port_registration_callback(p->j, on_registration, p); jack_set_graph_order_callback(p->j, on_reorder, p); jack_client_activate( p->j); watch_inotify(p); pthread_join(p->t, NULL); } static void plumber_usage(void) { eprintf("Usage: jack.plumbing [ options ] [ rule-files ]\n"); eprintf(" -d : Do not start as daemon.\n"); eprintf(" -o : Do not acquire ordinary rule files.\n"); eprintf(" -q : Quiet operation.\n"); eprintf(" -u N : Micro-seconds to defer at connection (default=%d).\n", DEFAULT_DELAY); exit(1); } static void parse_arguments(struct plumber *p, char **argv, int argc) { int c; while(( c = getopt(argc, argv, "dhoqu:")) != -1) { switch(c) { case 'd': p->d = 0; break; case 'h': plumber_usage (); break; case 'o': p->o = 0; break; case 'q': p->q = 1; break; case 'u': p->u = strtoul(optarg, NULL, 0); break; default: plumber_usage (); break; } } append_rule_file_list(p, argv + optind, argc - optind); } static void start_plumber(struct plumber *p, char **argv, int argc) { init_plumber_defaults(p); parse_arguments(p, argv, argc); init_plumber_connection(p); if(p->o) { append_ordinary_rule_files(p); } if(p->d) { as_daemon(p); } else { apply_rule_set(p); } finalize_plumber(p); } int main(int argc, char *argv[]) { struct plumber p; start_plumber(&p, argv, argc); return 0; } jack-tools-20101210.orig/jack.transport.text0000644000175000017500000000153111536646636017646 0ustar jonasjonasJACK.TRANSPORT(1) ================= Rohan Drape NAME ---- jack.transport - Minimalist Jack Transport Interface SYNOPSIS -------- jack.transport DESCRIPTION ----------- jack.transport is a minimalist Jack transport control interface using ncurses. It displays the transport state and current time, and pro- vides standard operating keys. COMMANDS -------- *s* : Start and stop transport. Aliased to [space]. *l* : Locate to entered time. Starting to type a number will also enter locate mode. *i* : Set skip increment to entered interval. *z* : Locate to start (zero). *r* : Erase and refresh screen. *>* : Skip forwards. Aliased to . and [right-arrow]. *<* : Skip backwards. Aliased to , and [left-arrow]. AUTHOR ------ Rohan Drape SEE ALSO -------- jackd(1), jack.play(1) jack-tools-20101210.orig/jack.osc.c0000644000175000017500000002374711536646636015651 0ustar jonasjonas/***** jack.osc.c - (c) rohan drape, 2004-2006 *****/ #include #include #include #include #include #include #include #include #include "common/byte-order.h" #include "common/client.h" #include "common/failure.h" #include "common/jack-client.h" #include "common/jack-port.h" #include "common/memory.h" #include "common/network.h" #include "common/observe-signal.h" #include "common/osc.h" #include "common/print.h" #include "common/time-current.h" #include "common/time-ntp.h" #include "common/time-timeval.h" #define REQUEST_TICK 0x00000001 #define REQUEST_PULSE 0x00000002 #define REQUEST_CORRECTION 0x00000004 #define REQUEST_TRANSPORT 0x00000008 #define REQUEST_ALL 0xFFFFFFFF struct jackosc { f64 fps; /* Frames per second (ie. sample rate) */ f64 spf; /* Seconds per frame */ f64 ppc; /* Pulses per cycle */ f64 pt; /* Pulse type */ f64 ppm; /* Pulses per minute */ f64 ppf; /* Pulses per frame */ f64 tpf; /* Ticks per frame */ f64 pulse; /* Pulse clock */ i64 frm; /* Frame clock (jack.osc) */ i64 j_frm; /* Frame clock (jackd) */ u64 ntp; /* NTP clock */ f64 utc; /* UTC clock */ i8 roll; i32 correct_interval; i32 correct_n; i8 fps_alt; jack_client_t *client; int fd; client_register_t *cr; pthread_t osc_thread; }; #define COMMON_SETUP(n) \ u8 packet[256]; \ osc_data_t o[n]; \ o[0].t = ntp; \ o[1].d = utc; \ o[2].h = frm; #define COMMON_SEND(addr,dsc,incl) \ int packet_sz; \ packet_sz = osc_construct_message(addr, dsc, o, packet, 256); \ sendto_client_register(d->fd, d->cr, packet, packet_sz, incl); void send_jck_drift(struct jackosc *d, u64 ntp, f64 utc, i64 frm, i64 ntp_dif, f64 utc_dif) { COMMON_SETUP(5); o[3].h = ntp_dif; o[4].d = utc_dif; COMMON_SEND("/drift", ",tdhhd", REQUEST_CORRECTION); } void send_jck_tick(struct jackosc *d, u64 ntp, f64 utc, i64 frm, i64 frame, f64 pulse) { COMMON_SETUP(5); o[3].h = frame; o[4].d = pulse; COMMON_SEND("/tick", ",tdhhd", REQUEST_TICK); } void send_jck_current(int fd, struct sockaddr_in address, u64 ntp, f64 utc, i64 frm, i64 frame, f64 pulse) { COMMON_SETUP(5); o[3].h = frame; o[4].d = pulse; int packet_sz; packet_sz = osc_construct_message("/current.reply", ",tdhhd", o, packet, 256); if(packet_sz) { sendto_exactly(fd, packet, packet_sz, address); } } void send_jck_pulse(struct jackosc *d, u64 ntp, f64 utc, i64 frm, u64 p_ntp, f64 p_utc, i64 p_frm, i32 pulse) { COMMON_SETUP(7); o[3].t = p_ntp; o[4].d = p_utc; o[5].h = p_frm; o[6].i = pulse; COMMON_SEND("/pulse", ",tdhtdhi", REQUEST_PULSE); } void send_jck_transport(struct jackosc *d, u64 ntp, f64 utc, i64 frm, f64 fps, f64 ppm, f64 ppc, f64 pt, i32 rolling) { COMMON_SETUP(8); o[3].d = fps; o[4].d = ppm; o[5].d = ppc; o[6].d = pt; o[7].i = rolling; COMMON_SEND("/transport", ",tdhddddi", REQUEST_TRANSPORT); } void send_jck_status(int fd, struct sockaddr_in address, f64 fps, f64 ppm, f64 ppc, f64 pt, i32 rolling) { u8 packet[256]; osc_data_t o[5]; int packet_sz; o[0].d = fps; o[1].d = ppm; o[2].d = ppc; o[3].d = pt; o[4].i = rolling; packet_sz = osc_construct_message("/status.reply", ",ddddi", o, packet, 256); if(packet_sz) { sendto_exactly(fd, packet, packet_sz, address); } } #define OSC_PARSE_MSG(command,types) \ osc_parse_message(command, types, packet, packet_sz, o) void *jackosc_osc_thread_procedure(void *PTR) { struct jackosc *d = (struct jackosc *) PTR; while(!observe_end_of_process()) { if(fd_wait(d->fd, 500000)) { struct sockaddr_in addr; socklen_t addr_len = sizeof(addr); const int packet_extent = 64; u8 packet[packet_extent]; i32 packet_sz = xrecvfrom(d->fd, packet, 64, 0, (struct sockaddr *)&addr, &addr_len); osc_data_t o[4]; if(OSC_PARSE_MSG("/receive", ",i")) { edit_client_register(d->cr, addr, o[0].i); } else if(OSC_PARSE_MSG("/receive_at", ",iis")) { struct sockaddr_in ra_addr; init_sockaddr_in(&ra_addr, o[2].s, (i16)o[1].i); edit_client_register(d->cr, ra_addr, o[0].i); } else if(OSC_PARSE_MSG("/status", ",")) { send_jck_status(d->fd, addr, d->fps, d->ppm, d->ppc, d->pt, d->roll); } else if(OSC_PARSE_MSG("/current", ",")) { send_jck_current(d->fd, addr, d->ntp, d->utc, d->frm, d->j_frm, d->pulse); } else if(OSC_PARSE_MSG("/start", ",")) { jack_transport_start(d->client); } else if(OSC_PARSE_MSG("/stop", ",")) { jack_transport_stop(d->client); } else if(OSC_PARSE_MSG("/locate", ",f")) { jack_transport_locate(d->client, o[0].f * d->fps); } else if(OSC_PARSE_MSG("/connect", ",ss")) { jack_port_connect_named(d->client, o[0].s, o[1].s); } else if(OSC_PARSE_MSG("/disconnect", ",ss")) { jack_port_disconnect_named(d->client, o[0].s, o[1].s); } else { eprintf("%s: dropped packet: %8s\n", __func__, packet); } } } return NULL; } inline f64 get_ticks_per_frame(f64 ticks_per_pulse, f64 pulses_per_minute, f64 frames_per_second) { f64 pulses_per_second = pulses_per_minute / 60.0; f64 ticks_per_second = ticks_per_pulse * pulses_per_second; return ticks_per_second / frames_per_second; } inline f64 get_pulses_per_frame(f64 pulses_per_minute, f64 frames_per_second) { f64 pulses_per_second = pulses_per_minute / 60.0; return pulses_per_second / frames_per_second; } int jackosc_process(jack_nframes_t nframes, void *PTR) { struct jackosc *d =(struct jackosc *) PTR; if(d->correct_n >= d->correct_interval) { struct timeval t = current_time_as_utc_timeval(); u64 c_ntp = utc_timeval_to_ntp(t); f64 c_utc = timeval_to_real(t); i64 c_ntp_dif = c_ntp - d->ntp; f64 c_utc_dif = c_utc - d->utc; send_jck_drift(d, d->ntp, d->utc, d->frm, c_ntp_dif, c_utc_dif); d->ntp = c_ntp; d->utc = c_utc; d->correct_n = 0; } jack_position_t p; jack_transport_state_t s = jack_transport_query(d->client, &p); if(( s & JackTransportRolling)!= d->roll) { d->roll = s & JackTransportRolling; send_jck_transport(d, d->ntp, d->utc, d->frm, d->fps, d->ppm, d->ppc, d->pt, d->roll); } if(d->fps_alt) { d->ppf = get_pulses_per_frame(d->ppm, d->fps); d->tpf = get_ticks_per_frame(p.ticks_per_beat, d->ppm, d->fps); send_jck_transport(d, d->ntp, d->utc, d->frm, d->fps, d->ppm, d->ppc, d->pt, d->roll); d->fps_alt = 0; } if(( p.valid & JackPositionBBT)) { if(d->ppm != p.beats_per_minute) { d->ppm = p.beats_per_minute; d->ppf = get_pulses_per_frame(d->ppm, d->fps); d->tpf = get_ticks_per_frame(p.ticks_per_beat, d->ppm, d->fps); send_jck_transport(d, d->ntp, d->utc, d->frm, d->fps, d->ppm, d->ppc, d->pt, d->roll); } if(d->ppc != p.beats_per_bar || d->pt != p.beat_type) { d->ppc = p.beats_per_bar; d->pt = p.beat_type; send_jck_transport(d, d->ntp, d->utc, d->frm, d->fps, d->ppm, d->ppc, d->pt, d->roll); } if(d->roll && (p.tick == 0 || ((f64)p.tick +(floorf((f64)nframes * d->tpf)))> (f64)p.ticks_per_beat)) { i32 p_tick_off =(p.tick == 0)? 0 : p.ticks_per_beat - p.tick; f64 p_frm_off = (f64)p_tick_off * d->tpf; f64 p_frm = (f64)d->frm + p_frm_off; f64 p_utc = d->utc +(p_frm_off * d->spf); u64 p_ntp = utc_real_to_ntp(p_utc); i32 p_pulse =(p.tick == 0)? p.beat : p.beat + 1; if((f64)p_pulse > d->ppc) { p_pulse = 1; } send_jck_pulse(d, d->ntp, d->utc, d->frm, p_ntp, p_utc, (i64)floor(p_frm), p_pulse); /* Correct pulse accumulator. */ d->pulse = (f64)p_pulse -(ceil(p_frm_off)* d->ppf); if(d->pulse < 1.0) { d->pulse += d->ppc; } } /* jck_tk is sent after jck_pl to report the corrected pulse. */ send_jck_tick(d, d->ntp, d->utc, d->frm, (i64)p.frame, d->pulse); } d->frm += nframes; d->j_frm = (i64)p.frame; d->utc += (f64)nframes * d->spf; d->ntp = utc_real_to_ntp(d->utc); d->pulse += (f64)nframes * d->ppf; if(d->pulse > d->ppc + 1.0) { d->pulse -= d->ppc; } d->correct_n += 1; return 0; } int jackosc_fps_handler(jack_nframes_t fps, void *PTR) { struct jackosc *d =(struct jackosc *) PTR; d->fps = (f64) fps; d->fps_alt = 1; return 0; } void jackosc_usage(void) { eprintf("Usage: jack.osc [ options ]\n"); eprintf(" -c Drift correction interval in periods (default=64).\n"); eprintf(" -p Port number (default=57130).\n"); FAILURE; } int main(int argc, char *argv[]) { observe_signals(); struct jackosc d; d.ppc = 0.0; d.pt = 0.0; d.ppm = 0.0; d.ppf = 0.0; d.tpf = 0.0; d.pulse = 0.0; d.frm = 0; d.ntp = 0; d.utc = 0.0; d.roll = 0; /* Ensure that a correction occurs when the process starts. */ d.correct_interval = 64; d.correct_n = d.correct_interval; d.cr = alloc_client_register(16); int port_n = 57130; int c; while(( c = getopt(argc, argv, "c:hp:")) != -1) { switch(c) { case 'c': d.correct_interval = atoi(optarg); d.correct_n = d.correct_interval; break; case 'h': jackosc_usage(); break; case 'p': port_n = atoi(optarg); break; default: eprintf("%s: Illegal option %c.\n", __func__, c); jackosc_usage(); break; } } d.fd = socket_udp(0); bind_inet(d.fd, NULL, port_n); d.client = jack_client_unique("jack.osc"); jack_set_error_function(jack_client_minimal_error_handler); jack_set_sample_rate_callback(d.client, jackosc_fps_handler, &d); jack_on_shutdown(d.client, jack_client_minimal_shutdown_handler, 0); jack_set_process_callback(d.client, jackosc_process, &d); d.fps = jack_get_sample_rate(d.client); d.fps_alt = 0; d.spf = 1.0 / d.fps; jack_client_activate(d.client); pthread_create(&(d.osc_thread), NULL, jackosc_osc_thread_procedure, &d); pthread_join(d.osc_thread, NULL); jack_client_close(d.client); free_client_register(d.cr); exit(0); return 0; } jack-tools-20101210.orig/jack.dl.h0000644000175000017500000000276511536646636015466 0ustar jonasjonas#include #include struct world { void* (**dsp_init)(struct world *, int); void (**dsp_step)(struct world *, int, void *, int); void **st; /* graph state */ bool *ga; /* graph active */ void **gh; /* graph shared library handle */ jack_client_t *c; /* client */ jack_port_t **ip; /* input ports */ jack_port_t **op; /* output ports */ int nc; /* number of channels */ int ng; /* number of graphs */ int nk; /* number of controls */ int nb; /* number of buffers */ float sr; /* sample rate */ float **in; /* input data */ float **out; /* output data */ float *ctl; /* shared control data */ float **bd; /* buffer data */ int *bl; /* buffer sizes */ float **p_ctl; /* private control data */ bool ef; /* exit flag */ }; #define w_sr(w) (w)->sr #define w_c_get1(w,i) (w)->ctl[(i)] #define w_c_set1(w,i,n) (w)->ctl[(i)]=(n) #define w_p_get1(w,g,i) (w)->p_ctl[(g)][(i)] #define w_p_set1(w,g,i,n) (w)->p_ctl[(g)][(i)]=(n) #define w_out1(w,i,n) (w)->out[0][(i)]+=(n) #define w_out2(w,i,n1,n2) {(w)->out[0][(i)]+=(n1);(w)->out[1][(i)]+=(n2);} #define w_b_read1(w,b,i) (w)->bd[(b)][(i)] #define w_b_write1(w,b,i,n) (w)->bd[(b)][(i)]=(n) jack-tools-20101210.orig/configure.ac0000644000175000017500000000234711536646636016271 0ustar jonasjonas# configure.ac -*-autoconf-*- # Initialize autoconf and autmake AC_INIT(jack.*,0.5) AC_CONFIG_AUX_DIR(config) AC_CANONICAL_SYSTEM AM_INIT_AUTOMAKE PKG_PROG_PKG_CONFIG # Check for programs. These macros set and export variables that are # used in the make process. AC_PROG_CC AC_PROG_CPP AC_PROG_INSTALL AC_PROG_LN_S AC_PROG_MAKE_SET AC_PROG_AWK AC_PROG_LD AM_PROG_LIBTOOL # Require JACK library. PKG_CHECK_MODULES(JACK, jack, , AC_MSG_ERROR("jack required")) # Require sndfile library. PKG_CHECK_MODULES(SNDFILE, sndfile, , AC_MSG_ERROR("libsndfile required")) # Require samplerate library. PKG_CHECK_MODULES(SRC, samplerate, , AC_MSG_ERROR("libssamplerate required")) # Require liblo library. PKG_CHECK_MODULES(LIBLO, liblo, , AC_MSG_ERROR("liblo required")) # Require X11 PKG_CHECK_MODULES(X11, x11, , AC_MSG_ERROR("x11 required")) PKG_CHECK_MODULES(XEXT, xext, , AC_MSG_ERROR("xext required")) PKG_CHECK_MODULES(Xt, xt, , AC_MSG_ERROR("xt required")) # Require inotify AC_CHECK_HEADERS(sys/inotify.h, AC_DEFINE(HAVE_INOTIFY, 1, inotify)) # Set compiler flags. AC_SUBST(AM_CFLAGS) AM_CFLAGS="-D_POSIX_C_SOURCE=200112 -std=c99 -O3 -funroll-loops -Wall" # Write Makefile. AC_OUTPUT(Makefile common/Makefile) jack-tools-20101210.orig/common/0000755000175000017500000000000011536646636015265 5ustar jonasjonasjack-tools-20101210.orig/common/jack-port.h0000644000175000017500000000114411536646636017330 0ustar jonasjonas#ifndef _COMMON_JACK_PORT_H #define _COMMON_JACK_PORT_H #include #include void jack_port_make_standard(jack_client_t *client, jack_port_t **ports, int n, bool output); int jack_port_connect_named(jack_client_t *client, const char *src, const char *dst); int jack_port_disconnect_named(jack_client_t *client, const char *src, const char *dst); int jack_port_is_connected_p(jack_client_t *j, const char *l, const char *r); void jack_port_clear_all_connections(jack_client_t *j, const char *l); void jack_port_connect_pattern(jack_client_t *client, int n, char *src, char *dst); #endif jack-tools-20101210.orig/common/jack-client.c0000644000175000017500000000210011536646636017606 0ustar jonasjonas/* jack-client.c - (c) rohan drape, 2005-2006 */ #include #include #include #include #include #include #include "failure.h" #include "jack-client.h" #include "print.h" void jack_client_minimal_error_handler(const char *desc) { eprintf("jack error: %s\n", desc); } void jack_client_minimal_shutdown_handler(void *arg) { eprintf("jack shutdown\n"); FAILURE; } jack_client_t *jack_client_unique_store(char *name) { int n = (int)getpid(); char uniq[64]; snprintf(uniq, 64, "%s-%d", name, n); strncpy(name,uniq,64); jack_client_t *client = jack_client_open(uniq,JackNullOption,NULL); if(! client) { eprintf("jack_client_open() failed: %s\n", uniq); FAILURE; } return client; } jack_client_t *jack_client_unique(const char *name) { char uniq[64]; strncpy(uniq,name,64); return jack_client_unique_store(uniq); } int jack_client_activate(jack_client_t *client) { int err = jack_activate(client); if(err) { eprintf("jack_activate() failed\n"); FAILURE; } return err; } jack-tools-20101210.orig/common/signal-copy.c0000644000175000017500000000046711536646636017665 0ustar jonasjonas/* signal-copy.c - (c) rohan drape, 2005-2006 */ #include #include #include "signal-copy.h" void signal_copy_circular ( float *dst , const float *src , int n , int s ) { memcpy ( dst , src + s , ( n - s ) * sizeof(float) ) ; memcpy ( dst + ( n - s ) , src , s * sizeof(float) ) ; } jack-tools-20101210.orig/common/float.h0000644000175000017500000000014111536646636016537 0ustar jonasjonas#ifndef _COMMON_FLOAT_H #define _COMMON_FLOAT_H typedef float f32; typedef double f64; #endif jack-tools-20101210.orig/common/signal-clip.h0000644000175000017500000000015011536646636017634 0ustar jonasjonas#ifndef _SIGNAL_CLIP #define _SIGNAL_CLIP void signal_clip(float *s, int n, float l, float r); #endif jack-tools-20101210.orig/common/observe-signal.c0000644000175000017500000000354611536646636020361 0ustar jonasjonas/* observe-signal.c - (c) rohan drape, 2005-2006 */ #define _XOPEN_SOURCE 600 /* To use SA_RESTART and SA_RESETHAND */ #include #include #include #include #include #include #include "observe-signal.h" volatile unsigned int signal_received = 0; static void signal_management_handler(int s) { signal_received |= 1 << s; } static void *signal_management_thread(void *PTR) { pthread_setcanceltype(PTHREAD_CANCEL_ASYNCHRONOUS, 0); sigset_t blocked; sigprocmask(SIG_SETMASK, 0, &blocked); int s; sigwait(&blocked, &s); if(s != SIGSEGV) { sigprocmask(SIG_UNBLOCK, &blocked, 0); } signal_management_handler(s); return NULL; } int observe_signals(void) { sigset_t signals; signal_received = 0; sigemptyset(&signals); sigaddset(&signals, SIGHUP); sigaddset(&signals, SIGINT); sigaddset(&signals, SIGQUIT); sigaddset(&signals, SIGPIPE); sigaddset(&signals, SIGTERM); struct sigaction action; action.sa_handler = signal_management_handler; action.sa_mask = signals; action.sa_flags = SA_RESTART | SA_RESETHAND; int i; for(i = 1; i < 32; i++) { if(sigismember(&signals, i)) { if(sigaction(i, &action, 0)) { fprintf(stderr, "sigaction() failed: %d\n", i); return -1; } } } if(pthread_sigmask(SIG_SETMASK, &signals, 0)) { fprintf(stderr, "pthread_sigmask() failed: %s\n", strerror(errno)); return -1; } pthread_t signal_thread_id; if(pthread_create(&signal_thread_id, 0, signal_management_thread, 0)) { fprintf(stderr, "pthread_create() failed\n"); return -1; } pthread_detach(signal_thread_id); return 0; } bool observe_end_of_process(void) { return(signal_received & 1< #include #include "failure.h" #include "memory.h" void *xmalloc(size_t size) { void *p = malloc(size); if(p == NULL) { fprintf(stderr, "malloc() failed: %ld\n", (long)size); FAILURE; } return p; } void *xcalloc(size_t count, size_t eltsize) { void *p = calloc(count, eltsize); if(p == NULL) { perror("calloc() failed"); FAILURE; } return p; } void *xrealloc(void *p, size_t size) { p = realloc(p, size); if(p == NULL) { perror("realloc() failed"); FAILURE; } return p; } float *fmalloc(size_t n) { float *d = xmalloc(n * sizeof(float)); size_t i; for(i = 0; i < n; i++) { d[i] = 0.0; } return d; } void fmemset(float *data, int n, float value) { int i; for(i = 0; i < n; i++) { data[i] = value; } } jack-tools-20101210.orig/common/signal-copy.h0000644000175000017500000000021411536646636017660 0ustar jonasjonas#ifndef _COMMON_SIGNAL_COPY_H #define _COMMON_SIGNAL_COPY_H void signal_copy_circular(float *dst, const float *src, int n, int s); #endif jack-tools-20101210.orig/common/signal-print.c0000644000175000017500000000046511536646636020045 0ustar jonasjonas/* signal-print.c - (c) rohan drape, 2005 */ #include #include "float.h" #include "signal-print.h" void signal_print(FILE *fp, const char *prefix, const f32 *f, int n) { int i; fprintf(fp, "%s", prefix); for(i = 0; i < n; i++) { fprintf(fp, "%2.1f ", f[i]); } fprintf(fp, "\n"); } jack-tools-20101210.orig/common/jack-port.c0000644000175000017500000000456011536646636017330 0ustar jonasjonas/* jack-port.c - (c) rohan drape, 2005-2010 */ #include #include #include #include #include #include #include "failure.h" #include "jack-port.h" #include "print.h" void jack_port_make_standard(jack_client_t *client, jack_port_t **ports, int n, bool output) { int i; for(i = 0; i < n; i++) { char name[64]; int direction = output ? JackPortIsOutput : JackPortIsInput; snprintf(name, 64, output ? "out_%d" : "in_%d", i + 1); ports[i] = jack_port_register(client, name, JACK_DEFAULT_AUDIO_TYPE, direction, 0); if(!ports[i]) { eprintf("jack_port_register() failed\n"); FAILURE; } } } int jack_port_connect_named(jack_client_t *client, const char *src, const char *dst) { int err = jack_connect(client, src, dst); if(err) { eprintf("jack_connect() failed: '%s' -> '%s'\n", src, dst); switch(err) { case EEXIST: eprintf("jack_connect() failed: connection exists\n"); break; default: eprintf("jack_connect() failed: unknown reason\n"); /* FAILURE; */ break; } } return err; } int jack_port_disconnect_named(jack_client_t *client, const char *src, const char *dst) { int err = jack_disconnect(client, src, dst); if(err) { eprintf("jack_disconnect() failed: '%s' -> '%s'\n", src, dst); FAILURE; } return err; } /* TRUE iff the input port `l' is connected to the output port `r'. */ int jack_port_is_connected_p(jack_client_t *j, const char *l, const char *r) { const char **c; c = jack_port_get_all_connections(j, jack_port_by_name(j, l)); if(c) { int k; for(k = 0; c[k]; k++) { if(strcmp(c[k], r)== 0) { free(c); return 1; } } free(c); } return 0; } /* Delete all connections at the port `l'. */ void jack_port_clear_all_connections(jack_client_t *j, const char *l) { const char **c; c = jack_port_get_all_connections(j, jack_port_by_name(j, l)); if(c) { int k; for(k = 0; c[k]; k++) { jack_port_disconnect_named(j, l, c[k]); } free(c); } } void jack_port_connect_pattern(jack_client_t *client, int n, char *src, char *dst) { int i; for(i = 0; i < n; i++) { char src_name[64],dst_name[64]; snprintf(src_name, 64, src, i + 1); snprintf(dst_name, 64, dst, i + 1); jack_port_connect_named(client,src_name,dst_name); } } jack-tools-20101210.orig/common/time-ntp.h0000644000175000017500000000034011536646636017170 0ustar jonasjonas#ifndef _COMMON_TIME_NTP_H #define _COMMON_TIME_NTP_H u64 utc_timeval_to_ntp(struct timeval tv); u64 utc_real_to_ntp(f64 utc); u32 utc_usec_to_ntp_approx(u32 usec); u64 utc_timeval_to_ntp_approx(struct timeval tv); #endif jack-tools-20101210.orig/common/jack-transport.c0000644000175000017500000000062711536646636020400 0ustar jonasjonas/* jack-transport.c - (c) rohan drape, 2005-2006 */ #include #include #include #include #include #include #include "failure.h" #include "jack-transport.h" #include "print.h" bool jack_transport_is_rolling(jack_client_t *client) { jack_transport_state_t s = jack_transport_query(client , NULL); return s & JackTransportRolling; } jack-tools-20101210.orig/common/jack-ringbuffer.h0000644000175000017500000000101511536646636020472 0ustar jonasjonas#ifndef _COMMON_JACK_RINGBUFFER_H #define _COMMON_JACK_RINGBUFFER_H #include #include void jack_ringbuffer_print_debug(const jack_ringbuffer_t *r, const char *s); int jack_ringbuffer_wait_for_read(const jack_ringbuffer_t *r, int nbytes, int fd); int jack_ringbuffer_wait_for_write(jack_ringbuffer_t *r, int nbytes, int fd); void jack_ringbuffer_read_exactly(jack_ringbuffer_t *r, char *buf, int n); void jack_ringbuffer_write_exactly(jack_ringbuffer_t *r, const char *buf, int n); #endif jack-tools-20101210.orig/common/signal-interpolate.c0000644000175000017500000000126311536646636021234 0ustar jonasjonas/* signal-interpolate.c - (c) rohan drape, 2005-2006 */ #include #include "int.h" #include "float.h" #include "signal-interpolate.h" f32 signal_interpolate (const f32 *signal, int signal_n, f32 index) { i32 index_i = (i32)floorf(index); f32 index_f = index - (f32)index_i; if (index_i == signal_n - 1) { return (signal[index_i] * (1.0 - index_f)) + (signal[0] * index_f); } else { return (signal[index_i] * (1.0 - index_f)) + (signal[index_i+1] * index_f); } } f32 signal_interpolate_safe (const f32 *signal, int signal_n, f32 index) { if (index < 0 || index >= (f32) signal_n) { return 0.0; } return signal_interpolate (signal, signal_n, index); } jack-tools-20101210.orig/common/Makefile.am0000644000175000017500000000167011536646636017325 0ustar jonasjonas MAINTAINERCLEANFILES = Makefile.in noinst_LIBRARIES = libcommon.a libcommon_a_SOURCES = byte-order.c byte-order.h \ client.c client.h \ failure.h \ file.c file.h \ float.h \ img.c img.h \ img-ppm.c img-ppm.h \ int.h \ jack-client.c jack-client.h \ jack-port.c jack-port.h \ jack-ringbuffer.c jack-ringbuffer.h \ jack-transport.c jack-transport.h \ memory.c memory.h \ network.c network.h \ observe-signal.c observe-signal.h \ osc.c osc.h \ print.h \ signal-clip.c signal-clip.h \ signal-copy.c signal-copy.h \ signal-interleave.c signal-interleave.h \ signal-interpolate.c signal-interpolate.h \ signal-print.c signal-print.h \ sound-file.c sound-file.h \ time-current.c time-current.h \ time-ntp.c time-ntp.h \ time-timespec.c time-timespec.h \ time-timeval.c time-timeval.h \ ximg.c ximg.h \ xregcomp.c xregcomp.h libcommon_a_CFLAGS = $(AM_CFLAGS) $(JACK_CFLAGS) jack-tools-20101210.orig/common/time-current.c0000644000175000017500000000073511536646636020054 0ustar jonasjonas/* time-current.c - (c) rohan drape, 2005-2006 */ #include #include #include "float.h" #include "time-timeval.h" #include "time-current.h" /* Get the current time as a UTC double precision value. */ f64 current_time_as_utc_real(void) { struct timeval current; gettimeofday(¤t, NULL); return timeval_to_real(current); } struct timeval current_time_as_utc_timeval(void) { struct timeval tv; gettimeofday(&tv, 0); return tv; } jack-tools-20101210.orig/common/file.c0000644000175000017500000000235711536646636016357 0ustar jonasjonas/* file.c - (c) rohan drape, 2005-2006 */ #include #include #include #include #include #include #include #include "memory.h" #include "failure.h" #include "file.h" bool file_exists_p(const char *filename) { struct stat buf; int err = stat(filename, &buf); return err == 0; } #define GENERATE_STAT_FIELD(type,name) \ type stat_##name(const char *filename) \ { \ struct stat buf; \ int err = stat(filename, &buf); \ if(err) { \ fprintf(stderr, "stat() failed: %s\n", filename); \ FAILURE; \ } \ return buf.st_##name; \ } GENERATE_STAT_FIELD(time_t, mtime); GENERATE_STAT_FIELD(size_t, size); int xpipe(int filedes[2]) { int err = pipe(filedes); if(err) { perror("pipe() failed"); FAILURE; } return err; } ssize_t xwrite(int filedes, const void *buffer, size_t size) { ssize_t err = write(filedes, buffer, size); if(err == -1) { perror("write() failed"); FAILURE; } return err; } ssize_t xread(int filedes, void *buffer, size_t size) { ssize_t err = read(filedes, buffer, size); if(err == -1) { perror("read() failed"); FAILURE; } return err; } jack-tools-20101210.orig/common/time-timeval.h0000644000175000017500000000051611536646636020035 0ustar jonasjonas#ifndef _COMMON_TIME_TIMEVAL_H #define _COMMON_TIME_TIMEVAL_H #include #include "int.h" #include "float.h" struct timeval usec_to_timeval(u64 usec); f64 timeval_to_real(struct timeval tv); struct timeval real_to_timeval(f64 d); int timeval_subtract(struct timeval *result, struct timeval x, struct timeval y); #endif jack-tools-20101210.orig/common/ximg.c0000644000175000017500000001205511536646636016400 0ustar jonasjonas/* ximg.c - (c) rohan drape, 2005-2006 */ #include #include #include "failure.h" #include "int.h" #include "memory.h" #include "ximg.h" static int ximg_handle_error(Display *d, XErrorEvent *e) { char message[128]; XGetErrorText(d, e->error_code, message, 128); fprintf(stderr, "X error: %s\n", message); FAILURE; return 1; } static int ximg_handle_io_error(Display *d) { fprintf(stderr, "X IO error\n"); FAILURE; return 1; } Ximg_t * ximg_open(int width, int height, char *name) { Ximg_t *x = xmalloc(sizeof(Ximg_t)); x->width = width; x->height = height; x->d = XOpenDisplay(NULL); XSetErrorHandler(ximg_handle_error); XSetIOErrorHandler(ximg_handle_io_error); Window r = DefaultRootWindow(x->d ); x->v = DefaultVisual(x->d, DefaultScreen(x->d)); XGCValues draw; draw.background = WhitePixel(x->d, DefaultScreen( x->d)); draw.foreground = BlackPixel(x->d, DefaultScreen( x->d)); x->draw = XCreateGC(x->d, r, GCForeground | GCBackground, &draw ); x->w = XCreateSimpleWindow(x->d, r, 0, 0, x->width, x->height, 0, BlackPixel(x->d, DefaultScreen( x->d)), WhitePixel(x->d, DefaultScreen( x->d))); XSetStandardProperties(x->d, x->w, name, name, None, NULL, 0, NULL); XSizeHints h; h.width = h.min_width = h.max_width = h.base_width = width; h.height = h.min_height = h.max_height = h.base_height = height; h.win_gravity = CenterGravity; h.flags = PSize | PMinSize | PMaxSize | PBaseSize | PWinGravity; XSetWMNormalHints(x->d, x->w, &h); x->b = XdbeAllocateBackBufferName(x->d, x->w, XdbeUndefined); x->swap.swap_window = x->w; x->swap.swap_action = XdbeUndefined; if(x->v->class != TrueColor){ fprintf(stderr, "ximg_open(): Non true color visual"); FAILURE; } x->image = XCreateImage(x->d, x->v, DisplayPlanes(x->d, DefaultScreen( x->d)), ZPixmap, 0, NULL, x->width, x->height, BitmapPad(x->d), 0); if(! x->image){ fprintf(stderr, "XCreateImage() failed"); FAILURE; } x->image->data = xmalloc(x->height * x->image->bytes_per_line); XPutImage(x->d, x->w, x->draw, x->image, 0, 0, 0, 0, x->width, x->height); XFlush(x->d); XMapWindow(x->d, x->w); return x; } /* Draw the pixel-map at data. `data' is a set of RGB triples, each one byte, in row major order. The pixmap is the same size as the window. Modified from work by John Bradley in xv(1). */ static inline int highbit(u32 ul) { i32 i; u32 hb = 0x80 << 24; /* hb = 0x80000000UL */ for(i = 31; ((ul & hb) == 0) && i >= 0; i--, ul <<= 1); return i; } void ximg_blit(Ximg_t *x, u8 *data) { u32 rmask = x->v->red_mask; u32 gmask = x->v->green_mask; u32 bmask = x->v->blue_mask; int rshift = 7 - highbit(rmask); int gshift = 7 - highbit(gmask); int bshift = 7 - highbit(bmask); int maplen = x->v->map_entries; if (maplen>256) { maplen=256; } int bperline = x->image->bytes_per_line; int bperpix = x->image->bits_per_pixel; int border = x->image->byte_order; if (bperpix != 8 && bperpix != 16 && bperpix != 24 && bperpix != 32) { fprintf(stderr, "ximg_blit() : domain error : bperpix"); abort (); } u8 *lip = (u8*)x->image->data; u8 *pp = data; int i; for (i=0; iheight; i++, lip+=bperline) { int j; u8 *ip = lip; for (j=0; jwidth; j++) { u32 r = *pp++; u32 g = *pp++; u32 b = *pp++; r = (rshift<0) ? r << (-rshift) : r >> rshift; g = (gshift<0) ? g << (-gshift) : g >> gshift; b = (bshift<0) ? b << (-bshift) : b >> bshift; r = r & rmask; g = g & gmask; b = b & bmask; u32 xcol = r | g | b; if (bperpix == 32) { if (border == MSBFirst) { *ip++ = (xcol>>24) & 0xff; *ip++ = (xcol>>16) & 0xff; *ip++ = (xcol>>8) & 0xff; *ip++ = xcol & 0xff; } else { *ip++ = xcol & 0xff; *ip++ = (xcol>>8) & 0xff; *ip++ = (xcol>>16) & 0xff; *ip++ = (xcol>>24) & 0xff; } } else if (bperpix == 24) { if (border == MSBFirst) { *ip++ = (xcol>>16) & 0xff; *ip++ = (xcol>>8) & 0xff; *ip++ = xcol & 0xff; } else { *ip++ = xcol & 0xff; *ip++ = (xcol>>8) & 0xff; *ip++ = (xcol>>16) & 0xff; } } else if (bperpix == 16) { if (border == MSBFirst) { *ip++ = (xcol>>8) & 0xff; *ip++ = xcol & 0xff; } else { *ip++ = xcol & 0xff; *ip++ = (xcol>>8) & 0xff; } } else if (bperpix == 8) { *ip++ = xcol & 0xff; } } } XdbeBeginIdiom( x->d); XPutImage(x->d, x->b, x->draw, x->image, 0, 0, 0, 0, x->width, x->height); XdbeSwapBuffers(x->d, &(x->swap), 1); XSync(x->d, 0); XdbeEndIdiom(x->d); } void ximg_mouse(Ximg_t *x, int *dx, int *dy, int *b) { int rootx, rooty; Window root, child; unsigned int mask; XQueryPointer(x->d, x->w, &root, &child, &rootx, &rooty, dx, dy, &mask); *b = (int)mask; } void ximg_close(Ximg_t *x) { XdbeDeallocateBackBufferName(x->d, x->b); XFreeGC(x->d, x->draw); XDestroyImage(x->image); XFlush(x->d); XSync(x->d, 0); XDestroyWindow(x->d, x->w); XCloseDisplay(x->d); free(x); } jack-tools-20101210.orig/common/img-ppm.c0000644000175000017500000000211711536646636017000 0ustar jonasjonas/* img-ppm.c - (c) rohan drape, 2005-2006 */ #include #include #include #include "failure.h" #include "memory.h" #include "int.h" #include "img-ppm.h" i32 img_write_ppm(u8 *data, i32 w, i32 h, FILE *fp) { fprintf(fp, "P6 %d %d 255\n", w, h); fwrite(data, w * h, 3, fp); return 0; } i32 img_write_ppm_file(u8 *data, i32 w, i32 h, const char *name) { FILE *fp = fopen(name, "w"); if(!fp){ return -1; } img_write_ppm(data, w, h, fp); fclose(fp); return 0; } u8 *img_read_ppm(i32 *w, i32 *h, FILE *fp) { i32 s_err = fscanf(fp, "P6 %d %d %*d%*c", w, h); if(s_err != 4){ fprintf(stderr, "img_read_ppm(): non P6 ppm file (err=%d)\n", s_err); FAILURE; } size_t n = *w * *h; u8 *data = xmalloc(n); size_t r_err = fread(data, 3, n, fp); if(r_err != n){ fprintf(stderr, "img_read_ppm(): fread() failed"); FAILURE; } return data; } u8 *img_read_ppm_file(i32 *w, i32 *h, const char *name) { FILE *fp = fopen(name, "r"); if(!fp){ return NULL; } u8 *data = img_read_ppm(w, h, fp); fclose(fp); return data; } jack-tools-20101210.orig/common/time-timespec.h0000644000175000017500000000022211536646636020177 0ustar jonasjonas#ifndef _COMMON_TIME_TIMESPEC_H #define _COMMON_TIME_TIMESPEC_H #include struct timespec usec_to_timespec(unsigned long usec); #endif jack-tools-20101210.orig/common/osc.c0000644000175000017500000002211111536646636016212 0ustar jonasjonas/* osc.c - (c) rohan drape, 2005-2006 */ #include #include #include #include #include #include "byte-order.h" #include "failure.h" #include "osc.h" void osc_print_packet(const u8 *packet, i32 packet_sz) { i32 i; for(i = 0; i < packet_sz; i++) { fprintf(stderr, "%3d (%1.1s) ", packet[i], packet + i); if(( i + 1)% 4 == 0) { fprintf(stderr, "\n"); } } } i32 osc_str_bound(i32 n) { return n +(4 -(n % 4)); } bool osc_is_numerical_type(u8 c) { return c == 'i' || c == 'h' || c == 't' || c == 'f' || c == 'd'; } bool osc_is_string_type(u8 c) { return c == 's' || c == 'S'; } bool osc_can_coerce(u8 u, u8 d) { return(( u == d) || (osc_is_numerical_type(u) && osc_is_numerical_type(d)) || (osc_is_string_type(u) && osc_is_string_type(d))); } void osc_coerce(u8 u, u8 d, osc_data_t *o) { if(u == d) { return; } if(u == 's' && d == 'S') { o->s = o->S; } else if(u == 'S' && d == 's') { o->S = o->s; } else if(u == 'i' && d == 'h') { o->i = (i32) o->h; } else if(u == 'i' && d == 't') { o->i = (i32) o->t; } else if(u == 'i' && d == 'f') { o->i = (i32) floorf(o->f); } else if(u == 'i' && d == 'd') { o->i = (i32) floor(o->d); } else if(u == 'h' && d == 'i') { o->h = (i64) o->i; } else if(u == 'h' && d == 't') { o->h = (i64) o->t; } else if(u == 'h' && d == 'f') { o->h = (i64) floorf(o->f); } else if(u == 'h' && d == 'd') { o->h = (i64) floor(o->d); } else if(u == 't' && d == 'i') { o->t = (u64) o->i; } else if(u == 't' && d == 'h') { o->t = (u64) o->t; } else if(u == 't' && d == 'f') { o->t = (u64) floorf(o->f); } else if(u == 't' && d == 'd') { o->t = (u64) floor(o->d); } else if(u == 'f' && d == 'i') { o->f = (f32) o->i; } else if(u == 'f' && d == 'h') { o->f = (f32) o->h; } else if(u == 'f' && d == 't') { o->f = (f32) o->t; } else if(u == 'f' && d == 'd') { o->f = (f32) o->d; } else if(u == 'd' && d == 'i') { o->d = (f64) o->i; } else if(u == 'd' && d == 'h') { o->d = (f64) o->h; } else if(u == 'd' && d == 't') { o->d = (f64) o->t; } else if(u == 'd' && d == 'f') { o->d = (f64) o->d; } else { fprintf(stderr, "osc_coerce: illegal coercion '%c' <- '%c'\n", u, d); FAILURE; } } void osc_coerce_arguments(const char *u_dsc, const char *p_dsc, osc_data_t *data) { u_dsc++; p_dsc++; while(*u_dsc != '\0') { osc_coerce(*u_dsc++, *p_dsc++, data++); } } i32 u8strlen(const u8* b) { return strlen((const char*)b); } i32 u8strncmp(const u8 *a, const u8 *b, i32 n) { return strncmp((const char*)a, (const char*)b, n); } i32 osc_collect_arguments(const char *dsc, const u8 *p, osc_data_t *data) { dsc++; i32 i = 0; while(*dsc != '\0') { u8 c = *dsc; if(c == 'i') { data[i].i = ntoh_i32_from_buf(p); p += 4; } else if(c == 'h') { data[i].h = ntoh_i64_from_buf(p); p += 8; } else if(c == 't') { data[i].t = ntoh_u64_from_buf(p); p += 8; } else if(c == 'f') { data[i].f = ntoh_f32_from_buf(p); p += 4; } else if(c == 'd') { data[i].d = ntoh_f64_from_buf(p); p += 8; } else if(c == 's') { data[i].s = (char*)p; p += osc_str_bound(u8strlen(p)); } else if(c == 'S') { data[i].S = (char*)p; p += osc_str_bound(u8strlen(p)); } else if(c == 'c') { data[i].c = ntoh_u32_from_buf(p); p += 4; } else if(c == 'm') { data[i].m = ntoh_u32_from_buf(p); p += 4; } else if(c == 'r') { data[i].r = ntoh_u32_from_buf(p); p += 4; } else if(c == 'b') { data[i].b.data = p + 4; data[i].b.size = ntoh_i32_from_buf(p); p += data[i].b.size + 4; } else { return -1; } dsc++; i++; } return 0; } i32 osc_pack_arguments(const char *dsc, const osc_data_t *data, u8 *p) { dsc++; i32 i = 0; while(*dsc != '\0') { u8 c = *dsc; if(c == 'i') { ntoh_i32_to_buf(p, data[i].i); p += 4; } else if(c == 'h') { ntoh_i64_to_buf(p, data[i].h); p += 8; } else if(c == 't') { ntoh_u64_to_buf(p, data[i].t); p += 8; } else if(c == 'f') { ntoh_f32_to_buf(p, data[i].f); p += 4; } else if(c == 'd') { ntoh_f64_to_buf(p, data[i].d); p += 8; } else if(c == 's') { i32 n = strlen(data[i].s); memcpy(p, data[i].s, n+1); p += osc_str_bound(n); } else if(c == 'S') { i32 n = strlen(data[i].s); memcpy(p, data[i].S, n+1); p += osc_str_bound(n); } else if(c == 'c') { ntoh_u32_to_buf(p, data[i].c); p += 4; } else if(c == 'm') { ntoh_u32_to_buf(p, data[i].m); p += 4; } else if(c == 'r') { ntoh_u32_to_buf(p, data[i].r); p += 4; } else if(c == 'b') { ntoh_i32_to_buf(p, data[i].b.size); memcpy(p + 4, data[i].b.data, data[i].b.size); p += osc_str_bound(data[i].b.size)+ 4; } else { return -1; } dsc++; i++; } return 0; } i32 osc_dsc_read_arg_len(const char *dsc, const u8 *p) { if(*dsc++ != ',') { fprintf(stderr, "osc_dsc_read_arg_len: illegal descriptor '%s'\n", dsc); return -1; } i32 n = 0; while(*dsc != '\0') { u8 c = *dsc; if(c == 'i' || c == 'f' || c == 'c' || c == 'm' || c == 'r') { n += 4; } else if(c == 'd' || c == 'h' || c == 't') { n += 8; } else if(c == 's' || c == 'S') { n += osc_str_bound(u8strlen(p + n)); } else if(c == 'b') { n += osc_str_bound(ntoh_i32_from_buf(p + n)) + 4; } else { return -1; } dsc++; } return n; } i32 osc_dsc_calculate_arg_len(const char *dsc, const osc_data_t *data) { if(*dsc++ != ',') { fprintf(stderr, "osc_dsc_calculate_arg_len: illegal descriptor '%s'\n", dsc); return -1; } i32 n = 0; while(*dsc != '\0') { u8 c = *dsc; if(c == 'i' || c == 'f' || c == 'c' || c == 'm' || c == 'r') { n += 4; } else if(c == 'd' || c == 'h' || c == 't') { n += 8; } else if(c == 's') { n += osc_str_bound(strlen(data->s)); } else if(c == 'S') { n += osc_str_bound(strlen(data->S)); } else if(c == 'b') { n += osc_str_bound(data->b.size)+ 4; } else { return -1; } dsc++; data++; } return n; } i32 osc_match_address(const char *addr, const u8 *packet) { size_t addr_n = strlen(addr); if(strncmp(addr, (char*)packet, addr_n)!= 0) { return 0; } else { return osc_str_bound(addr_n); } } i32 osc_match_dsc(const char *u_dsc, const char *p_dsc) { size_t u_dsc_n = strlen(u_dsc); if(*u_dsc++ != ',' || *p_dsc++ != ',') { return 0; } while(*u_dsc != '\0') { if(! osc_can_coerce(*u_dsc++, *p_dsc++)) { return 0; } } return osc_str_bound(u_dsc_n); } i32 osc_parse_message(const char *addr, const char *dsc, const u8 *packet, i32 packet_sz, osc_data_t *data) { i32 addr_len = osc_match_address(addr, packet); if(! addr_len) { return 0; } const char *p_dsc = (char*)packet + addr_len; i32 dsc_len = osc_match_dsc(dsc, p_dsc); if(! dsc_len) { return 0; } const u8 *p_arg = (u8*)p_dsc + dsc_len; i32 arg_len = osc_dsc_read_arg_len(p_dsc, p_arg); if(packet_sz < addr_len + dsc_len + arg_len) { return 0; } i32 err = osc_collect_arguments(p_dsc, p_arg, data); if(err) { return 0; } osc_coerce_arguments(dsc, p_dsc, data); return addr_len + dsc_len + arg_len; } i32 osc_construct_message(const char *addr, const char *dsc, const osc_data_t *data, u8 *packet, i32 packet_sz) { i32 addr_n = strlen(addr); i32 addr_len = osc_str_bound(addr_n); i32 dsc_n = strlen(dsc); i32 dsc_len = osc_str_bound(dsc_n); i32 arg_len = osc_dsc_calculate_arg_len(dsc, data); memset(packet, 0, addr_len + dsc_len + arg_len); memcpy(packet, addr, addr_n); memcpy(packet + addr_len, dsc, dsc_n); if(packet_sz < addr_len + dsc_len + arg_len) { return 0; } i32 err = osc_pack_arguments(dsc, data, packet + addr_len + dsc_len); if(err) { return 0; } return addr_len + dsc_len + arg_len; } i32 osc_build_message(u8 *packet, i32 packet_sz, const char *addr, const char *dsc, ...) { osc_data_t data[256]; va_list ap; va_start(ap, dsc); i32 index; index = 0; while(dsc && dsc[index+1]) { switch(dsc[index+1]) { case 'i': data[index].i = va_arg(ap, i32); break; case 'h': data[index].h = va_arg(ap, i64); break; case 't': data[index].t = va_arg(ap, u64); break; case 'f': data[index].f = va_arg(ap, f64); break; case 'd': data[index].d = va_arg(ap, f64); break; case 's': data[index].s = va_arg(ap, char*); break; case 'S': data[index].S = va_arg(ap, char*); break; case 'c': data[index].c = va_arg(ap, u32); break; case 'm': data[index].m = va_arg(ap, u32); break; case 'r': data[index].r = va_arg(ap, u32); break; case 'b': data[index].b = va_arg(ap, osc_blob_t); break; default: return 0; } index++; } va_end(ap); return osc_construct_message(addr, dsc, data, packet, packet_sz); } jack-tools-20101210.orig/common/client.c0000644000175000017500000000373411536646636016716 0ustar jonasjonas/* client.c - (c) rohan drape, 2005-2006 */ #include #include #include #include #include #include #include "client.h" #include "memory.h" #include "network.h" #include "print.h" client_register_t *alloc_client_register(i32 n) { client_register_t *r = xmalloc(sizeof(client_register_t)); r->n = n; r->c = xmalloc(n * sizeof(client_t)); i32 i; for(i = 0; i < r->n; i++) { r->c[i].in_use = 0; r->c[i].mask = 0; } return r; } void print_client_register(FILE *fp, const client_register_t *r, i32 mask) { i32 i; fprintf(fp, "print_client_register:\n"); for(i = 0; i < r->n; i++) { if(r->c[i].in_use &&(( r->c[i].mask & mask)|| mask == -1)) { fprintf(fp, "%d in use, mask = %d\n", i, r->c[i].mask); print_sockaddr_in(fp, r->c[i].address); } } } void free_client_register(client_register_t *r) { free(r->c); free(r); } void edit_client_register(client_register_t *r, struct sockaddr_in addr, i32 mask) { dprintf("edit_client_register: mask=%d\n", mask); i32 i; for(i = 0; i < r->n; i++) { if(r->c[i].in_use && sockaddr_in_equal(&addr, &(r->c[i].address))) { if(mask < 0) { r->c[i].in_use = 0; r->c[i].mask = 0; } else { r->c[i].mask = mask; } return; } } if(mask < 0) { eprintf("edit_client_register: Illegal unregistered client\n"); return; } for(i = 0; i < r->n; i++) { if(! r->c[i].in_use) { memcpy(&(r->c[i].address), &addr, sizeof(addr)); r->c[i].mask = mask; r->c[i].in_use = 1; return; } } eprintf("edit_client_register: Client dropped.\n"); } void sendto_client_register(int fd, const client_register_t *r, const u8 *packet, i32 packet_sz, i32 mask) { if(packet_sz) { i32 i; for(i = 0; i < r->n; i++) { if(r->c[i].in_use &&(r->c[i].mask & mask)) { sendto_exactly(fd, packet, packet_sz, r->c[i].address); } } } } jack-tools-20101210.orig/common/time-timespec.c0000644000175000017500000000045311536646636020200 0ustar jonasjonas/* time-timespec.c - (c) rohan drape, 2005-2006 */ #include #include "time-timespec.h" struct timespec usec_to_timespec(unsigned long usec) { struct timespec t; long nsec = usec * 1000; ldiv_t d = ldiv(nsec, 1000000000L); t.tv_sec = d.quot; t.tv_nsec = d.rem; return t; } jack-tools-20101210.orig/common/xregcomp.h0000644000175000017500000000022011536646636017254 0ustar jonasjonas#ifndef _COMMON_XREGCOMP_H #define _COMMON_XREGCOMP_H #include int xregcomp(regex_t *preg, const char *regex, int cflags); #endif jack-tools-20101210.orig/common/signal-interleave.h0000644000175000017500000000056111536646636021051 0ustar jonasjonas#ifndef _COMMON_SIGNAL_INTERLEAVE_H #define _COMMON_SIGNAL_INTERLEAVE_H #include "float.h" void signal_interleave(f32 *dst, const f32 *src, int f, int c); void signal_uninterleave(f32 *dst, const f32 *src, int f, int c); void signal_interleave_to(f32 *dst, const f32 **src, int f, int c); void signal_uninterleave_to(f32 **dst, const f32 *src, int f, int c); #endif jack-tools-20101210.orig/common/byte-order.h0000644000175000017500000000506211536646636017515 0ustar jonasjonas#ifndef _COMMON_BYTE_ORDER_H #define _COMMON_BYTE_ORDER_H #include #include #include "float.h" #include "int.h" typedef union { u16 u; i16 i; } n16_t; typedef union { u32 u; i32 i; f32 f; } n32_t; typedef union { u64 u; i64 i; f64 f; } n64_t; void byte_order_confirm(void); void hton16_to_buf(u8 *buf, u16 n); void ntoh16_to_buf(u8 *buf, u16 n); void hton32_to_buf(u8 *buf, u32 n); void ntoh32_to_buf(u8 *buf, u32 n); void hton64_to_buf(u8 *buf, u64 n); void ntoh64_to_buf(u8 *buf, u64 n); u16 hton16_from_buf(const u8 *buf); u16 ntoh16_from_buf(const u8 *buf); u32 hton32_from_buf(const u8 *buf); u32 ntoh32_from_buf(const u8 *buf); u64 hton64_from_buf(const u8 *buf); u64 ntoh64_from_buf(const u8 *buf); void hton16_buf(u8 *dst, const u8 *src); void ntoh16_buf(u8 *dst, const u8 *src); void hton32_buf(u8 *dst, const u8 *src); void ntoh32_buf(u8 *dst, const u8 *src); void hton64_buf(u8 *dst, const u8 *src); void ntoh64_buf(u8 *dst, const u8 *src); void hton_u16_to_buf(u8 *buf, u16 a); void ntoh_u16_to_buf(u8 *buf, u16 a); void hton_i16_to_buf(u8 *buf, i16 a); void ntoh_i16_to_buf(u8 *buf, i16 a); void hton_u32_to_buf(u8 *buf, u32 a); void ntoh_u32_to_buf(u8 *buf, u32 a); void hton_i32_to_buf(u8 *buf, i32 a); void ntoh_i32_to_buf(u8 *buf, i32 a); void hton_f32_to_buf(u8 *buf, f32 a); void ntoh_f32_to_buf(u8 *buf, f32 a); void hton_u64_to_buf(u8 *buf, u64 a); void ntoh_u64_to_buf(u8 *buf, u64 a); void hton_i64_to_buf(u8 *buf, i64 a); void ntoh_i64_to_buf(u8 *buf, i64 a); void hton_f64_to_buf(u8 *buf, f64 a); void ntoh_f64_to_buf(u8 *buf, f64 a); u16 hton_u16_from_buf(const u8 *buf); u16 ntoh_u16_from_buf(const u8 *buf); i16 hton_i16_from_buf(const u8 *buf); i16 ntoh_i16_from_buf(const u8 *buf); u32 hton_u32_from_buf(const u8 *buf); u32 ntoh_u32_from_buf(const u8 *buf); i32 hton_i32_from_buf(const u8 *buf); i32 ntoh_i32_from_buf(const u8 *buf); f32 hton_f32_from_buf(const u8 *buf); f32 ntoh_f32_from_buf(const u8 *buf); u64 hton_u64_from_buf(const u8 *buf); u64 ntoh_u64_from_buf(const u8 *buf); i64 hton_i64_from_buf(const u8 *buf); i64 ntoh_i64_from_buf(const u8 *buf); f64 hton_f64_from_buf(const u8 *buf); f64 ntoh_f64_from_buf(const u8 *buf); u16 hton_u16(u16 a); i16 hton_i16(i16 a); u16 ntoh_u16(u16 a); i16 ntoh_i16(i16 a); u32 hton_u32(u32 a); i32 hton_i32(i32 a); f32 hton_f32(f32 a); u64 hton_u64(u64 a); i64 hton_i64(i64 a); f64 hton_f64(f64 a); u32 ntoh_u32(u32 a); i32 ntoh_i32(i32 a); f32 ntoh_f32(f32 a); u64 ntoh_u64(u64 a); i64 ntoh_i64(i64 a); f64 ntoh_f64(f64 a); #endif jack-tools-20101210.orig/common/memory.h0000644000175000017500000000041011536646636016741 0ustar jonasjonas#ifndef _COMMON_MEMORY_H #define _COMMON_MEMORY_H #include void *xmalloc(size_t size); void *xcalloc(size_t count, size_t eltsize); void *xrealloc(void *p, size_t size); float *fmalloc(size_t n); void fmemset(float *data, int n, float value); #endif jack-tools-20101210.orig/common/byte-order.c0000644000175000017500000000741011536646636017507 0ustar jonasjonas/* byte-order.c - (c) rohan drape, 2005-2006 */ #include #include "byte-order.h" #include "failure.h" #include "float.h" #include "int.h" #include "print.h" u16 hton16(u16 n) { return htons(n); } u16 ntoh16(u16 n) { return ntohs(n); } u32 hton32(u32 n) { return htonl(n); } u32 ntoh32(u32 n) { return ntohl(n); } u64 hton64(u64 n) { u8 *ptr = (u8*)&n; return ((u64)hton32(*(u32*)ptr) << 32) + (hton32(*(u32*)(ptr + 4))); } u64 ntoh64(u64 n) { u8 *ptr = (u8*)&n; return ((u64)ntoh32(*(u32*)ptr) << 32) + (ntoh32(*(u32*)(ptr + 4))); } void byte_order_confirm(void) { u8 a[4] = {0,0,0,1}; u32 b = ntoh_u32_from_buf(a); if(b != 1){ eprintf("byte_order_confirm: incorrect machine word order\n"); FAILURE; } } #define GENERATE_NC_TO_BUF(proc,size) \ void proc##size##_to_buf(u8 *buf,u##size n) \ { \ n = proc##size(n); \ memcpy(buf,&n,size/8); \ } GENERATE_NC_TO_BUF(hton,16); GENERATE_NC_TO_BUF(ntoh,16); GENERATE_NC_TO_BUF(hton,32); GENERATE_NC_TO_BUF(ntoh,32); GENERATE_NC_TO_BUF(hton,64); GENERATE_NC_TO_BUF(ntoh,64); #define GENERATE_NC_FROM_BUF(proc,size) \ u##size proc##size##_from_buf(const u8 *buf) \ { \ u##size n; \ memcpy(&n,buf,size/8); \ return proc##size(n); \ } GENERATE_NC_FROM_BUF(hton,16); GENERATE_NC_FROM_BUF(ntoh,16); GENERATE_NC_FROM_BUF(hton,32); GENERATE_NC_FROM_BUF(ntoh,32); GENERATE_NC_FROM_BUF(hton,64); GENERATE_NC_FROM_BUF(ntoh,64); #define GENERATE_NC_BUF(proc,size) \ void proc##size##_buf(u8 *dst,const u8 *src) \ { \ u##size n = proc##size##_from_buf(src); \ memcpy(dst,&n,size/8); \ } GENERATE_NC_BUF(hton,16); GENERATE_NC_BUF(ntoh,16); GENERATE_NC_BUF(hton,32); GENERATE_NC_BUF(ntoh,32); GENERATE_NC_BUF(hton,64); GENERATE_NC_BUF(ntoh,64); #define GENERATE_TNC_TO_BUF(proc,tag,size) \ void proc##_##tag##size##_to_buf(u8 *buf,tag##size a) \ { \ n##size##_t n; \ n.tag = a; \ proc##size##_to_buf(buf,n.u); \ } GENERATE_TNC_TO_BUF(hton,u,16); GENERATE_TNC_TO_BUF(ntoh,u,16); GENERATE_TNC_TO_BUF(hton,i,16); GENERATE_TNC_TO_BUF(ntoh,i,16); GENERATE_TNC_TO_BUF(hton,u,32); GENERATE_TNC_TO_BUF(ntoh,u,32); GENERATE_TNC_TO_BUF(hton,i,32); GENERATE_TNC_TO_BUF(ntoh,i,32); GENERATE_TNC_TO_BUF(hton,f,32); GENERATE_TNC_TO_BUF(ntoh,f,32); GENERATE_TNC_TO_BUF(hton,u,64); GENERATE_TNC_TO_BUF(ntoh,u,64); GENERATE_TNC_TO_BUF(hton,i,64); GENERATE_TNC_TO_BUF(ntoh,i,64); GENERATE_TNC_TO_BUF(hton,f,64); GENERATE_TNC_TO_BUF(ntoh,f,64); #define GENERATE_TNC_FROM_BUF(proc,tag,size) \ tag##size proc##_##tag##size##_from_buf(const u8 *buf) \ { \ n##size##_t n; \ n.u = proc##size##_from_buf(buf); \ return n.tag; \ } GENERATE_TNC_FROM_BUF(hton,u,16); GENERATE_TNC_FROM_BUF(ntoh,u,16); GENERATE_TNC_FROM_BUF(hton,i,16); GENERATE_TNC_FROM_BUF(ntoh,i,16); GENERATE_TNC_FROM_BUF(hton,u,32); GENERATE_TNC_FROM_BUF(ntoh,u,32); GENERATE_TNC_FROM_BUF(hton,i,32); GENERATE_TNC_FROM_BUF(ntoh,i,32); GENERATE_TNC_FROM_BUF(hton,f,32); GENERATE_TNC_FROM_BUF(ntoh,f,32); GENERATE_TNC_FROM_BUF(hton,u,64); GENERATE_TNC_FROM_BUF(ntoh,u,64); GENERATE_TNC_FROM_BUF(hton,i,64); GENERATE_TNC_FROM_BUF(ntoh,i,64); GENERATE_TNC_FROM_BUF(hton,f,64); GENERATE_TNC_FROM_BUF(ntoh,f,64); #define GENERATE_TNC(proc,tag) \ tag \ proc##_##tag(tag a) \ { \ proc##_##tag##_to_buf((u8 *)&a,a); \ return a; \ } GENERATE_TNC(hton,u16); GENERATE_TNC(hton,i16); GENERATE_TNC(ntoh,u16); GENERATE_TNC(ntoh,i16); GENERATE_TNC(hton,u32); GENERATE_TNC(hton,i32); GENERATE_TNC(hton,f32); GENERATE_TNC(hton,u64); GENERATE_TNC(hton,i64); GENERATE_TNC(hton,f64); GENERATE_TNC(ntoh,u32); GENERATE_TNC(ntoh,i32); GENERATE_TNC(ntoh,f32); GENERATE_TNC(ntoh,u64); GENERATE_TNC(ntoh,i64); GENERATE_TNC(ntoh,f64); jack-tools-20101210.orig/common/failure.h0000644000175000017500000000020111536646636017056 0ustar jonasjonas#ifndef _COMMON_FAILURE_H #define _COMMON_FAILURE_H #include #ifndef FAILURE #define FAILURE exit(1) #endif #endif jack-tools-20101210.orig/common/signal-interleave.c0000644000175000017500000000164511536646636021050 0ustar jonasjonas/* signal-interleave.c - (c) rohan drape, 2005-2006 */ #include "float.h" #include "signal-interleave.h" /* f = number of frames, c = number of channels */ void signal_interleave(f32 *dst, const f32 *src, int f, int c) { int i, k = 0; for(i = 0; i < f; i++) { int j; for(j = 0; j < c; j++) { dst[k++] = src[(j*f)+i]; } } } void signal_uninterleave(f32 *dst, const f32 *src, int f, int c) { int i, k = 0; for(i = 0; i < f; i++) { int j; for(j = 0; j < c; j++) { dst[(j*f)+i] = src[k++]; } } } void signal_interleave_to(f32 *dst, const f32 **src, int f, int c) { int i, k = 0; for(i = 0; i < f; i++) { int j; for(j = 0; j < c; j++) { dst[k++] = src[j][i]; } } } void signal_uninterleave_to(f32 **dst, const f32 *src, int f, int c) { int i, k = 0; for(i = 0; i < f; i++) { int j; for(j = 0; j < c; j++) { dst[j][i] = src[k++]; } } } jack-tools-20101210.orig/common/file.h0000644000175000017500000000055011536646636016355 0ustar jonasjonas#ifndef _COMMON_FILE_H #define _COMMON_FILE_H void *xrealloc(void *p, size_t size); bool file_exists_p(const char *filename); time_t stat_mtime(const char *filename); size_t stat_size(const char *filename); int xpipe(int filedes[2]); ssize_t xwrite(int filedes, const void *buffer, size_t size); ssize_t xread(int filedes, void *buffer, size_t size); #endif jack-tools-20101210.orig/common/signal-print.h0000644000175000017500000000026411536646636020047 0ustar jonasjonas#ifndef _COMMON_SIGNAL_PRINT_H #define _COMMON_SIGNAL_PRINT_H #include #include "float.h" void signal_print(FILE *fp, const char *prefix, const f32 *f, int n); #endif jack-tools-20101210.orig/common/img.c0000644000175000017500000000143511536646636016210 0ustar jonasjonas/* img.c - (c) rohan drape, 2005-2006 */ #include #include #include #include "failure.h" #include "memory.h" #include "int.h" #include "float.h" /* data = pixel map, w = width, x = column number, y = row number, pixel = RGB */ void img_set_pixel(u8 *data, i32 w, i32 x, i32 y, const u8 *pixel) { i32 n = ((w * y) + x) * 3; memcpy(data + n, pixel, 3); } i32 signal_x_to_screen_x(f32 x, i32 width) { f32 xx = (x / 2.0) + 0.5; return floorf(xx * (f32)width); } i32 signal_y_to_screen_y(f32 y, i32 height) { f32 yy = 1.0 - ((y / 2.0) + 0.5); return floorf(yy * (f32)height); } i32 normal_x_to_screen_x(f32 x, i32 width) { return floorf(x * (f32)width); } i32 normal_y_to_screen_y(f32 y, i32 height) { return floorf((1.0 - y) * (f32)height); } jack-tools-20101210.orig/common/jack-ringbuffer.c0000644000175000017500000000324311536646636020472 0ustar jonasjonas/* jack-ringbuffer.c - (c) rohan drape, 2005-2006 */ #include #include #include #include #include #include #include "failure.h" #include "jack-ringbuffer.h" #include "print.h" void jack_ringbuffer_print_debug(const jack_ringbuffer_t *r, const char *s) { eprintf("%s: read_ptr=%d,write_ptr=%d,size=%d,size_mask=%d\n", s, (int)r->read_ptr, (int)r->write_ptr, (int)r->size, (int)r->size_mask); } int jack_ringbuffer_wait_for_read(const jack_ringbuffer_t *r, int nbytes, int fd) { int space = (int) jack_ringbuffer_read_space(r); while(space < nbytes) { char b; if(read(fd, &b, 1)== -1) { eprintf("%s: error reading communication pipe\n", __func__); FAILURE; } space = (int) jack_ringbuffer_read_space(r); } return space; } int jack_ringbuffer_wait_for_write(jack_ringbuffer_t *r, int nbytes, int fd) { int space = (int)jack_ringbuffer_write_space(r); while(space < nbytes) { char b; if(read(fd, &b, 1)== -1) { fprintf (stderr, "%s: error reading communication pipe\n", __func__); FAILURE; } space = (int) jack_ringbuffer_write_space(r); } return space; } void jack_ringbuffer_read_exactly(jack_ringbuffer_t *r, char *buf, int n) { int err = jack_ringbuffer_read(r, buf, n); if(err != n) { eprintf("%s: error reading ring buffer (%d != %d)\n", __func__, err, n); FAILURE; } } void jack_ringbuffer_write_exactly(jack_ringbuffer_t *r, const char *buf, int n) { int err = jack_ringbuffer_write(r, buf, n); if(err != n) { eprintf("%s: error writing ring buffer (%d != %d)\n", __func__, err, n); FAILURE; } } jack-tools-20101210.orig/common/network.c0000644000175000017500000000767011536646636017134 0ustar jonasjonas/* network.c - (c) rohan drape, 2005-2006 */ #include #include #include #include #include #include #include #include #include #include #include #include #include "int.h" #include "failure.h" #include "time-timeval.h" int socket_udp(int flags) { int fd = socket(AF_INET, SOCK_DGRAM, flags); if(fd < 0) { perror("socket_udp: socket() failed"); FAILURE; } return fd; } 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); FAILURE; } name->sin_addr = *(struct in_addr *) hostinfo->h_addr_list[0]; } else { name->sin_addr.s_addr = htonl(INADDR_ANY); } } void init_broadcast_sockaddr_in(struct sockaddr_in *name, uint16_t port) { name->sin_family = AF_INET; name->sin_port = htons(port); name->sin_addr.s_addr = htonl(INADDR_BROADCAST); } int sockaddr_in_equal(const struct sockaddr_in *a, const struct sockaddr_in *b) { return(( a->sin_family == b->sin_family)&& (a->sin_addr.s_addr == b->sin_addr.s_addr)&& (a->sin_port == b->sin_port)); } void print_sockaddr_in(FILE *fp, struct sockaddr_in a) { fprintf(fp, "sin_family %d\n", a.sin_family); fprintf(fp, "sin_port %d\n", a.sin_port); fprintf(fp, "sin_addr.s_addr %d\n", a.sin_addr.s_addr); } void bind_inet(int fd, const char *hostname, int port) { struct sockaddr_in name; init_sockaddr_in(&name, hostname, port); int err = bind(fd, (struct sockaddr *)&name, sizeof(name)); if(err < 0) { perror("bind_inet: bind() failed"); FAILURE; } } void connect_inet(int fd, const char *hostname, int port) { struct sockaddr_in name; init_sockaddr_in(&name, hostname, port); int err = connect(fd, (struct sockaddr *)&name, sizeof(name)); if(err < 0) { perror("connect_inet: bind() failed"); FAILURE; } } int xsendto(int fd, const void *data, size_t n, int flags, struct sockaddr *addr, socklen_t length) { int err = sendto(fd, data, n, flags, addr, length); if(err < 0) { perror("sendto() failed"); FAILURE; } return err; } void sendto_exactly(int fd, const u8 *data, int n, struct sockaddr_in address) { int err = xsendto(fd, data, n, 0, (struct sockaddr *)&address, sizeof(address)); if(err != n) { fprintf(stderr, "sendto_exactly: partial write\n"); FAILURE; } } int xrecv(int fd, void *buf, size_t n, int flags) { int err = recv(fd, buf, n, flags); if(err < 0) { perror("recv() failed"); FAILURE; } return err; } void recv_exactly(int fd, void *buf, size_t n, int flags) { int err = (int) xrecv(fd, buf, n, flags); if(err != n) { fprintf(stderr, "recv_exactly: partial recv (%d != %ul)\n", err, (int) n); FAILURE; } } int xrecvfrom(int fd, void *buf, size_t n, int flags, struct sockaddr *addr, socklen_t *length) { int err = recvfrom(fd, buf, n, flags, addr, length); if(err < 0) { perror("recvfrom() failed"); FAILURE; } return err; } void recvfrom_exactly(int fd, void *buf, size_t n, int flags, struct sockaddr *addr, socklen_t *length) { int err = (int) xrecvfrom(fd, buf, n, flags, addr, length); if(err != n) { fprintf(stderr, "recvfrom_exactly: partial recv (%d != %d)\n", err, (int) n); FAILURE; } } /* Wait at most `timeout' usecs for `fd' to become readable. Returns 0 on timeout, 1 if data is available. */ int fd_wait(int fd, unsigned long timeout) { fd_set set; FD_ZERO(&set); FD_SET(fd, &set); struct timeval t; t = usec_to_timeval(timeout); int err; err = select(FD_SETSIZE, &set, NULL, NULL, &t); if(err == -1) { fprintf(stderr, "fd_wait: select failed, %d\n", err); FAILURE; } return err; } jack-tools-20101210.orig/common/signal-interpolate.h0000644000175000017500000000036411536646636021242 0ustar jonasjonas#ifndef _COMMON_SIGNAL_INTERPOLATE_H #define _COMMON_SIGNAL_INTERPOLATE_H #include "float.h" f32 signal_interpolate(const f32 *signal, int signal_n, f32 index); f32 signal_interpolate_safe(const f32 *signal, int signal_n, f32 index); #endif jack-tools-20101210.orig/common/signal-clip.c0000644000175000017500000000046111536646636017634 0ustar jonasjonas/* signal-clip.c - (c) rohan drape, 2005-2006 */ #include "signal-clip.h" /* l = left, r = right, n = length of signal */ void signal_clip(float *s, int n, float l, float r) { int i; for(i = 0; i < n; i++) { if(s[i] < l) { s[i] = l; } else if(s[i] > r) { s[i] = r; } } } jack-tools-20101210.orig/common/img.h0000644000175000017500000000052011536646636016207 0ustar jonasjonas#ifndef _COMMON_IMG_H #define _COMMON_IMG_H #include "int.h" #include "float.h" void img_set_pixel(u8 *data, i32 w, i32 x, i32 y, const u8 *pixel); i32 signal_x_to_screen_x(f32 x, i32 width); i32 signal_y_to_screen_y(f32 y, i32 height); i32 normal_x_to_screen_x(f32 x, i32 width); i32 normal_y_to_screen_y(f32 y, i32 height); #endif jack-tools-20101210.orig/common/time-current.h0000644000175000017500000000030711536646636020054 0ustar jonasjonas#ifndef _COMMON_TIME_CURRENT_H #define _COMMON_TIME_CURRENT_H #include #include "float.h" f64 current_time_as_utc_real(void); struct timeval current_time_as_utc_timeval(void); #endif jack-tools-20101210.orig/common/network.h0000644000175000017500000000211711536646636017130 0ustar jonasjonas#ifndef _COMMON_NETWORK_H #define _COMMON_NETWORK_H #include #include #include "int.h" int socket_udp(int flags); void init_sockaddr_in(struct sockaddr_in *name, const char *hostname, uint16_t port); void init_broadcast_sockaddr_in(struct sockaddr_in *name, uint16_t port); int sockaddr_in_equal(const struct sockaddr_in *a, const struct sockaddr_in *b); void print_sockaddr_in(FILE *fp, struct sockaddr_in a); void bind_inet(int fd, const char *hostname, int port); void connect_inet(int fd, const char *hostname, int port); int xsendto(int fd, const void *data, size_t n, int flags, struct sockaddr *addr, socklen_t length); void sendto_exactly(int fd, const u8 *data, int n, struct sockaddr_in address); int xrecv(int fd, void *buf, size_t n, int flags); void recv_exactly(int fd, void *buf, size_t n, int flags); int xrecvfrom(int fd, void *buf, size_t n, int flags, struct sockaddr *addr, socklen_t *length); void recvfrom_exactly(int fd, void *buf, size_t n, int flags, struct sockaddr *addr, socklen_t *length); int fd_wait(int fd, unsigned long timeout); #endif jack-tools-20101210.orig/common/ximg.h0000644000175000017500000000101411536646636016376 0ustar jonasjonas#ifndef _COMMON_XIMG_H #define _COMMON_XIMG_H #include #include #include #include typedef struct { Display *d ; Window w ; Visual *v ; XImage *image ; GC draw ; XdbeBackBuffer b ; XdbeSwapInfo swap ; uint32_t width ; uint32_t height ; } Ximg_t ; Ximg_t *ximg_open(int width, int height, char *name); void ximg_blit(Ximg_t *x, uint8_t *data); void ximg_mouse(Ximg_t *x, int *dx, int *dy, int *b); void ximg_close(Ximg_t *x); #endif jack-tools-20101210.orig/common/time-ntp.c0000644000175000017500000000204411536646636017166 0ustar jonasjonas/* time-ntp.c - (c) rohan drape, 2005-2006 */ #include #include #include #include "int.h" #include "float.h" #include "time-timeval.h" #include "time-ntp.h" u64 utc_timeval_to_ntp(struct timeval tv) { const u64 secdif = (u64)2208988800UL; /* seconds from 1900 to 1970 */ const f64 ms_to_ntp = (f64)4294.967296; const u64 a = (u64)tv.tv_sec + secdif; const u64 b = (u64) ((f64)tv.tv_usec * ms_to_ntp); return (a << 32) + b; } u64 utc_real_to_ntp(f64 utc) { return utc_timeval_to_ntp(real_to_timeval(utc)); } /* This routine uses the factorization 2^32/10^6 = 4096 + 256 - 1825/32 which results in a max conversion error of 3 * 10^-7 and an average error of half that. */ u32 utc_usec_to_ntp_approx(u32 usec) { u32 t = (usec * 1825) >> 5; return (usec << 12) + (usec << 8) - t; } u64 utc_timeval_to_ntp_approx(struct timeval tv) { const u64 secdif = (u64)2208988800UL; /* seconds from 1900 to 1970 */ return ((u64)tv.tv_sec + (secdif << 32)) + ((u64)utc_usec_to_ntp_approx (tv.tv_usec)); } jack-tools-20101210.orig/common/img-ppm.h0000644000175000017500000000045311536646636017006 0ustar jonasjonas#ifndef _COMMON_IMG_PPM_H #define _COMMON_IMG_PPM_H #include "int.h" i32 img_write_ppm(u8 *data, i32 w, i32 h, FILE *fp); i32 img_write_ppm_file(u8 *data, i32 w, i32 h, const char *name); u8 *img_read_ppm(i32 *w, i32 *h, FILE *fp); u8 *img_read_ppm_file(i32 *w, i32 *h, const char *name); #endif jack-tools-20101210.orig/common/osc.h0000644000175000017500000000300411536646636016217 0ustar jonasjonas#ifndef _COMMON_OSC_H #define _COMMON_OSC_H #include #include #include "int.h" #include "float.h" typedef struct { const u8 *data; i32 size; } osc_blob_t; typedef union { i32 i; i64 h; u64 t; f32 f; f64 d; const char *s; const char *S; u32 c; u32 m; u32 r; osc_blob_t b; } osc_data_t; typedef struct { u8 type; osc_data_t value; } osc_arg_t; void osc_print_packet(const u8 *packet, i32 packet_sz); i32 osc_str_bound(i32 n); bool osc_is_numerical_type(u8 c); bool osc_is_string_type(u8 c); bool osc_can_coerce(u8 u, u8 d); void osc_coerce(u8 u, u8 d, osc_data_t *o); void osc_coerce_arguments(const char *u_dsc, const char *p_dsc, osc_data_t *data); i32 osc_collect_arguments(const char *dsc, const u8 *p, osc_data_t *data); i32 osc_pack_arguments(const char *dsc, const osc_data_t *data, u8 *p); i32 osc_dsc_read_arg_len(const char *dsc, const u8 *p); i32 osc_dsc_calculate_arg_len(const char *dsc, const osc_data_t *data); i32 osc_match_address(const char *addr, const u8 *packet); i32 osc_match_dsc(const char *u_dsc, const char *p_dsc); i32 osc_parse_message(const char *addr, const char *dsc, const u8 *packet, i32 packet_sz, osc_data_t *data); i32 osc_construct_message(const char *addr, const char *dsc, const osc_data_t *data, u8 *packet, i32 packet_sz); i32 osc_build_message(u8 *packet, i32 packet_sz, const char *addr, const char *dsc, ...); #ifdef DEBUG #define osc_debug_print(pkt,sz) osc_print_packet(pkt,sz); #else #define osc_debug_print(pkt,sz) #endif #endif jack-tools-20101210.orig/common/int.h0000644000175000017500000000040111536646636016223 0ustar jonasjonas#ifndef _COMMON_INT_H #define _COMMON_INT_H #include typedef int8_t i8; typedef int16_t i16; typedef int32_t i32; typedef int64_t i64; typedef uint8_t u8; typedef uint16_t u16; typedef uint32_t u32; typedef uint64_t u64; #endif jack-tools-20101210.orig/common/observe-signal.h0000644000175000017500000000023711536646636020360 0ustar jonasjonas#ifndef _COMMON_OBSERVE_SIGNAL_H #define _COMMON_OBSERVE_SIGNAL_H #include int observe_signals(void); bool observe_end_of_process(void); #endif jack-tools-20101210.orig/common/print.h0000644000175000017500000000034411536646636016573 0ustar jonasjonas#ifndef _COMMON_PRINT_H #define _COMMON_PRINT_H #include #define eprintf(...) fprintf(stderr,__VA_ARGS__) #ifdef DEBUG #define dprintf(...) fprintf(stderr,__VA_ARGS__) #else #define dprintf(...) #endif #endif jack-tools-20101210.orig/common/jack-transport.h0000644000175000017500000000025711536646636020404 0ustar jonasjonas#ifndef _COMMON_JACK_TRANSPORT_H #define _COMMON_JACK_TRANSPORT_H #include #include bool jack_transport_is_rolling(jack_client_t *client); #endif jack-tools-20101210.orig/common/sound-file.h0000644000175000017500000000072011536646636017502 0ustar jonasjonas#ifndef _COMMON_SOUND_FILE_H #define _COMMON_SOUND_FILE_H #include SNDFILE *xsf_open(const char *path, int mode, SF_INFO *sfinfo); void xsf_handle_error(SNDFILE *sndfile); sf_count_t xsf_read_float(SNDFILE *sndfile, float *ptr, sf_count_t items); sf_count_t xsf_write_float(SNDFILE *sndfile, float *ptr, sf_count_t items); float *read_signal_file(const char *name, int *n); void write_signal_file(const char *name, const float *data, int n); #endif jack-tools-20101210.orig/common/time-timeval.c0000644000175000017500000000207411536646636020031 0ustar jonasjonas/* time-timeval.c - (c) rohan drape, 2005-2006 */ #include #include #include "int.h" #include "float.h" #include "time-timeval.h" struct timeval usec_to_timeval(u64 usec) { struct timeval t; ldiv_t d = ldiv(usec, 1000000L); t.tv_sec = d.quot; t.tv_usec = d.rem; return t; } f64 timeval_to_real(struct timeval tv) { return (f64)tv.tv_sec + ((f64)tv.tv_usec / 1000000.0); } struct timeval real_to_timeval(f64 d) { struct timeval t; t.tv_sec = (long)floor(d); t.tv_usec = (long)ceil((d - (f64)t.tv_sec) * 1000000.0); return t; } int timeval_subtract(struct timeval *result, struct timeval x, struct timeval y) { if (x.tv_usec < y.tv_usec) { int nsec = (y.tv_usec - x.tv_usec) / 1000000 + 1; y.tv_usec -= 1000000 * nsec; y.tv_sec += nsec; } if (x.tv_usec - y.tv_usec > 1000000) { int nsec = (x.tv_usec - y.tv_usec) / 1000000; y.tv_usec += 1000000 * nsec; y.tv_sec -= nsec; } result->tv_sec = x.tv_sec - y.tv_sec; result->tv_usec = x.tv_usec - y.tv_usec; return x.tv_sec < y.tv_sec; } jack-tools-20101210.orig/common/client.h0000644000175000017500000000113011536646636016707 0ustar jonasjonas#ifndef _COMMON_CLIENT_H #define _COMMON_CLIENT_H #include "int.h" typedef struct { struct sockaddr_in address ; i32 mask ; i8 in_use ; } client_t ; typedef struct { client_t *c ; i32 n ; } client_register_t ; client_register_t *alloc_client_register(i32 n); void print_client_register(FILE *fp, const client_register_t *r, i32 mask); void free_client_register(client_register_t *r); void edit_client_register(client_register_t *r, struct sockaddr_in addr, i32 mask); void sendto_client_register(int fd, const client_register_t *r, const u8 *packet, i32 packet_sz, i32 mask); #endif jack-tools-20101210.orig/common/xregcomp.c0000644000175000017500000000062511536646636017260 0ustar jonasjonas/* xregcomp.c - (c) rohan drape, 2005-2006 */ #include #include "failure.h" #include "xregcomp.h" int xregcomp(regex_t *preg, const char *regex, int cflags) { int err = regcomp(preg, regex, cflags); if(err) { char str[64]; regerror(err, preg, str, 64); fprintf(stderr, "regcomp() failed on `%s' with `%d': %s\n", regex, cflags, str); FAILURE; } return err; } jack-tools-20101210.orig/common/jack-client.h0000644000175000017500000000055011536646636017622 0ustar jonasjonas#ifndef _COMMON_JACK_CLIENT_H #define _COMMON_JACK_CLIENT_H #include void jack_client_minimal_error_handler(const char *desc); void jack_client_minimal_shutdown_handler(void *arg); jack_client_t *jack_client_unique_store(char *name); jack_client_t *jack_client_unique(const char *name); int jack_client_activate(jack_client_t *client); #endif jack-tools-20101210.orig/common/sound-file.c0000644000175000017500000000374211536646636017504 0ustar jonasjonas/* sound-file.c - (c) rohan drape, 2005-2006 */ #include #include "failure.h" #include "memory.h" #include "sound-file.h" SNDFILE *xsf_open(const char *path, int mode, SF_INFO *sfinfo) { SNDFILE *s = sf_open(path, mode, sfinfo); if(!s) { sf_perror(s); FAILURE; } return s; } void xsf_handle_error(SNDFILE *sndfile) { int errnum = sf_error(sndfile); const char *errstr = sf_error_number(errnum); fprintf(stderr, "libsndfile failed: %s\n", errstr); FAILURE; } sf_count_t xsf_read_float(SNDFILE *sndfile, float *ptr, sf_count_t items) { sf_count_t err = sf_read_float(sndfile, ptr, items); if(err < 0) { xsf_handle_error(sndfile); } return err; } sf_count_t xsf_write_float(SNDFILE *sndfile, float *ptr, sf_count_t items) { sf_count_t err = sf_write_float(sndfile, ptr, items); if(err < 0) { xsf_handle_error(sndfile); } return err; } /* Read the single channel sound file at `name' to a newly allocated array and store the size at `n'. */ float *read_signal_file(const char *name, int *n) { SF_INFO sfi; SNDFILE *sfp = sf_open(name, SFM_READ, &sfi); if(!sfp) { fprintf(stderr, "sf_open() failed\n"); sf_perror(sfp); FAILURE; } if(sfi.channels != 1) { fprintf(stderr, "illegal channel count: %d\n", sfi.channels); FAILURE; } *n = sfi.frames; float *data = xmalloc(*n * sizeof(float)); int err = sf_read_float(sfp, data, *n); if(err == -1) { fprintf(stderr, "sf_read_float() failed\n"); sf_perror(sfp); FAILURE; } return data; } void write_signal_file(const char *name, const float *data, int n) { SF_INFO sfi; sfi.channels = 1; sfi.samplerate = 44100; sfi.frames = 0; sfi.format = SF_FORMAT_WAV | SF_FORMAT_FLOAT; SNDFILE *sfp = sf_open(name, SFM_WRITE, &sfi); if(!sfp) { sf_perror(sfp); FAILURE; } int err = sf_write_float(sfp, data, n); if(err == -1) { fprintf(stderr, "sf_write_float() failed\n"); sf_perror(sfp); FAILURE; } sf_close(sfp); } jack-tools-20101210.orig/jack.udp.c0000644000175000017500000001714311536646636015646 0ustar jonasjonas/***** jack.udp.c - (c) rohan drape, 2003-2010 *****/ #include #include #include #include #include #include #include #include "common/byte-order.h" #include "common/failure.h" #include "common/file.h" #include "common/jack-client.h" #include "common/jack-port.h" #include "common/jack-ringbuffer.h" #include "common/memory.h" #include "common/network.h" #include "common/print.h" #define MAX_CHANNELS 32 #define PAYLOAD_SAMPLES 256 #define PAYLOAD_BYTES (PAYLOAD_SAMPLES*sizeof(f32)) typedef struct { int buffer_size; f32 *j_buffer; int fd; struct sockaddr_in address; int channels; jack_port_t *j_port[MAX_CHANNELS]; jack_ringbuffer_t *rb; pthread_t c_thread; int pipe[2]; char *name; } jackudp_t; static void jackudp_init(jackudp_t *d) { d->buffer_size = 4096; d->channels = 2; d->name = NULL; } typedef struct { u32 index; u16 channels; u16 frames; u8 data[PAYLOAD_BYTES]; } packet_t; void packet_ntoh(packet_t *p) { p->index = ntoh_i32(p->index); p->channels = ntoh_i16(p->channels); p->frames = ntoh_i16(p->frames); u8 *d = p->data; u32 i = p->channels * p->frames; while(i--) { ntoh32_buf(d, d); d += 4; } } void packet_hton(packet_t *p) { u8 *d = p->data; int i = p->channels * p->frames; while(i--){ hton32_buf(d, d); d += 4; } p->index = hton_i32(p->index); p->channels = hton_i16(p->channels); p->frames = hton_i16(p->frames); } void packet_sendto(int fd, packet_t *p, struct sockaddr_in address) { packet_hton(p); sendto_exactly(fd, (unsigned char *)p, sizeof(packet_t), address); } void packet_recv(int fd, packet_t *p, int flags) { recv_exactly(fd, (char *)p, sizeof(packet_t), flags); packet_ntoh(p); } /* Read data from udp port and write to ring buffer. */ void *jackudp_recv_thread(void *PTR) { jackudp_t *d = (jackudp_t *) PTR; packet_t p; int next_packet = -1; while(1) { packet_recv(d->fd, &p, 0); if(p.index != next_packet && next_packet != -1) { eprintf("jack.udp recv: out of order packet arrival (%d, %d)\n", next_packet, (int)p.index); FAILURE; } if(p.channels != d->channels) { eprintf("jack.udp recv: channel mismatch packet arrival (%d != %d)\n", p.channels, d->channels); FAILURE; } int bytes_available = (int) jack_ringbuffer_write_space(d->rb); if(PAYLOAD_BYTES > bytes_available) { eprintf("jack.udp recv: buffer overflow (%d > %d)\n", (int) PAYLOAD_BYTES, bytes_available); } else { jack_ringbuffer_write_exactly(d->rb, (char *) p.data, (size_t) PAYLOAD_BYTES); } next_packet = p.index + 1; next_packet %= INT32_MAX; } return NULL; } /* Write data from ring buffer to JACK output ports. */ int jackudp_recv (jack_nframes_t nframes, void *PTR) { jackudp_t *d = (jackudp_t *) PTR; if(nframes >= d->buffer_size) { eprintf("jack.udp recv: JACK buffer size exceeds limit\n"); return -1; } int i, j; float *out[MAX_CHANNELS]; for(i = 0; i < d->channels; i++) { out[i] = (float *) jack_port_get_buffer(d->j_port[i], nframes); } int nsamples = nframes * d->channels; int nbytes = nsamples * sizeof(f32); int bytes_available = (int) jack_ringbuffer_read_space(d->rb); if(nbytes > bytes_available) { eprintf("jack.udp recv: buffer underflow (%d > %d)\n", nbytes, bytes_available); for(i = 0; i < nframes; i++) { for(j = 0; j < d->channels; j++) { out[j][i] = (float) 0.0; } } } else { jack_ringbuffer_read_exactly(d->rb, (char *)d->j_buffer, nbytes); for(i = 0; i < nframes; i++) { for(j = 0; j < d->channels; j++) { out[j][i] = (float) d->j_buffer[(i * d->channels) + j]; } } } return 0; } /* Read data from ring buffer and write to udp port. Packets are always sent with a full payload. */ void *jackudp_send_thread(void *PTR) { jackudp_t *d = (jackudp_t *) PTR; packet_t p; p.index = 0; while(1) { jack_ringbuffer_wait_for_read(d->rb, PAYLOAD_BYTES, d->pipe[0]); p.index += 1; p.index %= INT32_MAX; p.channels = d->channels; p.frames = PAYLOAD_SAMPLES / d->channels; jack_ringbuffer_read_exactly(d->rb, (char *)&(p.data), PAYLOAD_BYTES); packet_sendto(d->fd, &p, d->address); } return NULL; } /* Write data from the JACK input ports to the ring buffer. */ int jackudp_send(jack_nframes_t n, void *PTR ) { jackudp_t *d = (jackudp_t *) PTR; float *in[MAX_CHANNELS]; int i, j; for(i = 0; i < d->channels; i++) { in[i] = (float *) jack_port_get_buffer(d->j_port[i], n); } for(i = 0; i < n; i++) { for(j = 0; j < d->channels; j++) { d->j_buffer[(i*d->channels)+j] = (f32) in[j][i]; } } int bytes_available = (int) jack_ringbuffer_write_space(d->rb); int bytes_to_write = n * sizeof(f32) * d->channels; if(bytes_to_write > bytes_available) { eprintf ("jack.udp send: buffer overflow error (UDP thread late)\n"); } else { jack_ringbuffer_write_exactly(d->rb, (char *) d->j_buffer, bytes_to_write ); } char b = 1; if(write(d->pipe[1], &b, 1)== -1) { eprintf ("jack.udp send: error writing communication pipe.\n"); FAILURE; } return 0; } void jackudp_usage (void) { eprintf("Usage: jack.udp [ options ] mode\n"); eprintf(" -b Set the ring buffer size in frames (default=4096).\n"); eprintf(" -c Set the client name (default=\"jack.udp-PID\").\n"); eprintf(" -p Set the port number (default=57160).\n"); eprintf(" -n Set the number of channels (default=2).\n"); eprintf(" -r Set the remote addrress to send to (default=\"127.0.0.1\").\n"); FAILURE; } int main (int argc, char **argv) { jackudp_t d; int c; int port_n = 57160; char *hostname = NULL; jackudp_init(&d); while((c = getopt(argc, argv, "b:hn:p:r:c:")) != -1) { switch(c) { case 'b': d.buffer_size = atoi(optarg); break; case 'c': d.name = optarg; break; case 'h': jackudp_usage (); break; case 'n': d.channels = atoi (optarg); break; case 'p': port_n = atoi (optarg); break; case 'r': hostname = optarg; break; default: eprintf ("jack.udp: Illegal option %c.\n", c); jackudp_usage (); break; } } if (optind != argc - 1) { jackudp_usage (); } if(d.channels < 1 || d.channels > MAX_CHANNELS) { eprintf("jack.udp: illegal number of channels: %d\n", d.channels); FAILURE; } int recv_mode = (strcmp(argv[optind], "recv") == 0); d.fd = socket_udp(0); if(recv_mode) { bind_inet(d.fd, NULL, port_n); } else { init_sockaddr_in(&(d.address), hostname ? hostname : "127.0.0.1", port_n); } d.buffer_size *= d.channels * sizeof(f32); d.j_buffer = xmalloc(d.buffer_size); d.rb = jack_ringbuffer_create(d.buffer_size); xpipe(d.pipe); jack_client_t *client = NULL; if(d.name) { client = jack_client_open(d.name,JackNullOption,NULL); } else { client = jack_client_unique("jack.udp"); } jack_set_error_function(jack_client_minimal_error_handler); jack_on_shutdown(client, jack_client_minimal_shutdown_handler, 0); jack_set_process_callback(client, recv_mode ? jackudp_recv : jackudp_send, &d); jack_port_make_standard(client, d.j_port, d.channels, recv_mode); jack_client_activate(client); pthread_create(&(d.c_thread), NULL, recv_mode ? jackudp_recv_thread : jackudp_send_thread, &d); pthread_join(d.c_thread, NULL); close(d.fd); jack_ringbuffer_free(d.rb); jack_client_close(client); close(d.pipe[0]); close(d.pipe[1]); free(d.j_buffer); return EXIT_SUCCESS; } jack-tools-20101210.orig/jack.play.text0000644000175000017500000000335311536646636016563 0ustar jonasjonasJACK.PLAY(1) ============ Rohan Drape NAME ---- jack.play - JACK Sound File Player SYNOPSIS -------- jack.play [options] sound-file... OPTIONS ------- *-b* : Set the disk buffer size in frames (default=4096). This value must be a power of two. If the JACK period size at any time exceeds this value the player will halt. *-c* : Set the sample rate conversion algorithm (default=2). Values are: SRC_SINC_BEST_QUALITY = 0, SRC_SINC_MEDIUM_QUALITY = 1, SRC_SINC_FASTEST = 2, SRC_ZERO_ORDER_HOLD = 3 and SRC_LINEAR = 4. *-i* : Set the initial disk seek in frames (default=0). *-m* : Set the minimal disk transfer size in frames (default=32). This is an optimization switch. *-n* : Set the client name (default=jack.play). *-q* : Set the frame size to request data from the ringbuffer (default=64). This is an optimization switch. *-r* : Set the resampling ratio multiplier (default=1.0). *-t* : Run in JACK transport aware mode. *-u* : Do not make client name unique by appending process identifier. DESCRIPTION ----------- jack.play is a light-weight JACK sound file player. It creates as many output ports as there are channels in the input file. It will connect to ports mentioned in the environment variable JACK_PLAY_CONNECT_TO which must include a %d pattern to indicate port number, otherwise it implements no connection logic, use jack.plumbing(1) instead. jack.play will read files in any format supported by libsndfile, and will resample to match the server sample rate using libsamplerate. AUTHOR ------ Written by Rohan Drape SEE ALSO -------- jackd(1), libsndfile(3) , libsamplerate(3) jack-tools-20101210.orig/jack.scope.text0000644000175000017500000000723211536646636016727 0ustar jonasjonasJACK.SCOPE(1) ============= Rohan Drape NAME ---- jack.scope - JACK Oscilloscope SYNOPSIS -------- jack.scope [options] OPTIONS ------- *-b* : Set the frame size of the data displayed by the scope (default=512). *-d* : Set the delay interval in milli-seconds between scope updates (default=100.0). *-f* : Request that a still image file of each frame be stored to the indicated directory. *-m* : Set the scope operating mode (default=signal). The operating modes are: signal and embed. *-n* : Set the number of channels, and therefore the number of JACK input ports (default=1). Multiple channels are superimposed, each channel is drawn in a distinct color. There is a compile time channel limit. *-p* : Set the port number to listen for OSC packets on (default=57140). *-w* : Set the scope size in pixels (default=512). The scope window is square. DESCRIPTION ----------- jack.scope is an oscilloscope for JACK under X11. jack.scope draws either a time domain signal trace or a self correlation trace. Multiple input channels are superimposed, each channel is drawn in a different color. jack.scope accepts OSC packets for interactive control of drawing parameters. The operating mode of jack.scope is set using *-m*. In signal mode jack.scope draws a time domain signal trace, in embed mode jack.scope draws a self correlation trace. The size of the jack.scope window is set using *-w*, the scope window is square. The window is of fixed size and has centered gravity. The time interval that is displayed is determined by the frame size, set using *-b*. The image refresh rate is determined by the delay interval, set using *-d*. Note that the interval is truncated to the nearest frame boundary and that the time taken to compose the image and blit to the screen is indeterminate. The number of JACK input ports that jack.scope creates and monitors is set using *-n*. Multiple channels are drawn in superimposition, each channel is drawn in a distinct color. In signal mode the trace is drawn in a style set using '/style'. In dot mode only the sample pixel in each column is drawn. In fill mode all pixels between the sample pixel and the zero pixel of each column are drawn. In line mode all pixels between the adjacent sample pixels of each column are drawn. In embed mode the trace is a self correlation signal with a sample delay set using '/embed'. The delayed sample is on the x-axis. The interpolation increment is set using '/incr', increment values less than one result in increasingly continuous trace paths. jack.scope can store the animation as a sequence of uncompressed ppm(5) image files. To request this use the *-f* option with the directory files should be written to as the argument. The OSC messages understood by jack.scope are given in the table below. Each command requires one argument of the indicated type. The last column gives the option that sets the same parameter. Command Description Argument Option ------- ----------- -------- ------ /mode drawing-mode string -m /style style string N/A /frames frame-size integer -b /delay refresh-interval float -d /embed embedding integer N/A /incr increment float N/A jack.scope implements no connection logic, use jack.plumbing(1) instead. REFERENCES ---------- Monro, G. and Pressing, J. ‘‘Sound Visualization Using Embedding: The Art and Science of Auditory Autocorrelation’’ CMJ, 22/2, 1998. AUTHOR ------ Rohan Drape SEE ALSO -------- jackd(1), X(7x), OSC(7) jack-tools-20101210.orig/jack.scope.c0000644000175000017500000003133711536646636016170 0ustar jonasjonas/***** jack.scope.c - (c) rohan drape, 1998-2006 *****/ #include #include #include #include #include #include #include #include #include #include #include #include "common/byte-order.h" #include "common/failure.h" #include "common/file.h" #include "common/img.h" #include "common/img-ppm.h" #include "common/jack-client.h" #include "common/jack-port.h" #include "common/memory.h" #include "common/network.h" #include "common/observe-signal.h" #include "common/osc.h" #include "common/print.h" #include "common/signal-copy.h" #include "common/signal-clip.h" #include "common/signal-interleave.h" #include "common/signal-interpolate.h" #include "common/ximg.h" typedef void (*draw_fn_t) (u8 *, i32, const f32 *, i32, i32, i32, void *); typedef bool (*control_fn_t) (const u8 *, i32, void *); #define SIGNAL_MODE 0 #define EMBED_MODE 1 #define MODE_COUNT 2 #define MAX_CHANNELS 4 struct scope { int channels; int window_size; int data_frames; int data_samples; int draw_frames; int data_location; float *data; float *share; jack_port_t *port[MAX_CHANNELS]; pthread_t draw_thread; pthread_t osc_thread; float fps; float delay_msec; int delay_frames; int delay_location; int mode; int pipe[2]; char *image_directory; int image_cnt; int fd; draw_fn_t child_draw[MODE_COUNT]; control_fn_t child_control[MODE_COUNT]; void *child_data[MODE_COUNT]; }; void jackscope_print(struct scope *d) { eprintf("Channels : %d\n", d->channels); eprintf("WindowSize : %d\n", d->window_size); eprintf("DataFrames : %d\n", d->data_frames); eprintf("DataSamples : %d\n", d->data_samples); eprintf("DrawFrames : %d\n", d->draw_frames); eprintf("DataLocation : %d\n", d->data_location); eprintf("FramesPerSecond : %f\n", d->fps); eprintf("DelayMSecs : %f\n", d->delay_msec); eprintf("DelayFrames : %d\n", d->delay_frames); eprintf("DelayLocation : %d\n", d->delay_location); eprintf("Mode : %d\n", d->mode); } #define OSC_PARSE_MSG(command,types) \ osc_parse_message(command, types, packet, packet_sz, o) struct embed { i32 embed; f32 incr; }; static void embed_draw_grid(u8 *image, i32 size) { u8 half[3] = {128, 128, 128}; u8 feint[3] = {192, 192, 192}; i32 i; for(i = 0; i < size; i += 3) { img_set_pixel(image, size, i, size/2, half); img_set_pixel(image, size, i, size/6, feint); img_set_pixel(image, size, i, size-(size/6), feint); } for(i = 0; i < size; i += 3) { img_set_pixel(image, size, size/2, i, half); img_set_pixel(image, size, size/6, i, feint); img_set_pixel(image, size, size-(size/6), i, feint); } } static void embed_draw_data(u8 *image, i32 size, const f32 *signal, i32 n, const u8 *color, i32 embed, f32 incr) { if(incr <= 0.0) { incr = 1.0; } f32 xindex = 0.0; f32 yindex = (f32) embed; while(yindex < n) { i32 x = signal_x_to_screen_x(signal_interpolate_safe(signal, n, xindex), size); i32 y = signal_y_to_screen_y(signal_interpolate_safe(signal, n, yindex), size); xindex += incr; yindex += incr; img_set_pixel(image, size, x, y, color); } } void * embed_init(void) { struct embed *e = malloc(sizeof(struct embed)); e->embed = 6; e->incr = 1.0; return e; } void embed_draw(u8 *image, i32 size, const f32 *signal, i32 f, i32 d, i32 c, void *PTR) { struct embed *e = (struct embed *) PTR; embed_draw_grid(image, size); i32 i; for(i = 0; i < c; i++) { u8 color[12] = {128, 32, 32, 32, 32, 128, 128, 224, 224, 224, 224, 128}; embed_draw_data(image, size, signal +(i * f), d, color +(i * 3), e->embed, e->incr); } } bool embed_control(const u8 *packet, i32 packet_sz, void *PTR) { struct embed *e = (struct embed *) PTR; osc_data_t o[1]; if(OSC_PARSE_MSG("/embed", ",i")) { e->embed = o[0].i; return true; } else if(OSC_PARSE_MSG("/incr", ",f")) { e->incr = o[0].f; return true; } return false; } #define DOT_STYLE 0 #define FILL_STYLE 1 #define LINE_STYLE 2 struct signal { i32 style; }; static void signal_draw_grid(u8 *image, i32 size) { i32 i; for(i = 0; i < size; i += 3) { u8 half[3] = {128, 128, 128}; u8 feint[3] = {192, 192, 192}; img_set_pixel(image, size, i, size/2, half); img_set_pixel(image, size, i, size/6, feint); img_set_pixel(image, size, i, size-(size/6), feint); } } static void signal_draw_data(u8 *image, i32 size, const f32 *signal, i32 n, const u8 *color, i32 style) { i32 i; f32 incr = (f32)n /(f32)size; f32 index = 0.0; for(i = 0; i < size; i++) { f32 s = signal_interpolate_safe(signal, n, index); i32 y = signal_y_to_screen_y(s, size); index += incr; img_set_pixel(image, size, i, y, color); if(style == DOT_STYLE) { img_set_pixel(image, size, i, y, color); } else if(style == FILL_STYLE) { i32 m = size / 2; i32 l = y > m ? m : y; i32 r = y > m ? y : m; i32 j; for(j = l; j < r; j++) { img_set_pixel(image, size, i, j, color); } } else if(style == LINE_STYLE){ f32 ss = signal_interpolate_safe(signal, n, index); i32 yy = signal_y_to_screen_y(ss, size); i32 l = yy > y ? y : yy; i32 r = yy > y ? yy : y; i32 j; for(j = l; j < r; j++) { img_set_pixel(image, size, i, j, color); } } } } static void signal_set_style(struct signal *s, const char *style) { if(strcmp("dot", style) == 0) { s->style = DOT_STYLE; } else if(strcmp("fill", style) == 0) { s->style = FILL_STYLE; } else if(strcmp("line", style) == 0) { s->style = LINE_STYLE; } else { eprintf("signal_set_style: illegal style, %s\n", style); } } void * signal_init(void) { struct signal *s = malloc(sizeof(struct signal)); s->style = DOT_STYLE; return s; } void signal_draw(u8 *image, i32 size, const f32 *signal, i32 f, i32 d, i32 c, void *PTR) { struct signal *s = (struct signal *) PTR; signal_draw_grid(image, size); i32 i; for(i = 0; i < c; i++) { u8 color[12] = {128, 32, 32, 32, 32, 128, 128, 224, 224, 224, 224, 128}; signal_draw_data(image, size, signal +(i * f), d, color +(i * 3), s->style); } } bool signal_control(const u8 *packet, i32 packet_sz, void *PTR) { struct signal *s = (struct signal *) PTR; osc_data_t o[1]; if(OSC_PARSE_MSG("/style", ",s")) { signal_set_style(s, o[0].s); return true; } return false; } void set_mode(struct scope *d, const char *mode) { if(strncmp("signal", mode, 6)== 0) { d->mode = SIGNAL_MODE; } else if(strncmp("embed", mode, 5)== 0) { d->mode = EMBED_MODE; } else { eprintf("jack.scope: illegal mode, %s\n", mode); } } void * jackscope_osc_thread_procedure(void *PTR) { struct scope *d = (struct scope *) PTR; while(1) { const int packet_extent = 32; uint8_t packet[packet_extent]; int packet_sz = xrecv(d->fd, packet, 32, 0); osc_data_t o[1]; if(!(d->child_control[0](packet, packet_sz, d->child_data[0])|| d->child_control[1](packet, packet_sz, d->child_data[1]))) { if(OSC_PARSE_MSG("/frames", ",i")) { d->draw_frames = o[0].i > d->data_frames ? d->data_frames : o[0].i; } else if(OSC_PARSE_MSG("/mode", ",s")) { set_mode(d, o[0].s); } else if(OSC_PARSE_MSG("/delay", ",f")) { d->delay_msec = o[0].f; d->delay_frames = floorf(( d->delay_msec / 1000.0)* d->fps); } else { eprintf("jack.scope: dropped packet: %8s\n", packet); } } } return NULL; } /* The data is channel separated into a local buffer, 'local'. The image data 'image' is cleared and a user selected drawing procedure is invoked. The draw procedure must accept any combination of window size and frame count, and any number of channels. */ void * jackscope_draw_thread_procedure(void *PTR) { struct scope *d = (struct scope *) PTR; Ximg_t *x = ximg_open(d->window_size, d->window_size, "jack.scope"); int image_n = d->window_size * d->window_size * 3; uint8_t *image = xmalloc(image_n); float *local = xmalloc(d->data_samples * sizeof(float)); while(! observe_end_of_process ()) { char b; xread(d->pipe[0], &b, 1); signal_uninterleave(local, d->share, d->data_frames, d->channels); signal_clip(local, d->data_frames * d->channels, -1.0, 1.0); memset(image, 255, image_n); d->child_draw[d->mode](image, d->window_size, local, d->data_frames, d->draw_frames, d->channels, d->child_data[d->mode]); ximg_blit(x, image); if(d->image_directory) { char name[256]; snprintf(name, 256, "%s/jack.scope.%06d.ppm", d->image_directory, d->image_cnt); img_write_ppm_file(image, d->window_size, d->window_size, name); } d->image_cnt++; } ximg_close(x); free(image); free(local); return NULL; } /* Accumulate the input signal at `d->data'. When an image is due to be displayed copy the accumulator into `d->share' and poke the drawing routine. */ int jackscope_process(jack_nframes_t nframes, void *PTR) { struct scope *d = (struct scope *) PTR; float *in[MAX_CHANNELS]; int i; for(i = 0; i < d->channels; i++) { in[i] = (float *) jack_port_get_buffer(d->port[i], nframes); } int k = d->data_location; int l = d->delay_location; for(i = 0; i < nframes; i++) { int j; for(j = 0; j < d->channels; j++) { d->data[k++] = (float) in[j][i]; if(k >= d->data_samples) { k = 0; } } l++; if(l >= d->delay_frames) { signal_copy_circular(d->share, d->data, d->data_samples, k); l = 0; char b = 1; xwrite(d->pipe[1], &b, 1); } } d->data_location = k; d->delay_location = l; return 0; } void jackscope_usage (void) { eprintf("Usage: jack.scope [ options ] sound-file\n"); eprintf(" -b Scope size in frames (default=512).\n"); eprintf(" -d Delay time in ms between scope udpates (default=100.0).\n"); eprintf(" -f Request images be stored at location (default=NULL).\n"); eprintf(" -m Scope operating mode (default=signal).\n"); eprintf(" -n Number of channels (default=1).\n"); eprintf(" -p Port number to listen for OSC packets (default=57140).\n"); eprintf(" -w Scope size in pixels (default=512).\n"); FAILURE; } int main(int argc, char **argv) { observe_signals (); struct scope d; d.window_size = 512; d.data_frames = 512; d.data_samples = 0; d.data_location = 0; d.draw_frames = 0; d.delay_msec = 100.0; d.delay_location = 0; d.channels = 1; d.mode = SIGNAL_MODE; d.child_data[0] = signal_init (); d.child_draw[0] = signal_draw; d.child_control[0] = signal_control; d.child_data[1] = embed_init (); d.child_draw[1] = embed_draw; d.child_control[1] = embed_control; d.image_directory = NULL; d.image_cnt = 0; int port_n = 57140; int c; while ((c = getopt (argc, argv, "b:d:e:f:hi:m:n:s:w:")) != -1) { switch (c) { case 'b': d.data_frames = strtol(optarg, NULL, 0); break; case 'd': d.delay_msec = strtod(optarg, NULL); break; case 'f': d.image_directory = optarg; break; case 'h': jackscope_usage (); break; case 'm': set_mode(&d, optarg); break; case 'n': d.channels = strtol(optarg, NULL, 0); if (d.channels > MAX_CHANNELS) { eprintf("illegal channel count: %d", d.channels); FAILURE; } break; case 'p': port_n = strtol(optarg, NULL, 0); break; case 'w': d.window_size = strtol(optarg, NULL, 0); break; default: eprintf("jack.scope: illegal option, %c\n", (char)c); jackscope_usage (); break; } } d.draw_frames = d.data_frames; d.data_samples = d.data_frames * d.channels; d.data = xmalloc(d.data_samples * sizeof (float)); d.share = xmalloc(d.data_samples * sizeof (float)); d.fd = socket_udp(0); bind_inet(d.fd, NULL, port_n); xpipe(d.pipe); pthread_create(&(d.osc_thread), NULL, jackscope_osc_thread_procedure, &d); pthread_create(&(d.draw_thread), NULL, jackscope_draw_thread_procedure, &d); jack_client_t *client = jack_client_unique("jack.scope"); jack_set_process_callback(client, jackscope_process, &d); jack_set_error_function(jack_client_minimal_error_handler); jack_on_shutdown(client, jack_client_minimal_shutdown_handler, 0); d.fps = (float) jack_get_sample_rate(client); d.delay_frames = floorf(( d.delay_msec / 1000.0)* d.fps); jack_port_make_standard(client, d.port, d.channels, 0); jack_client_activate(client); pthread_join(d.draw_thread, NULL); jack_client_close (client); close(d.pipe[0]); close(d.pipe[1]); free(d.data); free(d.share); return EXIT_SUCCESS; } jack-tools-20101210.orig/autogen.sh0000644000175000017500000000063711536646636016001 0ustar jonasjonas#!/bin/sh libtoolize --force 2>&1 | sed '/^You should/d' || { echo "libtool failed, exiting..." exit 1 } aclocal $ACLOCAL_FLAGS || { echo "aclocal \$ACLOCAL_FLAGS where \$ACLOCAL_FLAGS= failed, exiting..." exit 1 } automake --add-missing --foreign || { echo "automake --add-missing --foreign failed, exiting..." exit 1 } autoconf || { echo "autoconf failed, exiting..." exit 1 } jack-tools-20101210.orig/jack.osc.text0000644000175000017500000001371311536646636016403 0ustar jonasjonasJACK.OSC(1) =========== Rohan Drape NAME ---- jack.osc - JACK Transport Publication Daemon SYNOPSIS -------- jack.osc [options] OPTIONS ------- *-c* : Set the drift correction interval in periods (default=64). *-p* : Set the port number (default=57130). DESCRIPTION ----------- jack.osc publishes the transport state of the local JACK server as OSC packets over a UDP connection. jack.osc allows any OSC enabled application to act as a JACK transport client, receiving sample accurate pulse stream timing data, and monitoring and initiating transport state change. Clients request to receive timing and change notification packets by sending a "request notification" packet, '/receive', to the jack.osc server. This packet has the form /receive category where category is a bit mask that indicates what categories of notification packets are requested. The bit locations are: Category Mask -------- ---- REQUEST_TICK 0x0000001 REQUEST_PULSE 0x0000002 REQUEST_CORRECTION 0x0000004 REQUEST_TRANSPORT 0x0000008 REQUEST_ALL 0xFFFFFFF Clients request notification messages to be sent to an address that is not that of the packet that requests the notification by sending a "request notification at" packet, '/receive_at'. This packet has the form /receive_at category port-number host-name where category is as for '/receive' and where port-number and host-name give the address that notification should be sent to. Once a client is registered subsequent '/receive' and '/receive_at' messages edit the category value for that client. To delete the client from the register send a request with a category value of negative one. After requesting notification the client will receive all relevant timing packets sent by the server. All jack.osc timing packets are sent at the start of a JACK period as OSC message and have the same shape: tag ntp utc frm arg... where tag is the command name, and ntp, utc and frm are time stamps that indicate the same time point, the start of the JACK period when the packet was sent. ntp is an unsigned 64bit integer NTP value. utc is a double precision real valued representation of the UTC time. frm is a signed 64bit integer frame counter the absolute value of which is not defined but which increments synchronously with the ntp and utc time stamps. arg... is the set of tag specific arguments. The timing packets sent by jack.osc are: /pulse ntp utc frm p-ntp p-utc p-frm pulse : Pulse Location. This packet indicates that the nearest frame to the integer pulse pulse occurs at the time given by the time stamps p-ntp, p-utc and p-frm. The pulse number is one based. This packet is sent at the start of the JACK period in which the integer pulse will occur. This packet is not sent if the transport is stopped. This packet is sent before the '/tick' packet for the same period. /tick ntp utc frm frame pulse : Period Tick. This packet is sent once per JACK period. The integer value frame is the transport location in frames, the double precision real value pulse is the transport location in pulses. The pulse value is read from an accumulator and is approximate only, the accumulator is corrected at each integer pulse location. /drift ntp utc frm ntp-dif utc-dif : Drift Correction. This packet is sent whenever the clock drift correction is run. The frequency of this is set by the *-c* option to the jack.osc server. The integer value ntp-dif is the NTP form of the corrected drift value and utc-dif the UTC form. Since JACK is a sample clock there is no frame drift value. The state change packets sent by jack.osc are: /transport ntp utc frm fps ppm ppc pt state : Transport state change. This packet is sent whenever the JACK transport changes. The double precision real value fps is the sample rate in frames per second. The double precision real value ppm is the tempo in pulses per minute. The double precision real value ppc is the measure length in pulses per cycle. The double precision real value pt is the pulse type. The integer value state is zero if the transport has stopped and one if it has started. See also the '/status' message described below. Clients can request the current frame and pulse values by sending a '/current' packet, which requires no argument. The replies with a '/current.reply' packet, which has the same form as a '/tick' packet. The precise interpretation of packets acquired in this manner is problematic. Clients request a status packet by sending a "request status" packet, '/status', which requires no argument. The server replies immediately with a status reply packet, '/status.reply'. The status packet is an OSC message and is not timestamped. It has the shape: /status.reply fps ppm ppc pt state where the argument values are as described for the '/transport' message. It is intended that a client will request a single status packet before requesting notification for all subsequent state changes. Clients initiate a change in transport roll state by sending a "request transport operation" packet, '/start' or '/stop' to the jack.osc server. Neither requires an argument. Clients initiate a change in transport location by sending a "request locate operation" packet, '/locate', to the jack.osc server. It has the shape: /locate location where the single precision real value location is the requested transport location in seconds. Clients can connect and disconnect ports by sending '/connect' and '/disconnect' messages to the jack.osc server. Both have the shape: /[dis]connect left right jack.osc implements only a subset of the OSC protocol. In particular it does not implement the patten matching rules and does not implement a scheduler for incoming messages. jack.osc drops all unrecognized incoming packets. AUTHOR ------ Rohan Drape SEE ALSO -------- jackd(1), OSC(7)