535 lines
16 KiB
C
535 lines
16 KiB
C
/*
|
|
OpenLase - a realtime laser graphics toolkit
|
|
|
|
Copyright (C) 2009-2011 Hector Martin "marcan" <hector@marcansoft.com>
|
|
|
|
This program is free software; you can redistribute it and/or modify
|
|
it under the terms of the GNU General Public License as published by
|
|
the Free Software Foundation, either version 2 or version 3.
|
|
|
|
This program is distributed in the hope that it will be useful,
|
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
GNU General Public License for more details.
|
|
|
|
You should have received a copy of the GNU General Public License
|
|
along with this program; if not, write to the Free Software
|
|
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
|
*/
|
|
|
|
/*
|
|
Simple bare-bones ILDA file player. Works directly on JACK. libol does (now)
|
|
have ILDA loading and display, but that goes through quite a bit of processing.
|
|
This bare-bones player should accurately display ILDA files at the target sample
|
|
rate or, if slower, performs simple resampling. Thus, it works well for things
|
|
like the ILDA test pattern.
|
|
|
|
Oh, and it also tries to watch the input file and reload if it changes. Nice
|
|
if you make a shell loop to convert SVG to ILD every time the SVG changes (but
|
|
use a temp file and rename the ILD at the end, otherwise this breaks horribly
|
|
on partial files). Then you can have Inkscape open and every time you save
|
|
the laser image updates.
|
|
*/
|
|
|
|
#define _BSD_SOURCE
|
|
|
|
#include <stdio.h>
|
|
#include <errno.h>
|
|
#include <unistd.h>
|
|
#include <string.h>
|
|
#include <stdlib.h>
|
|
#include <jack/jack.h>
|
|
|
|
#include <sys/types.h>
|
|
#include <sys/param.h>
|
|
#include <sys/stat.h>
|
|
|
|
#if BYTE_ORDER == LITTLE_ENDIAN
|
|
static inline uint16_t swapshort(uint16_t v) {
|
|
return (v >> 8) | (v << 8);
|
|
}
|
|
# define MAGIC 0x41444C49
|
|
#else
|
|
static inline uint16_t swapshort(uint16_t v) {
|
|
return v;
|
|
}
|
|
# define MAGIC 0x494C4441
|
|
#endif
|
|
|
|
#include <stdint.h>
|
|
|
|
typedef jack_default_audio_sample_t sample_t;
|
|
typedef jack_nframes_t nframes_t;
|
|
|
|
jack_port_t *out_x;
|
|
jack_port_t *out_y;
|
|
jack_port_t *out_z;
|
|
jack_port_t *out_r;
|
|
jack_port_t *out_g;
|
|
jack_port_t *out_b;
|
|
jack_port_t *out_w;
|
|
|
|
nframes_t rate;
|
|
nframes_t divider = 1;
|
|
|
|
nframes_t pointrate = 30000;
|
|
|
|
int scale = 0;
|
|
|
|
sample_t size = 1.0;
|
|
|
|
struct ilda_hdr {
|
|
uint32_t magic;
|
|
uint8_t pad1[3];
|
|
uint8_t format;
|
|
char name[8];
|
|
char company[8];
|
|
uint16_t count;
|
|
uint16_t frameno;
|
|
uint16_t framecount;
|
|
uint8_t scanner;
|
|
uint8_t pad2;
|
|
} __attribute__((packed));
|
|
|
|
struct color {
|
|
uint8_t r, g, b;
|
|
};
|
|
|
|
#define BLANK 0x40
|
|
#define LAST 0x80
|
|
|
|
struct icoord3d {
|
|
int16_t x;
|
|
int16_t y;
|
|
int16_t z;
|
|
uint8_t state;
|
|
uint8_t color;
|
|
} __attribute__((packed));
|
|
|
|
struct icoord2d {
|
|
int16_t x;
|
|
int16_t y;
|
|
uint8_t state;
|
|
uint8_t color;
|
|
} __attribute__((packed));
|
|
|
|
struct coord3d {
|
|
int16_t x;
|
|
int16_t y;
|
|
int16_t z;
|
|
uint8_t state;
|
|
struct color color;
|
|
};
|
|
|
|
struct frame {
|
|
struct coord3d *points;
|
|
int position;
|
|
int count;
|
|
};
|
|
|
|
#define FRAMEBUFS 10
|
|
struct frame frames[FRAMEBUFS];
|
|
|
|
struct frame * volatile curframe;
|
|
struct frame *curdframe;
|
|
|
|
int subpos;
|
|
|
|
struct color palette[256] = {
|
|
{ 0, 0, 0}, {255, 255, 255}, {255, 0, 0}, {255, 255, 0},
|
|
{ 0, 255, 0}, { 0, 255, 255}, { 0, 0, 255}, {255, 0, 255},
|
|
{255, 128, 128}, {255, 140, 128}, {255, 151, 128}, {255, 163, 128},
|
|
{255, 174, 128}, {255, 186, 128}, {255, 197, 128}, {255, 209, 128},
|
|
{255, 220, 128}, {255, 232, 128}, {255, 243, 128}, {255, 255, 128},
|
|
{243, 255, 128}, {232, 255, 128}, {220, 255, 128}, {209, 255, 128},
|
|
{197, 255, 128}, {186, 255, 128}, {174, 255, 128}, {163, 255, 128},
|
|
{151, 255, 128}, {140, 255, 128}, {128, 255, 128}, {128, 255, 140},
|
|
{128, 255, 151}, {128, 255, 163}, {128, 255, 174}, {128, 255, 186},
|
|
{128, 255, 197}, {128, 255, 209}, {128, 255, 220}, {128, 255, 232},
|
|
{128, 255, 243}, {128, 255, 255}, {128, 243, 255}, {128, 232, 255},
|
|
{128, 220, 255}, {128, 209, 255}, {128, 197, 255}, {128, 186, 255},
|
|
{128, 174, 255}, {128, 163, 255}, {128, 151, 255}, {128, 140, 255},
|
|
{128, 128, 255}, {140, 128, 255}, {151, 128, 255}, {163, 128, 255},
|
|
{174, 128, 255}, {186, 128, 255}, {197, 128, 255}, {209, 128, 255},
|
|
{220, 128, 255}, {232, 128, 255}, {243, 128, 255}, {255, 128, 255},
|
|
{255, 128, 243}, {255, 128, 232}, {255, 128, 220}, {255, 128, 209},
|
|
{255, 128, 197}, {255, 128, 186}, {255, 128, 174}, {255, 128, 163},
|
|
{255, 128, 151}, {255, 128, 140}, {255, 0, 0}, {255, 23, 0},
|
|
{255, 46, 0}, {255, 70, 0}, {255, 93, 0}, {255, 116, 0},
|
|
{255, 139, 0}, {255, 162, 0}, {255, 185, 0}, {255, 209, 0},
|
|
{255, 232, 0}, {255, 255, 0}, {232, 255, 0}, {209, 255, 0},
|
|
{185, 255, 0}, {162, 255, 0}, {139, 255, 0}, {116, 255, 0},
|
|
{ 93, 255, 0}, { 70, 255, 0}, { 46, 255, 0}, { 23, 255, 0},
|
|
{ 0, 255, 0}, { 0, 255, 23}, { 0, 255, 46}, { 0, 255, 70},
|
|
{ 0, 255, 93}, { 0, 255, 116}, { 0, 255, 139}, { 0, 255, 162},
|
|
{ 0, 255, 185}, { 0, 255, 209}, { 0, 255, 232}, { 0, 255, 255},
|
|
{ 0, 232, 255}, { 0, 209, 255}, { 0, 185, 255}, { 0, 162, 255},
|
|
{ 0, 139, 255}, { 0, 116, 255}, { 0, 93, 255}, { 0, 70, 255},
|
|
{ 0, 46, 255}, { 0, 23, 255}, { 0, 0, 255}, { 23, 0, 255},
|
|
{ 46, 0, 255}, { 70, 0, 255}, { 93, 0, 255}, {116, 0, 255},
|
|
{139, 0, 255}, {162, 0, 255}, {185, 0, 255}, {209, 0, 255},
|
|
{232, 0, 255}, {255, 0, 255}, {255, 0, 232}, {255, 0, 209},
|
|
{255, 0, 185}, {255, 0, 162}, {255, 0, 139}, {255, 0, 116},
|
|
{255, 0, 93}, {255, 0, 70}, {255, 0, 46}, {255, 0, 23},
|
|
{128, 0, 0}, {128, 12, 0}, {128, 23, 0}, {128, 35, 0},
|
|
{128, 47, 0}, {128, 58, 0}, {128, 70, 0}, {128, 81, 0},
|
|
{128, 93, 0}, {128, 105, 0}, {128, 116, 0}, {128, 128, 0},
|
|
{116, 128, 0}, {105, 128, 0}, { 93, 128, 0}, { 81, 128, 0},
|
|
{ 70, 128, 0}, { 58, 128, 0}, { 47, 128, 0}, { 35, 128, 0},
|
|
{ 23, 128, 0}, { 12, 128, 0}, { 0, 128, 0}, { 0, 128, 12},
|
|
{ 0, 128, 23}, { 0, 128, 35}, { 0, 128, 47}, { 0, 128, 58},
|
|
{ 0, 128, 70}, { 0, 128, 81}, { 0, 128, 93}, { 0, 128, 105},
|
|
{ 0, 128, 116}, { 0, 128, 128}, { 0, 116, 128}, { 0, 105, 128},
|
|
{ 0, 93, 128}, { 0, 81, 128}, { 0, 70, 128}, { 0, 58, 128},
|
|
{ 0, 47, 128}, { 0, 35, 128}, { 0, 23, 128}, { 0, 12, 128},
|
|
{ 0, 0, 128}, { 12, 0, 128}, { 23, 0, 128}, { 35, 0, 128},
|
|
{ 47, 0, 128}, { 58, 0, 128}, { 70, 0, 128}, { 81, 0, 128},
|
|
{ 93, 0, 128}, {105, 0, 128}, {116, 0, 128}, {128, 0, 128},
|
|
{128, 0, 116}, {128, 0, 105}, {128, 0, 93}, {128, 0, 81},
|
|
{128, 0, 70}, {128, 0, 58}, {128, 0, 47}, {128, 0, 35},
|
|
{128, 0, 23}, {128, 0, 12}, {255, 192, 192}, {255, 64, 64},
|
|
{192, 0, 0}, { 64, 0, 0}, {255, 255, 192}, {255, 255, 64},
|
|
{192, 192, 0}, { 64, 64, 0}, {192, 255, 192}, { 64, 255, 64},
|
|
{ 0, 192, 0}, { 0, 64, 0}, {192, 255, 255}, { 64, 255, 255},
|
|
{ 0, 192, 192}, { 0, 64, 64}, {192, 192, 255}, { 64, 64, 255},
|
|
{ 0, 0, 192}, { 0, 0, 64}, {255, 192, 255}, {255, 64, 255},
|
|
{192, 0, 192}, { 64, 0, 64}, {255, 96, 96}, {255, 255, 255},
|
|
{245, 245, 245}, {235, 235, 235}, {224, 224, 224}, {213, 213, 213},
|
|
{203, 203, 203}, {192, 192, 192}, {181, 181, 181}, {171, 171, 171},
|
|
{160, 160, 160}, {149, 149, 149}, {139, 139, 139}, {128, 128, 128},
|
|
{117, 117, 117}, {107, 107, 107}, { 96, 96, 96}, { 85, 85, 85},
|
|
{ 75, 75, 75}, { 64, 64, 64}, { 53, 53, 53}, { 43, 43, 43},
|
|
{ 32, 32, 32}, { 21, 21, 21}, { 11, 11, 11}, { 0, 0, 0},
|
|
};
|
|
|
|
#define MONOCHROME
|
|
|
|
int process (nframes_t nframes, void *arg)
|
|
{
|
|
struct frame *frame = curdframe;
|
|
|
|
sample_t *o_x = (sample_t *) jack_port_get_buffer (out_x, nframes);
|
|
sample_t *o_y = (sample_t *) jack_port_get_buffer (out_y, nframes);
|
|
sample_t *o_z = (sample_t *) jack_port_get_buffer (out_z, nframes);
|
|
sample_t *o_r = (sample_t *) jack_port_get_buffer (out_r, nframes);
|
|
sample_t *o_g = (sample_t *) jack_port_get_buffer (out_g, nframes);
|
|
sample_t *o_b = (sample_t *) jack_port_get_buffer (out_b, nframes);
|
|
sample_t *o_w = (sample_t *) jack_port_get_buffer (out_w, nframes);
|
|
|
|
nframes_t frm;
|
|
for (frm = 0; frm < nframes; frm++) {
|
|
struct coord3d *c = &frame->points[frame->position];
|
|
*o_x++ = (c->x / 32768.0) * size;
|
|
*o_y++ = (c->y / 32768.0) * size;
|
|
*o_z++ = (c->z / 32768.0) * size;
|
|
if(c->state & BLANK) {
|
|
*o_r++ = *o_g++ = *o_b++ = *o_w++ = 0.0;
|
|
} else {
|
|
#ifdef MONOCHROME
|
|
*o_r++ = *o_g++ = *o_b++ = *o_w++ = 1.0;
|
|
#else
|
|
*o_r = c->color.r / 255.0;
|
|
*o_g = c->color.g / 255.0;
|
|
*o_b = c->color.b / 255.0;
|
|
*o_w++ = 0.333 * *o_r++ + 0.333 * *o_g++ + 0.333 * *o_b++;
|
|
//*o_w++ = 0.2126 * *o_r++ + 0.7152 * *o_g++ + 0.0722 * *o_b++;
|
|
#endif
|
|
}
|
|
subpos++;
|
|
if (subpos == divider) {
|
|
subpos = 0;
|
|
if (c->state & LAST)
|
|
frame->position = 0;
|
|
else
|
|
frame->position = (frame->position + 1) % frame->count;
|
|
}
|
|
if (frame->position == 0) {
|
|
if(curdframe != curframe) {
|
|
printf("Frame update\n");
|
|
curdframe = curframe;
|
|
}
|
|
}
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
int bufsize (nframes_t nframes, void *arg)
|
|
{
|
|
printf ("the maximum buffer size is now %u\n", nframes);
|
|
return 0;
|
|
}
|
|
|
|
int srate (nframes_t nframes, void *arg)
|
|
{
|
|
rate = nframes;
|
|
printf ("Playing back at %u pps\n", rate / divider);
|
|
return 0;
|
|
}
|
|
|
|
void jack_shutdown (void *arg)
|
|
{
|
|
exit (1);
|
|
}
|
|
|
|
int clamp(int v)
|
|
{
|
|
if(v > 32767) {
|
|
printf("warn: val is %d\n", v);
|
|
return 32767;
|
|
}
|
|
if(v < -32768) {
|
|
printf("warn: val is %d\n", v);
|
|
return -32768;
|
|
}
|
|
return v;
|
|
}
|
|
|
|
int loadild(const char *fname, struct frame *frame)
|
|
{
|
|
int i;
|
|
FILE *ild = fopen(fname, "rb");
|
|
|
|
int minx = 65536, maxx = -65536;
|
|
int miny = 65536, maxy = -65536;
|
|
int minz = 65536, maxz = -65536;
|
|
|
|
if (!ild) {
|
|
fprintf(stderr, "cannot open %s\n", fname);
|
|
return -1;
|
|
}
|
|
|
|
frame->count = 0;
|
|
memset(frame, 0, sizeof(struct frame));
|
|
|
|
while(!frame->count) {
|
|
|
|
struct ilda_hdr hdr;
|
|
|
|
if (fread(&hdr, sizeof(hdr), 1, ild) != 1) {
|
|
fprintf(stderr, "error while reading file\n");
|
|
return -1;
|
|
}
|
|
|
|
if (hdr.magic != MAGIC) {
|
|
fprintf(stderr, "Invalid magic 0x%08x\n", hdr.magic);
|
|
return -1;
|
|
}
|
|
|
|
hdr.count = swapshort(hdr.count);
|
|
hdr.frameno = swapshort(hdr.frameno);
|
|
hdr.framecount = swapshort(hdr.framecount);
|
|
|
|
switch (hdr.format) {
|
|
case 0:
|
|
printf("Got 3D frame, %d points\n", hdr.count);
|
|
frame->points = malloc(sizeof(struct coord3d) * hdr.count);
|
|
struct icoord3d *tmp3d = malloc(sizeof(struct icoord3d) * hdr.count);
|
|
if (fread(tmp3d, sizeof(struct icoord3d), hdr.count, ild) != hdr.count) {
|
|
fprintf(stderr, "error while reading frame\n");
|
|
return -1;
|
|
}
|
|
for(i=0; i<hdr.count; i++) {
|
|
frame->points[i].x = swapshort(tmp3d[i].x);
|
|
frame->points[i].y = swapshort(tmp3d[i].y);
|
|
frame->points[i].z = swapshort(tmp3d[i].z);
|
|
frame->points[i].state = tmp3d[i].state;
|
|
frame->points[i].color = palette[tmp3d[i].color];
|
|
}
|
|
free(tmp3d);
|
|
frame->count = hdr.count;
|
|
break;
|
|
case 1:
|
|
printf("Got 2D frame, %d points\n", hdr.count);
|
|
frame->points = malloc(sizeof(struct coord3d) * hdr.count);
|
|
struct icoord2d *tmp2d = malloc(sizeof(struct icoord2d) * hdr.count);
|
|
if (fread(tmp2d, sizeof(struct icoord2d), hdr.count, ild) != hdr.count) {
|
|
fprintf(stderr, "error while reading frame\n");
|
|
return -1;
|
|
}
|
|
for(i=0; i<hdr.count; i++) {
|
|
frame->points[i].x = swapshort(tmp2d[i].x);
|
|
frame->points[i].y = swapshort(tmp2d[i].y);
|
|
frame->points[i].z = 0;
|
|
frame->points[i].state = tmp2d[i].state;
|
|
frame->points[i].color = palette[tmp2d[i].color];
|
|
}
|
|
free(tmp2d);
|
|
frame->count = hdr.count;
|
|
break;
|
|
case 2:
|
|
printf("Got color palette section, %d entries\n", hdr.count);
|
|
if (fread(palette, 3, hdr.count, ild) != hdr.count) {
|
|
fprintf(stderr, "error while reading palette\n");
|
|
return -1;
|
|
}
|
|
break;
|
|
}
|
|
}
|
|
|
|
fclose(ild);
|
|
|
|
if (scale) {
|
|
for(i=0; i<frame->count; i++) {
|
|
if(frame->points[i].x > maxx)
|
|
maxx = frame->points[i].x;
|
|
if(frame->points[i].y > maxy)
|
|
maxy = frame->points[i].y;
|
|
if(frame->points[i].z > maxz)
|
|
maxz = frame->points[i].z;
|
|
if(frame->points[i].x < minx)
|
|
minx = frame->points[i].x;
|
|
if(frame->points[i].y < miny)
|
|
miny = frame->points[i].y;
|
|
if(frame->points[i].z < minz)
|
|
minz = frame->points[i].z;
|
|
}
|
|
|
|
int dx, dy, dz, dmax;
|
|
int cx, cy, cz;
|
|
dx = maxx-minx;
|
|
dy = maxy-miny;
|
|
dz = maxz-minz;
|
|
cx = (minx+maxx)/2;
|
|
cy = (miny+maxy)/2;
|
|
cz = (minz+maxz)/2;
|
|
|
|
dmax = dx;
|
|
if (dy > dmax)
|
|
dmax = dy;
|
|
if (dz > dmax)
|
|
dmax = dz;
|
|
|
|
printf("X range: %d .. %d (%d) (c:%d)\n", minx, maxx, dx, cx);
|
|
printf("Y range: %d .. %d (%d) (c:%d)\n", miny, maxy, dy, cy);
|
|
printf("Z range: %d .. %d (%d) (c:%d)\n", minz, maxz, dz, cz);
|
|
|
|
printf("Scaling by %d\n", dmax);
|
|
|
|
for(i=0; i<frame->count; i++) {
|
|
frame->points[i].x -= cx;
|
|
frame->points[i].y -= cy;
|
|
frame->points[i].z -= cz;
|
|
|
|
frame->points[i].x = clamp((int)frame->points[i].x * 32767 / (dmax/2+1));
|
|
frame->points[i].y = clamp((int)frame->points[i].y * 32767 / (dmax/2+1));
|
|
frame->points[i].z = clamp((int)frame->points[i].z * 32767 / (dmax/2+1));
|
|
}
|
|
|
|
}
|
|
|
|
printf("Resampling %d -> %d\n", pointrate, rate);
|
|
|
|
if (pointrate > rate) {
|
|
printf("Downsampling not implemented!\n");
|
|
return -1;
|
|
}
|
|
|
|
int ocount = frame->count * rate / pointrate;
|
|
struct coord3d *opoints = malloc(sizeof(struct coord3d) * ocount);
|
|
|
|
float mul = (float)frame->count / (float)ocount;
|
|
|
|
for(i=0; i<ocount; i++) {
|
|
float pos = i*mul;
|
|
int lpos = pos;
|
|
int rpos = pos+1;
|
|
if (rpos >= frame->count)
|
|
rpos = lpos;
|
|
float off = pos - lpos;
|
|
opoints[i].x = frame->points[lpos].x * (1-off) + frame->points[rpos].x * off;
|
|
opoints[i].y = frame->points[lpos].y * (1-off) + frame->points[rpos].y * off;
|
|
opoints[i].z = frame->points[lpos].z * (1-off) + frame->points[rpos].z * off;
|
|
opoints[i].color.r = frame->points[lpos].color.r * (1-off) + frame->points[rpos].color.r * off;
|
|
opoints[i].color.g = frame->points[lpos].color.g * (1-off) + frame->points[rpos].color.g * off;
|
|
opoints[i].color.b = frame->points[lpos].color.b * (1-off) + frame->points[rpos].color.b * off;
|
|
opoints[i].state = frame->points[lpos].state | frame->points[rpos].state;
|
|
}
|
|
|
|
free(frame->points);
|
|
frame->points = opoints;
|
|
frame->count = ocount;
|
|
|
|
return 0;
|
|
}
|
|
|
|
int main (int argc, char *argv[])
|
|
{
|
|
int frameno = 0;
|
|
char **argvp = &argv[1];
|
|
char *fname;
|
|
jack_client_t *client;
|
|
static const char jack_client_name[] = "playilda";
|
|
jack_status_t jack_status;
|
|
struct stat st1, st2;
|
|
|
|
if (argc > 2 && !strcmp(argvp[0],"-s")) {
|
|
scale = 1;
|
|
argc--;
|
|
argvp++;
|
|
}
|
|
|
|
if (argc < 2) {
|
|
fprintf(stderr, "usage: %s [-s] filename.ild [rate]\n", argv[0]);
|
|
return 1;
|
|
}
|
|
|
|
fname = *argvp;
|
|
|
|
if (argc > 2) {
|
|
pointrate = atoi(argvp[1]);
|
|
}
|
|
|
|
if ((client = jack_client_open(jack_client_name, JackNullOption, &jack_status)) == 0) {
|
|
fprintf (stderr, "jack server not running?\n");
|
|
return 1;
|
|
}
|
|
|
|
jack_set_process_callback (client, process, 0);
|
|
jack_set_buffer_size_callback (client, bufsize, 0);
|
|
jack_set_sample_rate_callback (client, srate, 0);
|
|
jack_on_shutdown (client, jack_shutdown, 0);
|
|
|
|
out_x = jack_port_register (client, "out_x", JACK_DEFAULT_AUDIO_TYPE, JackPortIsOutput, 0);
|
|
out_y = jack_port_register (client, "out_y", JACK_DEFAULT_AUDIO_TYPE, JackPortIsOutput, 0);
|
|
out_z = jack_port_register (client, "out_z", JACK_DEFAULT_AUDIO_TYPE, JackPortIsOutput, 0);
|
|
out_r = jack_port_register (client, "out_r", JACK_DEFAULT_AUDIO_TYPE, JackPortIsOutput, 0);
|
|
out_g = jack_port_register (client, "out_g", JACK_DEFAULT_AUDIO_TYPE, JackPortIsOutput, 0);
|
|
out_b = jack_port_register (client, "out_b", JACK_DEFAULT_AUDIO_TYPE, JackPortIsOutput, 0);
|
|
out_w = jack_port_register (client, "out_w", JACK_DEFAULT_AUDIO_TYPE, JackPortIsOutput, 0);
|
|
|
|
memset(frames, 0, sizeof(frames));
|
|
|
|
curframe = curdframe = &frames[frameno];
|
|
if (loadild(fname, curframe) < 0)
|
|
{
|
|
return 1;
|
|
}
|
|
|
|
stat(fname, &st1);
|
|
|
|
subpos = 0;
|
|
|
|
if (jack_activate (client)) {
|
|
fprintf (stderr, "cannot activate client");
|
|
return 1;
|
|
}
|
|
|
|
while (1) {
|
|
stat(fname, &st2);
|
|
if(st1.st_mtim.tv_sec != st2.st_mtim.tv_sec || st1.st_mtim.tv_nsec != st2.st_mtim.tv_nsec) {
|
|
frameno = (frameno+1)%FRAMEBUFS;
|
|
printf("Loading new frame to slot %d\n", frameno);
|
|
if(frames[frameno].points)
|
|
free(frames[frameno].points);
|
|
loadild(fname, &frames[frameno]);
|
|
printf("New frame loaded\n");
|
|
curframe = &frames[frameno];
|
|
memcpy(&st1, &st2, sizeof(st1));
|
|
}
|
|
usleep(50000);
|
|
}
|
|
jack_client_close (client);
|
|
exit (0);
|
|
}
|
|
|