mirror of
https://github.com/ericonr/sndio.git
synced 2024-02-18 04:45:21 -06:00
add xvolkeys utility
This commit is contained in:
parent
f7d028191a
commit
28654d372c
3
configure
vendored
3
configure
vendored
@ -160,7 +160,8 @@ if [ $rmidi = yes ]; then
|
|||||||
fi
|
fi
|
||||||
|
|
||||||
for f in Makefile aucat/Makefile sndiod/Makefile \
|
for f in Makefile aucat/Makefile sndiod/Makefile \
|
||||||
libsndio/Makefile sndioctl/Makefile examples/Makefile \
|
libsndio/Makefile sndioctl/Makefile xvolkeys/Makefile \
|
||||||
|
examples/Makefile \
|
||||||
contrib/init.d.sndiod
|
contrib/init.d.sndiod
|
||||||
do
|
do
|
||||||
sed \
|
sed \
|
||||||
|
53
xvolkeys/Makefile.in
Normal file
53
xvolkeys/Makefile.in
Normal file
@ -0,0 +1,53 @@
|
|||||||
|
# extra includes paths (-I options)
|
||||||
|
INCLUDE = -I/usr/X11R6/include -I../libsndio -I../bsd-compat
|
||||||
|
|
||||||
|
# extra libraries paths (-L options)
|
||||||
|
LIB = -L/usr/X11R6/lib -L../libsndio
|
||||||
|
|
||||||
|
# extra defines (-D options)
|
||||||
|
DEFS = -DDEBUG @defs@
|
||||||
|
|
||||||
|
# extra libraries (-l options)
|
||||||
|
LDADD = -lX11 -lsndio @ldadd@
|
||||||
|
|
||||||
|
# variables defined on configure script command line (if any)
|
||||||
|
@vars@
|
||||||
|
|
||||||
|
#
|
||||||
|
# binaries, documentation, man pages and examples will be installed in
|
||||||
|
# ${BIN_DIR}, ${MAN1_DIR}
|
||||||
|
#
|
||||||
|
BIN_DIR = @bindir@
|
||||||
|
MAN1_DIR = @mandir@/man1
|
||||||
|
|
||||||
|
#
|
||||||
|
# programs to build
|
||||||
|
#
|
||||||
|
PROG = xvolkeys
|
||||||
|
MAN1 = xvolkeys.1
|
||||||
|
|
||||||
|
all: ${PROG} ${MAN1}
|
||||||
|
|
||||||
|
install:
|
||||||
|
mkdir -p ${DESTDIR}${BIN_DIR} ${DESTDIR}${MAN1_DIR}
|
||||||
|
cp xvolkeys ${DESTDIR}${BIN_DIR}
|
||||||
|
cp xvolkeys.1 ${DESTDIR}${MAN1_DIR}
|
||||||
|
|
||||||
|
uninstall:
|
||||||
|
cd ${DESTDIR}${BIN_DIR} && rm -f ${PROG}
|
||||||
|
cd ${DESTDIR}${MAN1_DIR} && rm -f ${MAN1}
|
||||||
|
|
||||||
|
clean:
|
||||||
|
rm -f -- *.o xvolkeys
|
||||||
|
|
||||||
|
# ---------------------------------------------------------- dependencies ---
|
||||||
|
|
||||||
|
OBJS = xvolkeys.o
|
||||||
|
|
||||||
|
xvolkeys: ${OBJS}
|
||||||
|
${CC} ${LDFLAGS} ${LIB} -o xvolkeys ${OBJS} ${LDADD}
|
||||||
|
|
||||||
|
.c.o:
|
||||||
|
${CC} ${CFLAGS} ${INCLUDE} ${DEFS} -c $<
|
||||||
|
|
||||||
|
xvolkeys.o: xvolkeys.c sysex.h
|
125
xvolkeys/sysex.h
Normal file
125
xvolkeys/sysex.h
Normal file
@ -0,0 +1,125 @@
|
|||||||
|
/* $OpenBSD$ */
|
||||||
|
/*
|
||||||
|
* Copyright (c) 2011 Alexandre Ratchov <alex@caoua.org>
|
||||||
|
*
|
||||||
|
* Permission to use, copy, modify, and distribute this software for any
|
||||||
|
* purpose with or without fee is hereby granted, provided that the above
|
||||||
|
* copyright notice and this permission notice appear in all copies.
|
||||||
|
*
|
||||||
|
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
||||||
|
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
||||||
|
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
|
||||||
|
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
||||||
|
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
|
||||||
|
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
|
||||||
|
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||||
|
*/
|
||||||
|
#ifndef AUCAT_SYSEX_H
|
||||||
|
#define AUCAT_SYSEX_H
|
||||||
|
|
||||||
|
#include <stdint.h>
|
||||||
|
|
||||||
|
/*
|
||||||
|
* start and end markers
|
||||||
|
*/
|
||||||
|
#define SYSEX_START 0xf0
|
||||||
|
#define SYSEX_END 0xf7
|
||||||
|
|
||||||
|
/*
|
||||||
|
* type/vendor namespace IDs we use
|
||||||
|
*/
|
||||||
|
#define SYSEX_TYPE_RT 0x7f /* real-time universal */
|
||||||
|
#define SYSEX_TYPE_EDU 0x7d /* non-comercial */
|
||||||
|
|
||||||
|
/*
|
||||||
|
* realtime messages in the "universal real-time" namespace
|
||||||
|
*/
|
||||||
|
#define SYSEX_MTC 0x01 /* mtc messages */
|
||||||
|
#define SYSEX_MTC_FULL 0x01 /* mtc full frame message */
|
||||||
|
#define SYSEX_CONTROL 0x04
|
||||||
|
#define SYSEX_MASTER 0x01
|
||||||
|
#define SYSEX_MMC 0x06
|
||||||
|
#define SYSEX_MMC_STOP 0x01
|
||||||
|
#define SYSEX_MMC_START 0x02
|
||||||
|
#define SYSEX_MMC_LOC 0x44
|
||||||
|
#define SYSEX_MMC_LOC_LEN 0x06
|
||||||
|
#define SYSEX_MMC_LOC_CMD 0x01
|
||||||
|
|
||||||
|
/*
|
||||||
|
* sepcial "any" midi device number
|
||||||
|
*/
|
||||||
|
#define SYSEX_DEV_ANY 0x7f
|
||||||
|
|
||||||
|
/*
|
||||||
|
* aucat-specific messages, in the "edu" namespace
|
||||||
|
*/
|
||||||
|
#define SYSEX_AUCAT 0x23 /* aucat-specific */
|
||||||
|
#define SYSEX_AUCAT_SLOTDESC 0x01 /* mixer info */
|
||||||
|
#define SYSEX_AUCAT_DUMPREQ 0x02 /* dump request */
|
||||||
|
#define SYSEX_AUCAT_DUMPEND 0x03 /* end of dump */
|
||||||
|
|
||||||
|
/*
|
||||||
|
* minimum size of sysex message we accept
|
||||||
|
*/
|
||||||
|
#define SYSEX_SIZE(m) (5 + sizeof(struct sysex_ ## m))
|
||||||
|
|
||||||
|
/*
|
||||||
|
* all possible system exclusive messages we support. For aucat-specific
|
||||||
|
* messages we use the same header as real-time messages to simplify the
|
||||||
|
* message parser
|
||||||
|
*/
|
||||||
|
struct sysex {
|
||||||
|
uint8_t start;
|
||||||
|
uint8_t type; /* type or vendor id */
|
||||||
|
uint8_t dev; /* device or product id */
|
||||||
|
uint8_t id0; /* message id */
|
||||||
|
uint8_t id1; /* sub-id */
|
||||||
|
union sysex_all {
|
||||||
|
struct sysex_empty {
|
||||||
|
uint8_t end;
|
||||||
|
} empty;
|
||||||
|
struct sysex_master {
|
||||||
|
uint8_t fine;
|
||||||
|
uint8_t coarse;
|
||||||
|
uint8_t end;
|
||||||
|
} master;
|
||||||
|
struct sysex_start {
|
||||||
|
uint8_t end;
|
||||||
|
} start;
|
||||||
|
struct sysex_stop {
|
||||||
|
uint8_t end;
|
||||||
|
} stop;
|
||||||
|
struct sysex_loc {
|
||||||
|
uint8_t len;
|
||||||
|
uint8_t cmd;
|
||||||
|
uint8_t hr;
|
||||||
|
uint8_t min;
|
||||||
|
uint8_t sec;
|
||||||
|
uint8_t fr;
|
||||||
|
uint8_t cent;
|
||||||
|
uint8_t end;
|
||||||
|
} loc;
|
||||||
|
struct sysex_full {
|
||||||
|
uint8_t hr;
|
||||||
|
uint8_t min;
|
||||||
|
uint8_t sec;
|
||||||
|
uint8_t fr;
|
||||||
|
uint8_t end;
|
||||||
|
} full;
|
||||||
|
struct sysex_slotdesc {
|
||||||
|
uint8_t chan; /* channel */
|
||||||
|
uint8_t vol; /* current volume */
|
||||||
|
#define SYSEX_NAMELEN 10 /* \0 included */
|
||||||
|
uint8_t name[SYSEX_NAMELEN]; /* stream name */
|
||||||
|
uint8_t end;
|
||||||
|
} slotdesc;
|
||||||
|
struct sysex_dumpreq {
|
||||||
|
uint8_t end;
|
||||||
|
} dumpreq;
|
||||||
|
struct sysex_dumpend {
|
||||||
|
uint8_t end;
|
||||||
|
} dumpend;
|
||||||
|
} u;
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif /* !defined(AUCAT_SYSEX_H) */
|
63
xvolkeys/xvolkeys.1
Normal file
63
xvolkeys/xvolkeys.1
Normal file
@ -0,0 +1,63 @@
|
|||||||
|
.\" $OpenBSD$
|
||||||
|
.\"
|
||||||
|
.\" Copyright (c) 2010-2012 Alexandre Ratchov <alex@caoua.org>
|
||||||
|
.\"
|
||||||
|
.\" Permission to use, copy, modify, and distribute this software for any
|
||||||
|
.\" purpose with or without fee is hereby granted, provided that the above
|
||||||
|
.\" copyright notice and this permission notice appear in all copies.
|
||||||
|
.\"
|
||||||
|
.\" THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
||||||
|
.\" WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
||||||
|
.\" MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
|
||||||
|
.\" ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
||||||
|
.\" WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
|
||||||
|
.\" ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
|
||||||
|
.\" OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||||
|
.\"
|
||||||
|
.Dd November 29, 2010
|
||||||
|
.Dt XVOLKEYS 1
|
||||||
|
.Os
|
||||||
|
.Sh NAME
|
||||||
|
.Nm xvolkeys
|
||||||
|
.Nd hot-keys in X to control sndiod master volume
|
||||||
|
.Sh SYNOPSIS
|
||||||
|
.Nm xvolkeys
|
||||||
|
.Op Fl D
|
||||||
|
.Op Fl v
|
||||||
|
.Op Fl f Ar port
|
||||||
|
.Sh DESCRIPTION
|
||||||
|
The
|
||||||
|
.Nm
|
||||||
|
increments or
|
||||||
|
decrements the
|
||||||
|
.Xr sndiod 1
|
||||||
|
master volume whenever the "+" and "-" keys
|
||||||
|
are pressed while the Control and Alt keys are held down.
|
||||||
|
It is meant to be started as background process by
|
||||||
|
.Xr xinit 1
|
||||||
|
or
|
||||||
|
.Xr xdm 1
|
||||||
|
session startup scripts.
|
||||||
|
.Pp
|
||||||
|
The options are as follows:
|
||||||
|
.Bl -tag -width Ds
|
||||||
|
.It Fl D
|
||||||
|
Daemonize.
|
||||||
|
.It Fl f Ar dev
|
||||||
|
MIDI port to use, default is
|
||||||
|
.Pa snd/0
|
||||||
|
.It Fl v
|
||||||
|
Increase log verbosity.
|
||||||
|
.El
|
||||||
|
.Sh SEE ALSO
|
||||||
|
.Xr sndiod 1
|
||||||
|
.Xr sndio 7
|
||||||
|
.Sh BUGS
|
||||||
|
The
|
||||||
|
.Nm
|
||||||
|
utility keeps the audio device open.
|
||||||
|
If the device is disconnected or
|
||||||
|
.Xr sndiod 1
|
||||||
|
is restarted, the
|
||||||
|
.Nm
|
||||||
|
process terminates.
|
278
xvolkeys/xvolkeys.c
Normal file
278
xvolkeys/xvolkeys.c
Normal file
@ -0,0 +1,278 @@
|
|||||||
|
#include <poll.h>
|
||||||
|
#include <unistd.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <errno.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <sndio.h>
|
||||||
|
#include <X11/Xlib.h>
|
||||||
|
#include <X11/Xutil.h>
|
||||||
|
#include <X11/keysym.h>
|
||||||
|
#include "sysex.h"
|
||||||
|
|
||||||
|
/*
|
||||||
|
* X keysyms to increment / decrement volume: + and -
|
||||||
|
*/
|
||||||
|
#define KEY_INC XK_plus
|
||||||
|
#define KEY_DEC XK_minus
|
||||||
|
|
||||||
|
/*
|
||||||
|
* modifiers: Alt + Ctrl
|
||||||
|
*/
|
||||||
|
#define MODMASK (Mod1Mask | ControlMask)
|
||||||
|
|
||||||
|
/*
|
||||||
|
* max MIDI message length we accept
|
||||||
|
*/
|
||||||
|
#define MIDI_MSGMAX (sizeof(struct sysex))
|
||||||
|
|
||||||
|
/*
|
||||||
|
* max MIDI volume
|
||||||
|
*/
|
||||||
|
#define MIDI_MAXVOL 127
|
||||||
|
|
||||||
|
/*
|
||||||
|
* midi parser state
|
||||||
|
*/
|
||||||
|
struct mio_hdl *hdl;
|
||||||
|
unsigned int midx;
|
||||||
|
unsigned char mev[MIDI_MSGMAX];
|
||||||
|
|
||||||
|
int master = MIDI_MAXVOL;
|
||||||
|
int verbose;
|
||||||
|
|
||||||
|
unsigned char dumpreq[] = {
|
||||||
|
SYSEX_START,
|
||||||
|
SYSEX_TYPE_EDU,
|
||||||
|
0,
|
||||||
|
SYSEX_AUCAT,
|
||||||
|
SYSEX_AUCAT_DUMPREQ,
|
||||||
|
SYSEX_END
|
||||||
|
};
|
||||||
|
|
||||||
|
void
|
||||||
|
midi_setvol(int vol)
|
||||||
|
{
|
||||||
|
struct sysex msg;
|
||||||
|
|
||||||
|
if (vol > MIDI_MAXVOL)
|
||||||
|
vol = MIDI_MAXVOL;
|
||||||
|
if (vol < 0)
|
||||||
|
vol = 0;
|
||||||
|
if (verbose)
|
||||||
|
fprintf(stderr, "setvol(%d)\n", vol);
|
||||||
|
if (master != vol) {
|
||||||
|
msg.start = SYSEX_START;
|
||||||
|
msg.type = SYSEX_TYPE_RT;
|
||||||
|
msg.dev = SYSEX_DEV_ANY;
|
||||||
|
msg.id0 = SYSEX_CONTROL;
|
||||||
|
msg.id1 = SYSEX_MASTER;
|
||||||
|
msg.u.master.fine = 0;
|
||||||
|
msg.u.master.coarse = vol;
|
||||||
|
msg.u.master.end = SYSEX_END;
|
||||||
|
if (mio_write(hdl, &msg, SYSEX_SIZE(master)) == 0) {
|
||||||
|
fprintf(stderr, "Couldn't write volume message\n");
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
master = vol;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* decode midi sysex message
|
||||||
|
*/
|
||||||
|
void
|
||||||
|
midi_sysex(unsigned char *msg, unsigned len)
|
||||||
|
{
|
||||||
|
int i;
|
||||||
|
|
||||||
|
if (verbose >= 2) {
|
||||||
|
fprintf(stderr, "sysex: ");
|
||||||
|
for (i = 0; i < len; i++)
|
||||||
|
fprintf(stderr, " %02x", msg[i]);
|
||||||
|
fprintf(stderr, "\n");
|
||||||
|
}
|
||||||
|
if (len == 8 &&
|
||||||
|
msg[1] == SYSEX_TYPE_RT &&
|
||||||
|
msg[3] == SYSEX_CONTROL &&
|
||||||
|
msg[4] == SYSEX_MASTER) {
|
||||||
|
if (master != msg[6]) {
|
||||||
|
master = msg[6];
|
||||||
|
fprintf(stderr, "master -> %d\n", master);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
midi_parse(unsigned char *mbuf, unsigned len)
|
||||||
|
{
|
||||||
|
unsigned c;
|
||||||
|
|
||||||
|
for (; len > 0; len--) {
|
||||||
|
c = *mbuf++;
|
||||||
|
if (c >= 0xf8) {
|
||||||
|
/* ignore */
|
||||||
|
} else if (c == SYSEX_END) {
|
||||||
|
if (mev[0] == SYSEX_START) {
|
||||||
|
mev[midx++] = c;
|
||||||
|
midi_sysex(mev, midx);
|
||||||
|
}
|
||||||
|
mev[0] = 0;
|
||||||
|
} else if (c == SYSEX_START) {
|
||||||
|
mev[0] = c;
|
||||||
|
midx = 1;
|
||||||
|
} else if (c >= 0x80) {
|
||||||
|
mev[0] = 0;
|
||||||
|
} else if (mev[0]) {
|
||||||
|
if (midx < MIDI_MSGMAX - 1) {
|
||||||
|
mev[midx++] = c;
|
||||||
|
} else
|
||||||
|
mev[0] = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
usage(void)
|
||||||
|
{
|
||||||
|
fprintf(stderr, "usage: xvolkeys [-Dv] [-f device]\n");
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
int
|
||||||
|
main(int argc, char **argv)
|
||||||
|
{
|
||||||
|
#define MIDIBUFSZ 0x100
|
||||||
|
unsigned char msg[MIDIBUFSZ];
|
||||||
|
char *devname;
|
||||||
|
struct pollfd *pfds;
|
||||||
|
unsigned int i, scr, nscr;
|
||||||
|
Display *dpy;
|
||||||
|
KeyCode inc_code, dec_code;
|
||||||
|
KeySym *inc_map, *dec_map;
|
||||||
|
XEvent xev;
|
||||||
|
int c, nfds, n, nret;
|
||||||
|
int background;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* parse command line options
|
||||||
|
*/
|
||||||
|
devname = "snd/0";
|
||||||
|
verbose = 0;
|
||||||
|
background = 0;
|
||||||
|
while ((c = getopt(argc, argv, "Df:v")) != -1) {
|
||||||
|
switch (c) {
|
||||||
|
case 'D':
|
||||||
|
background = 1;
|
||||||
|
break;
|
||||||
|
case 'v':
|
||||||
|
verbose++;
|
||||||
|
break;
|
||||||
|
case 'f':
|
||||||
|
devname = optarg;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
usage();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
argc -= optind;
|
||||||
|
argv += optind;
|
||||||
|
if (argc > 0)
|
||||||
|
usage();
|
||||||
|
|
||||||
|
hdl = mio_open("snd/0", MIO_IN | MIO_OUT, 0);
|
||||||
|
if (hdl == NULL) {
|
||||||
|
fprintf(stderr, "Couldn't open MIDI control device\n");
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
dpy = XOpenDisplay(NULL);
|
||||||
|
if (dpy == 0) {
|
||||||
|
fprintf(stderr, "Couldn't open display\n");
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
inc_code = XKeysymToKeycode(dpy, KEY_INC);
|
||||||
|
inc_map = XGetKeyboardMapping(dpy, inc_code, 1, &nret);
|
||||||
|
if (nret <= ShiftMask) {
|
||||||
|
fprintf(stderr, "Couldn't get keymap for '+' key\n");
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
dec_code = XKeysymToKeycode(dpy, KEY_DEC);
|
||||||
|
dec_map = XGetKeyboardMapping(dpy, dec_code, 1, &nret);
|
||||||
|
if (nret <= ShiftMask) {
|
||||||
|
fprintf(stderr, "Couldn't get keymap for '-' key\n");
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
nscr = ScreenCount(dpy);
|
||||||
|
for (i = 0; i <= 0xff; i++) {
|
||||||
|
if ((i & MODMASK) != 0)
|
||||||
|
continue;
|
||||||
|
for (scr = 0; scr != nscr; scr++) {
|
||||||
|
XGrabKey(dpy, inc_code, i | MODMASK,
|
||||||
|
RootWindow(dpy, scr), 1,
|
||||||
|
GrabModeAsync, GrabModeAsync);
|
||||||
|
XGrabKey(dpy, dec_code, i | MODMASK,
|
||||||
|
RootWindow(dpy, scr), 1,
|
||||||
|
GrabModeAsync, GrabModeAsync);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* mask non-key events for each screan */
|
||||||
|
for (scr = 0; scr != nscr; scr++)
|
||||||
|
XSelectInput(dpy, RootWindow(dpy, scr), KeyPress);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* request initial volume
|
||||||
|
*/
|
||||||
|
if (mio_write(hdl, dumpreq, sizeof(dumpreq)) != sizeof(dumpreq)) {
|
||||||
|
fprintf(stderr, "Failed to request master volume\n");
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
pfds = malloc(sizeof(struct pollfd) * (mio_nfds(hdl) + 1));
|
||||||
|
if (pfds == NULL) {
|
||||||
|
fprintf(stderr, "Failed to allocate pollfd structures\n");
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (background) {
|
||||||
|
verbose = 0;
|
||||||
|
if (daemon(0, 0) < 0) {
|
||||||
|
perror("daemon");
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
while (1) {
|
||||||
|
while (XPending(dpy)) {
|
||||||
|
XNextEvent(dpy, &xev);
|
||||||
|
if (xev.type != KeyPress)
|
||||||
|
continue;
|
||||||
|
if (xev.xkey.keycode == inc_code &&
|
||||||
|
inc_map[xev.xkey.state & ShiftMask] == KEY_INC) {
|
||||||
|
midi_setvol(master + 5);
|
||||||
|
} else if (xev.xkey.keycode == dec_code &&
|
||||||
|
dec_map[xev.xkey.state & ShiftMask] == KEY_DEC) {
|
||||||
|
midi_setvol(master - 5);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
nfds = mio_pollfd(hdl, pfds, POLLIN);
|
||||||
|
pfds[nfds].fd = ConnectionNumber(dpy);
|
||||||
|
pfds[nfds].events = POLLIN;
|
||||||
|
while (poll(pfds, nfds + 1, -1) < 0 && errno == EINTR)
|
||||||
|
; /* nothing */
|
||||||
|
if (mio_revents(hdl, pfds) & POLLIN) {
|
||||||
|
n = mio_read(hdl, msg, MIDIBUFSZ);
|
||||||
|
if (n == 0)
|
||||||
|
break;
|
||||||
|
midi_parse(msg, n);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
XFree(inc_map);
|
||||||
|
XFree(dec_map);
|
||||||
|
XCloseDisplay(dpy);
|
||||||
|
mio_close(hdl);
|
||||||
|
return 0;
|
||||||
|
}
|
Loading…
Reference in New Issue
Block a user