From 5ab306402d9efcceb3cc7b1097602c45365f12bd Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Sun, 9 Jan 2005 01:11:53 +0000 Subject: * add new module module-mmkbd-evdev * fix stupid error message in main.c git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@337 fefdeb5f-60dc-0310-8127-8f9354f1896f --- configure.ac | 3 + doc/todo | 2 +- polyp/Makefile.am | 18 +++- polyp/main.c | 3 +- polyp/module-lirc.c | 1 - polyp/module-mmkbd-evdev.c | 225 +++++++++++++++++++++++++++++++++++++++++++++ polyp/pdispatch.c | 2 +- 7 files changed, 249 insertions(+), 5 deletions(-) create mode 100644 polyp/module-mmkbd-evdev.c diff --git a/configure.ac b/configure.ac index 644c4050..1bf49291 100644 --- a/configure.ac +++ b/configure.ac @@ -174,6 +174,9 @@ AC_SUBST(LIRC_CFLAGS) AC_SUBST(LIRC_LIBS) AM_CONDITIONAL([HAVE_LIRC], [test "x$HAVE_LIRC" = x1]) +AC_CHECK_HEADER(linux/input.h,HAVE_EVDEV=1,HAVE_EVDEV=0) +AM_CONDITIONAL([HAVE_EVDEV], [test "x$HAVE_EVDEV" = x1]) + # If using GCC specify some additional parameters if test "x$GCC" = "xyes" ; then CFLAGS="$CFLAGS -pipe -W -Wall -pedantic" diff --git a/doc/todo b/doc/todo index 3292342a..fd024778 100644 --- a/doc/todo +++ b/doc/todo @@ -6,6 +6,7 @@ Architectural changes: - add API for synchronizing multiple sinks/sources to a common clock - absolutely indexed write()s from client - remove "polyplib-" prefix +- hardware volume support Fixes: - improve module-oss-mmap latency measurement @@ -20,7 +21,6 @@ Features: - rendezvous autotunnel module - polish for starting polypaudio as root/system-wide instance - export connection fd -- /dev/input/event plugin Long term: - pass meta info for hearing impaired diff --git a/polyp/Makefile.am b/polyp/Makefile.am index 95a80ec1..72731c1d 100644 --- a/polyp/Makefile.am +++ b/polyp/Makefile.am @@ -160,7 +160,8 @@ SYMDEF_FILES= \ module-null-sink-symdef.h \ module-esound-sink-symdef.h \ module-zeroconf-publish-symdef.h \ - module-lirc-symdef.h + module-lirc-symdef.h \ + module-mmkbd-evdev-symdef.h EXTRA_DIST+=$(SYMDEF_FILES) BUILT_SOURCES+=$(SYMDEF_FILES) @@ -707,6 +708,21 @@ module_lirc_la_CFLAGS = $(AM_CFLAGS) $(LIRC_CFLAGS) endif + +### Linux evdev + +if HAVE_EVDEV + +modlib_LTLIBRARIES+= \ + module-mmkbd-evdev.la + +module_mmkbd_evdev_la_SOURCES = module-mmkbd-evdev.c +module_mmkbd_evdev_la_LDFLAGS = -module -avoid-version +module_mmkbd_evdev_la_LIBADD = $(AM_LIBADD) +module_mmkbd_evdev_la_CFLAGS = $(AM_CFLAGS) + +endif + ### libpolypcore (needs to be updated) if BUILD_LIBPOLYPCORE diff --git a/polyp/main.c b/polyp/main.c index c5b3a7e8..51c41439 100644 --- a/polyp/main.c +++ b/polyp/main.c @@ -309,7 +309,8 @@ int main(int argc, char *argv[]) { if (conf->use_pid_file) { if (pa_pid_file_create() < 0) { - pa_loop_write(daemon_pipe[1], &retval, sizeof(retval)); + if (conf->daemonize) + pa_loop_write(daemon_pipe[1], &retval, sizeof(retval)); goto finish; } diff --git a/polyp/module-lirc.c b/polyp/module-lirc.c index b400be12..4cfc09de 100644 --- a/polyp/module-lirc.c +++ b/polyp/module-lirc.c @@ -31,7 +31,6 @@ #include #include "module.h" -#include "iochannel.h" #include "log.h" #include "module-lirc-symdef.h" #include "namereg.h" diff --git a/polyp/module-mmkbd-evdev.c b/polyp/module-mmkbd-evdev.c new file mode 100644 index 00000000..758aaae5 --- /dev/null +++ b/polyp/module-mmkbd-evdev.c @@ -0,0 +1,225 @@ +/* $Id$ */ + +/*** + This file is part of polypaudio. + + polypaudio is free software; you can redistribute it and/or modify + it under the terms of the GNU Lesser General Public License as published + by the Free Software Foundation; either version 2 of the License, + or (at your option) any later version. + + polypaudio 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 Lesser General Public License + along with polypaudio; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 + USA. +***/ + +#ifdef HAVE_CONFIG_H +#include +#endif + +#include +#include +#include +#include +#include +#include +#include + +#include + +#include "module.h" +#include "log.h" +#include "module-mmkbd-evdev-symdef.h" +#include "namereg.h" +#include "sink.h" +#include "xmalloc.h" +#include "modargs.h" +#include "util.h" + +PA_MODULE_AUTHOR("Lennart Poettering") +PA_MODULE_DESCRIPTION("Multimedia keyboard support via Linux evdev") +PA_MODULE_VERSION(PACKAGE_VERSION) +PA_MODULE_USAGE("device= sink=") + +#define DEFAULT_DEVICE "/dev/input/event0" + +static const char* const valid_modargs[] = { + "device", + "sink", + NULL, +}; + +struct userdata { + int fd; + struct pa_io_event *io; + char *sink_name; + struct pa_module *module; + float mute_toggle_save; +}; + +static void io_callback(struct pa_mainloop_api *io, struct pa_io_event *e, int fd, enum pa_io_event_flags events, void*userdata) { + struct userdata *u = userdata; + assert(io); + assert(u); + + if (events & (PA_IO_EVENT_HANGUP|PA_IO_EVENT_ERROR)) { + pa_log(__FILE__": lost connection to evdev device.\n"); + goto fail; + } + + if (events & PA_IO_EVENT_INPUT) { + struct input_event e; + + if (pa_loop_read(u->fd, &e, sizeof(e)) <= 0) { + pa_log(__FILE__": failed to read from event device: %s\n", strerror(errno)); + goto fail; + } + + if (e.type == EV_KEY && (e.value == 1 || e.value == 2)) { + enum { INVALID, UP, DOWN, MUTE_TOGGLE } volchange = INVALID; + + pa_log_debug(__FILE__": key code=%u, value=%u\n", e.code, e.value); + + switch (e.code) { + case KEY_VOLUMEDOWN: volchange = DOWN; break; + case KEY_VOLUMEUP: volchange = UP; break; + case KEY_MUTE: volchange = MUTE_TOGGLE; break; + } + + if (volchange != INVALID) { + struct pa_sink *s; + + if (!(s = pa_namereg_get(u->module->core, u->sink_name, PA_NAMEREG_SINK, 1))) + pa_log(__FILE__": failed to get sink '%s'\n", u->sink_name); + else { + double v = pa_volume_to_user(s->volume); + + switch (volchange) { + case UP: v += .05; break; + case DOWN: v -= .05; break; + case MUTE_TOGGLE: { + + if (v > 0) { + u->mute_toggle_save = v; + v = 0; + } else + v = u->mute_toggle_save; + } + default: + ; + } + + pa_sink_set_volume(s, pa_volume_from_user(v)); + } + } + } + } + + return; + +fail: + u->module->core->mainloop->io_free(u->io); + u->io = NULL; + + pa_module_unload_request(u->module); +} + +#define test_bit(bit, array) (array[bit/8] & (1<<(bit%8))) + +int pa__init(struct pa_core *c, struct pa_module*m) { + struct pa_modargs *ma = NULL; + struct userdata *u; + int version; + struct input_id input_id; + char name[256]; + uint8_t evtype_bitmask[EV_MAX/8 + 1]; + assert(c && m); + + if (!(ma = pa_modargs_new(m->argument, valid_modargs))) { + pa_log(__FILE__": Failed to parse module arguments\n"); + goto fail; + } + + m->userdata = u = pa_xmalloc(sizeof(struct userdata)); + u->module = m; + u->io = NULL; + u->sink_name = pa_xstrdup(pa_modargs_get_value(ma, "sink", NULL)); + u->fd = -1; + u->mute_toggle_save = 0; + + if ((u->fd = open(pa_modargs_get_value(ma, "device", DEFAULT_DEVICE), O_RDONLY)) < 0) { + pa_log(__FILE__": failed to open evdev device: %s\n", strerror(errno)); + goto fail; + } + + if (ioctl(u->fd, EVIOCGVERSION, &version) < 0) { + pa_log(__FILE__": EVIOCGVERSION failed: %s\n", strerror(errno)); + goto fail; + } + + pa_log_info(__FILE__": evdev driver version %i.%i.%i\n", version >> 16, (version >> 8) & 0xff, version & 0xff); + + if(ioctl(u->fd, EVIOCGID, &input_id)) { + pa_log(__FILE__": EVIOCGID failed: %s\n", strerror(errno)); + goto fail; + } + + pa_log_info(__FILE__": evdev vendor 0x%04hx product 0x%04hx version 0x%04hx bustype %u\n", + input_id.vendor, input_id.product, input_id.version, input_id.bustype); + + if(ioctl(u->fd, EVIOCGNAME(sizeof(name)), name) < 0) { + pa_log(__FILE__": EVIOCGNAME failed: %s\n", strerror(errno)); + goto fail; + } + + pa_log_info(__FILE__": evdev device name: %s\n", name); + + memset(evtype_bitmask, 0, sizeof(evtype_bitmask)); + if (ioctl(u->fd, EVIOCGBIT(0, EV_MAX), evtype_bitmask) < 0) { + pa_log(__FILE__": EVIOCGBIT failed: %s\n", strerror(errno)); + goto fail; + } + + if (!test_bit(EV_KEY, evtype_bitmask)) { + pa_log(__FILE__": device has no keys.\n"); + goto fail; + } + + u->io = c->mainloop->io_new(c->mainloop, u->fd, PA_IO_EVENT_INPUT|PA_IO_EVENT_HANGUP, io_callback, u); + + pa_modargs_free(ma); + + return 0; + +fail: + + if (ma) + pa_modargs_free(ma); + + pa__done(c, m); + return -1; +} + +void pa__done(struct pa_core *c, struct pa_module*m) { + struct userdata *u; + assert(c); + assert(m); + + if (!(u = m->userdata)) + return; + + if (u->io) + m->core->mainloop->io_free(u->io); + + if (u->fd >= 0) + close(u->fd); + + pa_xfree(u->sink_name); + pa_xfree(u); +} diff --git a/polyp/pdispatch.c b/polyp/pdispatch.c index 90de345f..7a9e9c68 100644 --- a/polyp/pdispatch.c +++ b/polyp/pdispatch.c @@ -33,7 +33,7 @@ #include "llist.h" #include "log.h" -/* #define DEBUG_OPCODES */ +/*#define DEBUG_OPCODES */ #ifdef DEBUG_OPCODES -- cgit