From 11de1f857ce719a9daca77f59382f4e65fee5546 Mon Sep 17 00:00:00 2001 From: Dimitri Sokolyuk Date: Fri, 12 Sep 2014 23:09:43 +0000 Subject: sync with HEAD --- Makefile | 24 ++- Makefile.linux | 15 -- alsa.c | 92 ++++++------ cms.c | 49 ++++++- cms.h | 18 ++- fft.c | 88 ++++++----- fft.h | 9 +- sio.c | 99 +++++++------ sio.h | 10 +- spectrogram.c | 451 ++++----------------------------------------------------- 10 files changed, 253 insertions(+), 602 deletions(-) delete mode 100644 Makefile.linux diff --git a/Makefile b/Makefile index 2034dab..ace154b 100644 --- a/Makefile +++ b/Makefile @@ -1,15 +1,27 @@ # $Id$ -VERSION=2.0 +VERSION=3.0 PROG= spectrogram -SRCS= spectrogram.c sio.c fft.c cms.c Spectrogram.c -BINDIR= /usr/local/bin -HEADERS=sio.h fft.h cms.h Spectrogram.h SpectrogramP.h + +SRCS= spectrogram.c fft.c cms.c aux.c widget.c Spectrogram.c LIBS= fftw3 x11 xaw7 +BINDIR= /usr/local/bin + +UNAME!= uname +.ifdef ${UNAME} == Linux +SRCS+= alsa.c +LIBS+= alsa +.else +SRCS+= sio.c +LDADD+= -lsndio +.endif + PCCF!= pkg-config --cflags ${LIBS} -PCLA!= pkg-config --libs ${LIBS} CFLAGS+=${PCCF} -LDADD+= ${PCLA} -lsndio + +PCLA!= pkg-config --libs ${LIBS} +LDADD+= ${PCLA} + DEBUG+= -Wall NOMAN= DIR= ${PROG}-${VERSION} diff --git a/Makefile.linux b/Makefile.linux deleted file mode 100644 index 159ec60..0000000 --- a/Makefile.linux +++ /dev/null @@ -1,15 +0,0 @@ -# $Id$ - -PROG= spectrogram -SRCS= spectrogram.c alsa.c fft.c cms.c -BINDIR= /usr/local/bin -HEADERS=fft.h cms.h -LIBS= fftw3 x11 alsa -PCCF!= pkg-config --cflags ${LIBS} -PCLA!= pkg-config --libs ${LIBS} -CFLAGS+=${PCCF} -LDADD+= ${PCLA} -DEBUG+= -Wall -NOMAN= - -.include diff --git a/alsa.c b/alsa.c index e1f0208..cf99349 100644 --- a/alsa.c +++ b/alsa.c @@ -26,86 +26,88 @@ #define RATE 48000 #define FPS 25 -struct sio { - snd_pcm_t *handle; - snd_pcm_hw_params_t *params; - int16_t *buffer; - unsigned int samples; +static snd_pcm_t *hdl; +static snd_pcm_hw_params_t *par; +static int16_t *buffer; +static unsigned int samples; + +struct data { + int16_t left; + int16_t right; }; -struct sio * +int init_sio(void) { - struct sio *sio; snd_pcm_uframes_t round; unsigned int rate; int rc; - sio = malloc(sizeof(struct sio)); - assert(sio); - - rc = snd_pcm_open(&sio->handle, "default", SND_PCM_STREAM_CAPTURE, 0); + rc = snd_pcm_open(&hdl, "default", SND_PCM_STREAM_CAPTURE, 0); if (rc < 0) errx(1, "unable to open pcm device: %s", snd_strerror(rc)); - snd_pcm_hw_params_malloc(&sio->params); - snd_pcm_hw_params_any(sio->handle, sio->params); - snd_pcm_hw_params_set_access(sio->handle, sio->params, + snd_pcm_hw_params_malloc(&par); + snd_pcm_hw_params_any(hdl, par); + snd_pcm_hw_params_set_access(hdl, par, SND_PCM_ACCESS_RW_INTERLEAVED); - snd_pcm_hw_params_set_format(sio->handle, sio->params, + snd_pcm_hw_params_set_format(hdl, par, SND_PCM_FORMAT_S16_LE); - snd_pcm_hw_params_set_channels(sio->handle, sio->params, STEREO); - snd_pcm_hw_params_set_rate(sio->handle, sio->params, RATE, 0); + snd_pcm_hw_params_set_channels(hdl, par, STEREO); + snd_pcm_hw_params_set_rate(hdl, par, RATE, 0); - rc = snd_pcm_hw_params(sio->handle, sio->params); + rc = snd_pcm_hw_params(hdl, par); if (rc < 0) errx(1, "unable to set hw parameters: %s", snd_strerror(rc)); - snd_pcm_hw_params_get_period_size(sio->params, &round, NULL); - snd_pcm_hw_params_get_rate(sio->params, &rate, 0); - snd_pcm_hw_params_free(sio->params); - snd_pcm_prepare(sio->handle); - - sio->samples = rate / FPS; - warnx("min samples: %d", sio->samples); - sio->samples -= sio->samples % round - round; - warnx("max samples: %d", sio->samples); - sio->buffer = calloc(sio->samples * STEREO, sizeof(int16_t)); - assert(sio->buffer); + snd_pcm_hw_params_get_period_size(par, &round, NULL); + snd_pcm_hw_params_get_rate(par, &rate, 0); + snd_pcm_hw_params_free(par); + snd_pcm_prepare(hdl); + samples = rate / FPS; + samples -= samples % round - round; + buffer = calloc(samples * STEREO, sizeof(int16_t)); + assert(buffer); - return sio; + return 0; } unsigned int -max_samples_sio(struct sio *sio) +max_samples_sio(void) { - return sio->samples; + return samples; } -int16_t * -read_sio(struct sio *sio, unsigned int n) +void +read_sio(double *left, double *right, size_t n) { snd_pcm_sframes_t rc; + struct data *data; + int i; - if (n > sio->samples) - n = sio->samples; + if (n > samples) + n = samples; - rc = snd_pcm_readi(sio->handle, sio->buffer, sio->samples); - if (rc != sio->samples) { + rc = snd_pcm_readi(hdl, buffer, samples); + if (rc != samples) { warnx("audio read error: %s", snd_strerror(rc)); if (rc == -EPIPE) - snd_pcm_prepare(sio->handle); + snd_pcm_prepare(hdl); } - return sio->buffer + sio->samples - n; + data = (struct data *)&buffer[samples - n]; + + for (i = 0; i < n; i++) { + left[i] = data[i].left; + right[i] = data[i].right; + } } void -free_sio(struct sio *sio) +free_sio(void) { - snd_pcm_drain(sio->handle); - snd_pcm_close(sio->handle); - free(sio->buffer); - free(sio); + snd_pcm_drain(hdl); + snd_pcm_close(hdl); + free(buffer); } diff --git a/cms.c b/cms.c index 435089a..0f30dab 100644 --- a/cms.c +++ b/cms.c @@ -20,11 +20,16 @@ * output: R, G, B 0..65535 */ +#include + +#include #include +#include #include "cms.h" -void +#if 0 +static void hsv2rgb(unsigned short *r, unsigned short *g, unsigned short *b, double h, double s, double v) { @@ -65,13 +70,14 @@ hsv2rgb(unsigned short *r, unsigned short *g, unsigned short *b, *r = *g = *b = UINT16_MAX * v; } } +#endif /* * input: H 0..360, S 0..100, L 0..100 * output: R, G, B 0..65535 */ -void +static void hsl2rgb(unsigned short *r, unsigned short *g, unsigned short *b, double h, double s, double l) { @@ -114,3 +120,42 @@ hsl2rgb(unsigned short *r, unsigned short *g, unsigned short *b, *r = *g = *b = UINT16_MAX * l; } } + +unsigned long +hslcolor(Display *d, double h, double s, double l) +{ + int scr = DefaultScreen(d); + Colormap cmap = DefaultColormap(d, scr); + XColor c; + + hsl2rgb(&c.red, &c.green, &c.blue, h, s, l); + c.flags = DoRed|DoGreen|DoBlue; + + XAllocColor(d, cmap, &c); + + return c.pixel; +} + +unsigned long * +init_palette(Display *d, struct palette pal, int n) +{ + unsigned long *p; + float hstep, sstep, lstep; + int i; + + p = calloc(n, sizeof(unsigned long)); + assert(p); + + hstep = (pal.to.h - pal.from.h) / (n - 1); + sstep = (pal.to.s - pal.from.s) / (n - 1); + lstep = (pal.to.l - pal.from.l) / (n - 1); + + for (i = 0; i < n; i++) { + p[i] = hslcolor(d, pal.from.h, pal.from.s, pal.from.l); + pal.from.h += hstep; + pal.from.s += sstep; + pal.from.l += lstep; + } + + return p; +} diff --git a/cms.h b/cms.h index 111b3ae..aa1083a 100644 --- a/cms.h +++ b/cms.h @@ -18,15 +18,17 @@ #ifndef __CMS_H #define __CMS_H +struct hsl { + double h, s, l; +}; + +struct palette { + struct hsl from, to; +}; + __BEGIN_DECLS -void hsv2rgb( - unsigned short *r, unsigned short *g, unsigned short *b, - double h, double s, double v -); -void hsl2rgb( - unsigned short *r, unsigned short *g, unsigned short *b, - double h, double s, double l -); +unsigned long *init_palette(Display *, struct palette, int); +unsigned long hslcolor(Display *, double h, double s, double l); __END_DECLS #endif diff --git a/fft.c b/fft.c index 412148e..84e8a95 100644 --- a/fft.c +++ b/fft.c @@ -20,76 +20,88 @@ #include #include #include +#include /* must be prior fftw3 */ #include #include "fft.h" -struct fft { - fftw_plan plan; - double *in; - double *out; - size_t n; - double *window; -}; +static fftw_plan plan; +static fftw_complex *out; +static double *in; +static size_t sz; +static double *window; +static double *sq; static double * hamming(size_t n) { - double *w; + double alpha = 0.53836; + double beta = 1.0 - alpha; + double *p; int i; - w = calloc(n, sizeof(double)); - assert(w); + p = calloc(n, sizeof(double)); + assert(p); - for (i = 0; i < n; i++) - w[i] = 0.54 - 0.46 * cos((2 * M_PI * i) / (n - 1)); + for (i = 0; i < n; i++) { + p[i] = alpha - beta * cos(2 * M_PI * i / (n - 1)); + p[i] /= INT16_MAX; + } - return w; + return p; } -struct fft * -init_fft(size_t n) +static double * +squares(size_t n) { - struct fft *p; + double *p; + int i; - p = malloc(sizeof(struct fft)); + p = calloc(n, sizeof(double)); assert(p); - p->n = n; - p->in = fftw_malloc(p->n * sizeof(double)); - p->out = fftw_malloc(p->n * sizeof(double)); - assert(p->in && p->out); - - p->window = hamming(p->n); - p->plan = fftw_plan_r2r_1d(p->n, p->in, p->out, - FFTW_R2HC, FFTW_MEASURE); + for (i = 0; i < n; i++) + p[i] = sqrt(i + 1); return p; } int -exec_fft(struct fft *p, int16_t *data, double *out, enum fft_chan chan) +init_fft(size_t maxn, size_t n) +{ + in = fftw_malloc(maxn * sizeof(double)); + out = fftw_malloc(maxn * sizeof(fftw_complex) / 2); + assert(in && out); + + plan = fftw_plan_dft_r2c_1d(n, in, out, FFTW_MEASURE); + window = hamming(n); + sq = squares(n / 2); + sz = n; + + return 0; +} + +int +exec_fft(double *io) { int i; - for (i = 0; i < p->n; i++) - p->in[i] = p->window[i] * data[2 * i + chan] - / (double)INT16_MAX; + for (i = 0; i < sz; i++) + in[i] = window[i] * io[i]; - fftw_execute(p->plan); + fftw_execute(plan); - for (i = 1; i < p->n / 2; i++) - out[i - 1] = sqrt(i * (pow(p->out[i], 2) - + pow(p->out[p->n - i], 2))); + for (i = 0; i < sz / 2; i++) + io[i] = sq[i] * cabs(out[i]); return 0; } void -free_fft(struct fft *p) +free_fft(void) { - fftw_free(p->in); - fftw_free(p->out); - free(p->window); - free(p); + fftw_free(in); + fftw_free(out); + free(window); + free(sq); } diff --git a/fft.h b/fft.h index eeeaffd..200a763 100644 --- a/fft.h +++ b/fft.h @@ -18,13 +18,10 @@ #ifndef __FFT_H #define __FFT_H -struct fft; -enum fft_chan { FFT_LEFT, FFT_RIGHT }; - __BEGIN_DECLS -struct fft *init_fft(size_t); -int exec_fft(struct fft *, int16_t *, double *, enum fft_chan); -void free_fft(struct fft *); +int init_fft(size_t, size_t); +int exec_fft(double *); +void free_fft(void); __END_DECLS #endif diff --git a/sio.c b/sio.c index f140950..43ffcd6 100644 --- a/sio.c +++ b/sio.c @@ -27,80 +27,75 @@ #define SIGNED 1 #define FPS 25 -struct sio { - struct sio_hdl *sio; - struct sio_par par; - int16_t *buffer; - unsigned int samples; +static struct sio_hdl *hdl; +static struct sio_par par; +static int16_t *buffer; +static unsigned int samples; + +struct data { + int16_t left; + int16_t right; }; -struct sio * +int init_sio(void) { - struct sio *sio; - - sio = malloc(sizeof(struct sio)); - assert(sio); - - sio->sio = sio_open(SIO_DEVANY, SIO_REC, 0); - if (!sio->sio) + hdl = sio_open(SIO_DEVANY, SIO_REC, 0); + if (!hdl) errx(1, "cannot connect to sound server, is it running?"); - sio_initpar(&sio->par); + sio_initpar(&par); - sio->par.rchan = STEREO; - sio->par.bits = BITS; - sio->par.le = SIO_LE_NATIVE; - sio->par.sig = SIGNED; + par.rchan = STEREO; + par.bits = BITS; + par.le = SIO_LE_NATIVE; + par.sig = SIGNED; - if (!sio_setpar(sio->sio, &sio->par)) + if (!sio_setpar(hdl, &par)) errx(1, "SIO set params failed"); - if (!sio_getpar(sio->sio, &sio->par)) + if (!sio_getpar(hdl, &par)) errx(1, "SIO get params failed"); - if (sio->par.rchan != STEREO || - sio->par.bits != BITS || - sio->par.le != SIO_LE_NATIVE || - sio->par.sig != SIGNED) + if (par.rchan != STEREO || + par.bits != BITS || + par.le != SIO_LE_NATIVE || + par.sig != SIGNED) errx(1, "unsupported audio params"); - sio->samples = sio->par.rate / FPS; - warnx("min samples: %d", sio->samples); - sio->samples -= sio->samples % sio->par.round - sio->par.round; - warnx("max samples: %d", sio->samples); - sio->buffer = calloc(sio->samples * sio->par.rchan, sizeof(int16_t)); - assert(sio->buffer); - - sio_start(sio->sio); + samples = par.rate / FPS; + samples -= samples % par.round - par.round; + buffer = calloc(samples * par.rchan, sizeof(int16_t)); + assert(buffer); - return sio; + return sio_start(hdl); } unsigned int -max_samples_sio(struct sio *sio) +max_samples_sio(void) { /* * maximal number of samples we're willing to provide * with 1920 at 25 fps and 48000 Hz or * with 1764 at 25 fps and 44100 Hz it shall fit on most screens */ - return sio->samples; + return samples; } -int16_t * -read_sio(struct sio *sio, unsigned int n) +void +read_sio(double *left, double *right, size_t n) { - int done; - char *buffer = (char *)sio->buffer; - size_t bufsz = sio->samples * sio->par.rchan * sizeof(int16_t); - size_t rndsz = n * sio->par.rchan * sizeof(int16_t); + int done, i; + char *p = (char *)buffer; + size_t bufsz = samples * par.rchan * sizeof(int16_t); + size_t rndsz = n * par.rchan * sizeof(int16_t); + struct data *data; if (rndsz > bufsz) rndsz = bufsz; - for (done = 0; bufsz > 0; buffer += done, bufsz -= done) { - done = sio_read(sio->sio, buffer, bufsz); - if (sio_eof(sio->sio)) + for (done = 0; bufsz > 0; p += done, bufsz -= done) { + done = sio_read(hdl, p, bufsz); + if (sio_eof(hdl)) errx(1, "SIO EOF"); } @@ -108,14 +103,18 @@ read_sio(struct sio *sio, unsigned int n) * return a pointer to the latest ROUND samples (the most recent * ones) to minimize latency between picture and sound */ - return (int16_t *)(buffer - rndsz); + data = (struct data *)(p - rndsz); + + for (i = 0; i < n; i++) { + left[i] = data[i].left; + right[i] = data[i].right; + } } void -free_sio(struct sio *sio) +free_sio(void) { - sio_stop(sio->sio); - sio_close(sio->sio); - free(sio->buffer); - free(sio); + sio_stop(hdl); + sio_close(hdl); + free(buffer); } diff --git a/sio.h b/sio.h index 775b222..b5b5d5e 100644 --- a/sio.h +++ b/sio.h @@ -18,13 +18,11 @@ #ifndef __SIO_H #define __SIO_H -struct sio; - __BEGIN_DECLS -struct sio *init_sio(void); -int16_t *read_sio(struct sio *, unsigned int); -unsigned int max_samples_sio(struct sio *); -void free_sio(struct sio *); +int init_sio(void); +void read_sio(double *, double *, size_t); +unsigned int max_samples_sio(void); +void free_sio(void); __END_DECLS #endif diff --git a/spectrogram.c b/spectrogram.c index a9546af..1578481 100644 --- a/spectrogram.c +++ b/spectrogram.c @@ -17,119 +17,21 @@ #include #include -#include -#include -#include - -#include #include -#include #include -#include #include #include -#include #include -#include "cms.h" +#include "aux.h" #include "fft.h" #include "sio.h" - -#define HGAP 4 -#define VGAP 1 +#include "widget.h" extern char *__progname; int die = 0; -struct pixmap { - Pixmap pix; - GC gc; -}; - -struct background { - Pixmap pix; - Pixmap mask; - GC gc; - XRectangle geo; -}; - -struct subwin { - Window win; - Pixmap pix; /* buffer */ - GC gc; - XRectangle geo; -}; - -struct panel { - Window win; /* container */ - struct subwin *wf; - struct subwin *sp; - struct background *bg; - struct background *shadow; - int mirror; - int maxval; - double *data; - unsigned long *palette; -}; - -struct hsl { - float h, s, l; -}; - -struct palette { - struct hsl from, to; -}; - -enum mirror { LTR, RTL }; - -struct palette p_spectr = {{ 120.0, 100.0, 75.0 }, { 0.0, 100.0, 25.0 }}; -struct palette p_shadow = {{ 120.0, 100.0, 10.0 }, { 0.0, 100.0, 10.0 }}; -struct palette p_waterfall = {{ 210.0, 75.0, 0.0 }, { 180.0, 100.0, 100.0 }}; -struct hsl hsl_gray = {0.0, 0.0, 20.0}; -unsigned long *sp_pal = NULL; -unsigned long *sh_pal = NULL; -unsigned long *wf_pal = NULL; - -unsigned long -hslcolor(Display *d, struct hsl hsl) -{ - int scr = DefaultScreen(d); - Colormap cmap = DefaultColormap(d, scr); - XColor c; - - hsl2rgb(&c.red, &c.green, &c.blue, hsl.h, hsl.s, hsl.l); - c.flags = DoRed|DoGreen|DoBlue; - - XAllocColor(d, cmap, &c); - - return c.pixel; -} - -unsigned long * -init_palette(Display *d, struct palette pal, int n) -{ - unsigned long *p; - float hstep, sstep, lstep; - int i; - - p = calloc(n, sizeof(unsigned long)); - assert(p); - - hstep = (pal.to.h - pal.from.h) / (n - 1); - sstep = (pal.to.s - pal.from.s) / (n - 1); - lstep = (pal.to.l - pal.from.l) / (n - 1); - - for (i = 0; i < n; i++) { - p[i] = hslcolor(d, pal.from); - pal.from.h += hstep; - pal.from.s += sstep; - pal.from.l += lstep; - } - - return p; -} - void catch(int notused) { @@ -150,312 +52,19 @@ usage(void) exit(0); } -void -blit(Display *d, Drawable p, GC gc, XRectangle r) -{ - XCopyArea(d, p, p, gc, 0, 0, r.width, r.height - 1, 0, 1); -} - -void -clear(Display *d, Drawable p, GC gc, XRectangle r) -{ - XSetForeground(d, gc, BlackPixel(d, DefaultScreen(d))); - XFillRectangle(d, p, gc, 0, 0, r.width, r.height); -} - -void -copy(Display *d, Drawable from, Drawable to, GC gc, XRectangle r, Drawable mask) -{ - XSetClipMask(d, gc, mask); - XCopyArea(d, from, to, gc, 0, 0, r.width, r.height, 0, 0); - XSetClipMask(d, gc, None); -} - -void -draw_panel(Display *d, struct panel *p) -{ - int i, v, x; - - /* blit waterfall */ - blit(d, p->wf->pix, p->wf->gc, p->wf->geo); - /* blit shadow mask */ - blit(d, p->shadow->mask, p->shadow->gc, p->shadow->geo); - - /* clear spectrogram */ - clear(d, p->sp->pix, p->sp->gc, p->sp->geo); - /* clear mask */ - clear(d, p->bg->mask, p->bg->gc, p->bg->geo); - - for (i = 0; i < p->sp->geo.width; i++) { - /* limit maxval */ - v = p->data[i] >= p->maxval ? p->maxval - 1 : p->data[i]; - x = p->mirror ? p->sp->geo.width - i - 1 : i; - - /* draw waterfall */ - XSetForeground(d, p->wf->gc, p->palette[v]); - XDrawPoint(d, p->wf->pix, p->wf->gc, x, 0); - - /* draw spectrogram */ - XSetForeground(d, p->bg->gc, 1); - XDrawLine(d, p->bg->mask, p->bg->gc, - x, p->bg->geo.height - v, - x, p->bg->geo.height); - } - - /* copy mask to shadow mask */ - copy(d, p->bg->mask, p->shadow->mask, p->shadow->gc, p->shadow->geo, - p->bg->mask); - /* shadow to buffer */ - copy(d, p->shadow->pix, p->sp->pix, p->sp->gc, p->sp->geo, - p->shadow->mask); - /* spectrogram to buffer */ - copy(d, p->bg->pix, p->sp->pix, p->sp->gc, p->sp->geo, - p->bg->mask); -} - -void -flip(Display *d, struct subwin *p) -{ - XCopyArea(d, p->pix, p->win, p->gc, - 0, 0, p->geo.width, p->geo.height, 0, 0); -} - -void -flip_panel(Display *d, struct panel *p) -{ - /* flip spectrogram */ - flip(d, p->sp); - /* flip waterfall */ - flip(d, p->wf); -} - -void -draw_background(Display *d, Pixmap pix, GC gc, XRectangle r, unsigned long *pal) -{ - int i, x, y; - - x = r.width - 1; - for (i = 0; i < r.height; i++) { - y = r.height - i - 1; - XSetForeground(d, gc, pal[i]); - XDrawLine(d, pix, gc, 0, y, x, y); - } -} - -struct background * -init_background(Display *d, Drawable parent, XRectangle r) -{ - struct background *p; - int scr = DefaultScreen(d); - int planes = DisplayPlanes(d, scr); - int black = BlackPixel(d, scr); - - p = malloc(sizeof(struct subwin)); - assert(p); - - p->pix = XCreatePixmap(d, parent, r.width, r.height, planes); - p->mask = XCreatePixmap(d, parent, r.width, r.height, 1); - p->gc = XCreateGC(d, p->mask, 0, NULL); - p->geo = r; - - /* clear */ - XSetForeground(d, p->gc, black); - XFillRectangle(d, p->mask, p->gc, 0, 0, r.width, r.height); - - return p; -} - -struct subwin * -init_subwin(Display *d, Drawable parent, XRectangle r) -{ - struct subwin *p; - int scr = DefaultScreen(d); - int white = WhitePixel(d, scr); - int black = BlackPixel(d, scr); - int planes = DisplayPlanes(d, scr); - - p = malloc(sizeof(struct subwin)); - assert(p); - - p->win = XCreateSimpleWindow(d, parent, r.x, r.y, - r.width, r.height, 0, white, black); - p->pix = XCreatePixmap(d, p->win, r.width, r.height, planes); - p->gc = XCreateGC(d, p->pix, 0, NULL); - p->geo = r; - - /* clear */ - XSetForeground(d, p->gc, black); - XFillRectangle(d, p->pix, p->gc, 0, 0, r.width, r.height); - - XMapWindow(d, p->win); - - return p; -} - -struct panel * -init_panel(Display *d, Window win, XRectangle r, enum mirror m) -{ - struct panel *p; - int scr = DefaultScreen(d); - unsigned long white = WhitePixel(d, scr); - unsigned long gray = hslcolor(d, hsl_gray); - unsigned int maxval = r.height / 4; - XRectangle geo; - - p = malloc(sizeof(struct panel)); - assert(p); - - p->data = calloc(r.width, sizeof(double)); - assert(p->data); - - if (!sp_pal) - sp_pal = init_palette(d, p_spectr, maxval); - if (!sh_pal) - sh_pal = init_palette(d, p_shadow, maxval); - if (!wf_pal) - wf_pal = init_palette(d, p_waterfall, maxval); - - /* main panel window */ - p->win = XCreateSimpleWindow(d, win, - r.x, r.y, r.width, r.height, - 0, white, gray); - - /* sperctrogram window and its bitmasks */ - geo.x = 0; - geo.y = 0; - geo.width = r.width; - geo.height = maxval; - p->sp = init_subwin(d, p->win, geo); - - p->bg = init_background(d, p->sp->win, geo); - draw_background(d, p->bg->pix, p->sp->gc, p->bg->geo, sp_pal); - - p->shadow = init_background(d, p->sp->win, geo); - draw_background(d, p->shadow->pix, p->sp->gc, p->shadow->geo, sh_pal); - - p->palette = wf_pal; - p->maxval = maxval; - p->mirror = m; - - /* waterfall window and double buffer */ - geo.x = 0; - geo.y = p->sp->geo.height + VGAP; - geo.width = r.width; - geo.height = r.height - maxval; - p->wf = init_subwin(d, p->win, geo); - - XMapWindow(d, p->win); - - return p; -} - -void -free_background(Display *d, struct background *p) -{ - XFreePixmap(d, p->pix); - XFreePixmap(d, p->mask); - XFreeGC(d, p->gc); -} - -void -free_subwin(Display *d, struct subwin *p) -{ - XFreePixmap(d, p->pix); - XFreeGC(d, p->gc); - XUnmapWindow(d, p->win); - XDestroyWindow(d, p->win); -} - -void -free_panel(Display *d, struct panel *p) -{ - free_background(d, p->bg); - free_background(d, p->shadow); - free_subwin(d, p->sp); - free_subwin(d, p->wf); - XUnmapWindow(d, p->win); - XDestroyWindow(d, p->win); - free(p->data); - free(p); -} - -int -move(Display *dsp, Window win, Window container) -{ - int dx, dy; - XWindowAttributes wa, wac; - - XGetWindowAttributes(dsp, win, &wa); - XGetWindowAttributes(dsp, container, &wac); - - dx = (wa.width - wac.width) / 2; - dy = (wa.height - wac.height) / 2; - if (dy < 0) - dy = 0; - - XMoveWindow(dsp, container, dx, dy); - - return 0; -} - -void -gofullscreen(Display *d, Window win) -{ - XClientMessageEvent cm; - - bzero(&cm, sizeof(cm)); - cm.type = ClientMessage; - cm.send_event = True; - cm.message_type = XInternAtom(d, "_NET_WM_STATE", False); - cm.window = win; - cm.format = 32; - cm.data.l[0] = 1; /* _NET_WM_STATE_ADD */ - cm.data.l[1] = XInternAtom(d, "_NET_WM_STATE_FULLSCREEN", False); - cm.data.l[2] = 0; /* no secondary property */ - cm.data.l[3] = 1; /* normal application */ - - XSendEvent(d, DefaultRootWindow(d), False, NoEventMask, (XEvent *)&cm); - XMoveWindow(d, win, 0, 0); -} - -void -hide_ptr(Display *d, Window win) -{ - Pixmap bm; - Cursor ptr; - Colormap cmap; - XColor black, dummy; - static char empty[] = {0, 0, 0, 0, 0, 0, 0, 0}; - - cmap = DefaultColormap(d, DefaultScreen(d)); - XAllocNamedColor(d, cmap, "black", &black, &dummy); - bm = XCreateBitmapFromData(d, win, empty, 8, 8); - ptr = XCreatePixmapCursor(d, bm, bm, &black, &black, 0, 0); - - XDefineCursor(d, win, ptr); - XFreeCursor(d, ptr); - if (bm != None) - XFreePixmap(d, bm); - XFreeColors(d, cmap, &black.pixel, 1, 0); -} - int main(int argc, char **argv) { Display *dsp; Window win, container; Atom delwin; - Atom nhints; - XSizeHints *hints; XClassHint *class; XWindowAttributes wa; XRectangle geo; int scr; struct panel *left, *right; - struct sio *sio; - struct fft *fft; - int16_t *buffer; + double *ldata, *rdata; int dflag = 0; /* daemonize */ int fflag = 0; /* fullscreen */ @@ -495,8 +104,8 @@ main(int argc, char **argv) if (dflag) daemon(0, 0); - sio = init_sio(); - maxwidth = max_samples_sio(sio); + init_sio(); + maxwidth = max_samples_sio(); maxheight = wa.height; dsp = XOpenDisplay(NULL); @@ -539,42 +148,33 @@ main(int argc, char **argv) XSetWMProtocols(dsp, win, &delwin, 1); /* set minimal size */ - nhints = XInternAtom(dsp, "WM_NORMAL_HINTS", 0); - hints = XAllocSizeHints(); - hints->flags = PMinSize|PMaxSize; - hints->min_width = width; - hints->min_height = height; - hints->max_width = maxwidth; - hints->max_height = maxheight; - XSetWMSizeHints(dsp, win, hints, nhints); - XFree(hints); + restrictsize(dsp, win, width, height, maxwidth, maxheight); container = XCreateSimpleWindow(dsp, win, 0, 0, width, height, 0, white, black); XMapWindow(dsp, container); - fft = init_fft(round); + init_fft(maxwidth, round); geo.x = 0; geo.y = 0; geo.width = round / 2; geo.height = height; left = init_panel(dsp, container, geo, RTL); + ldata = dataptr(left); geo.x = round / 2 + HGAP; geo.y = 0; geo.width = round / 2; geo.height = height; right = init_panel(dsp, container, geo, LTR); - - free(sp_pal); - free(sh_pal); + rdata = dataptr(right); XClearWindow(dsp, win); XMapRaised(dsp, win); /* XMapWindow */ if (fflag) { - gofullscreen(dsp, win); + fullscreen(dsp, win); if (pflag) hide_ptr(dsp, win); } @@ -592,14 +192,14 @@ main(int argc, char **argv) die = 1; break; case XK_1: - left->mirror ^= 1; + toggle_mirror(left); break; case XK_2: - right->mirror ^= 1; + toggle_mirror(right); break; case XK_3: - left->mirror ^= 1; - right->mirror ^= 1; + toggle_mirror(left); + toggle_mirror(right); break; default: break; @@ -616,26 +216,25 @@ main(int argc, char **argv) } } - buffer = read_sio(sio, round); + read_sio(ldata, rdata, round); - exec_fft(fft, buffer, left->data, FFT_LEFT); - exec_fft(fft, buffer, right->data, FFT_RIGHT); + exec_fft(ldata); + exec_fft(rdata); - draw_panel(dsp, left); - draw_panel(dsp, right); + draw_panel(left); + draw_panel(right); - flip_panel(dsp, left); - flip_panel(dsp, right); + flip_panel(left); + flip_panel(right); if (fflag) XResetScreenSaver(dsp); } - free_sio(sio); - free_fft(fft); - free_panel(dsp, left); - free_panel(dsp, right); - free(wf_pal); + free_sio(); + free_fft(); + free_panel(left); + free_panel(right); XDestroyWindow(dsp, win); XCloseDisplay(dsp); -- cgit v1.2.3