aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--Makefile24
-rw-r--r--Makefile.linux15
-rw-r--r--alsa.c92
-rw-r--r--cms.c49
-rw-r--r--cms.h18
-rw-r--r--fft.c88
-rw-r--r--fft.h9
-rw-r--r--sio.c99
-rw-r--r--sio.h10
-rw-r--r--spectrogram.c451
10 files changed, 253 insertions, 602 deletions
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 <bsd.prog.mk>
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 <X11/Xlib.h>
+
+#include <assert.h>
#include <stdint.h>
+#include <stdlib.h>
#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 <stdlib.h>
#include <string.h>
#include <math.h>
+#include <complex.h> /* must be prior fftw3 */
#include <fftw3.h>
#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 <X11/Xlib.h>
#include <X11/Xutil.h>
-#include <X11/keysym.h>
-#include <sys/types.h>
-#include <sys/time.h>
-
-#include <assert.h>
#include <err.h>
-#include <math.h>
#include <signal.h>
-#include <stdarg.h>
#include <stdio.h>
#include <stdlib.h>
-#include <string.h>
#include <unistd.h>
-#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);