diff options
| -rw-r--r-- | configure.ac | 7 | ||||
| -rw-r--r-- | polyp/Makefile.am | 20 | ||||
| -rw-r--r-- | polyp/module-lirc.c | 221 | ||||
| -rw-r--r-- | polyp/module-match.c | 6 | ||||
| -rw-r--r-- | polyp/module-oss.c | 1 | 
5 files changed, 248 insertions, 7 deletions
| diff --git a/configure.ac b/configure.ac index e287f279..644c4050 100644 --- a/configure.ac +++ b/configure.ac @@ -167,6 +167,13 @@ AC_MSG_RESULT(yes)],  AC_SUBST(LIBWRAP_LIBS)  LIBS="$saved_LIBS" +HAVE_LIRC=1 +AC_CHECK_HEADER(lirc/lirc_client.h,[AC_CHECK_LIB(lirc_client,lirc_init,,HAVE_LIRC=0)],HAVE_LIRC=0) +LIRC_LIBS=-llirc_client +AC_SUBST(LIRC_CFLAGS) +AC_SUBST(LIRC_LIBS) +AM_CONDITIONAL([HAVE_LIRC], [test "x$HAVE_LIRC" = x1]) +  # If using GCC specify some additional parameters  if test "x$GCC" = "xyes" ; then     CFLAGS="$CFLAGS -pipe -W -Wall -pedantic" diff --git a/polyp/Makefile.am b/polyp/Makefile.am index 352e6a7a..95a80ec1 100644 --- a/polyp/Makefile.am +++ b/polyp/Makefile.am @@ -159,7 +159,8 @@ SYMDEF_FILES= \  		module-tunnel-source-symdef.h \  		module-null-sink-symdef.h \  		module-esound-sink-symdef.h \ -		module-zeroconf-publish-symdef.h +		module-zeroconf-publish-symdef.h \ +		module-lirc-symdef.h  EXTRA_DIST+=$(SYMDEF_FILES)  BUILT_SOURCES+=$(SYMDEF_FILES) @@ -242,7 +243,8 @@ libsocket_server_la_LIBADD = $(AM_LIBADD) libiochannel.la libsocket-util.la $(LI  libsocket_client_la_SOURCES = socket-client.c socket-client.h  libsocket_client_la_LDFLAGS = -avoid-version -libsocket_client_la_LIBADD = $(AM_LIBADD) libiochannel.la libsocket-util.la libparseaddr.la +libsocket_client_la_LIBADD = $(AM_LIBADD) libiochannel.la libsocket-util.la libparseaddr.la $(LIBASYNCNS_LIBS) +libsocket_client_la_CFLAGS = $(AM_CFLAGS) $(LIBASYNCNS_CFLAGS)  libparseaddr_la_SOURCES = parseaddr.c parseaddr.h  libparseaddr_la_LDFLAGS = -avoid-version @@ -691,6 +693,20 @@ mainloop_test_glib12_LDADD = $(mainloop_test_LDADD) $(GLIB12_LIBS) libpolyp-main  endif +### LIRC support + +if HAVE_LIRC + +modlib_LTLIBRARIES+= \ +		module-lirc.la + +module_lirc_la_SOURCES = module-lirc.c +module_lirc_la_LDFLAGS = -module -avoid-version +module_lirc_la_LIBADD = $(AM_LIBADD) $(LIRC_LIBS)  +module_lirc_la_CFLAGS = $(AM_CFLAGS) $(LIRC_CFLAGS) + +endif +  ### libpolypcore (needs to be updated)  if BUILD_LIBPOLYPCORE diff --git a/polyp/module-lirc.c b/polyp/module-lirc.c new file mode 100644 index 00000000..a68b5b99 --- /dev/null +++ b/polyp/module-lirc.c @@ -0,0 +1,221 @@ +/* $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 <config.h> +#endif + +#include <stdio.h> +#include <assert.h> +#include <unistd.h> +#include <string.h> +#include <lirc/lirc_client.h> +#include <stdlib.h> + +#include "module.h" +#include "iochannel.h" +#include "log.h" +#include "module-lirc-symdef.h" +#include "namereg.h" +#include "sink.h" +#include "xmalloc.h" +#include "modargs.h" + +PA_MODULE_AUTHOR("Lennart Poettering") +PA_MODULE_DESCRIPTION("LIRC volume control") +PA_MODULE_VERSION(PACKAGE_VERSION) +PA_MODULE_USAGE("config=<config file> sink=<sink name>") + +static const char* const valid_modargs[] = { +    "config", +    "sink", +    NULL, +}; + +struct userdata { +    int lirc_fd; +    struct pa_io_event *io; +    struct lirc_config *config; +    char *sink_name; +    struct pa_module *module; +    float mute_toggle_save; +}; + +static int lirc_in_use = 0; + +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; +    char *name = NULL, *code = NULL; +    assert(io); +    assert(u); + +    if (events & (PA_IO_EVENT_HANGUP|PA_IO_EVENT_ERROR)) { +        pa_log(__FILE__": lost connection to LIRC daemon.\n"); +        goto fail; +    } +         +    if (events & PA_IO_EVENT_INPUT) { +        char *c; +         +        if (lirc_nextcode(&code) != 0 || !code) { +            pa_log(__FILE__": lirc_nextcode() failed.\n"); +            goto fail; +        } +         +        c = pa_xstrdup(code); +        c[strcspn(c, "\n\r")] = 0; +        pa_log_debug(__FILE__": raw IR code '%s'\n", c); +        pa_xfree(c); +         +        while (lirc_code2char(u->config, code, &name) == 0 && name) { +            enum { INVALID, UP, DOWN, MUTE, RESET, MUTE_TOGGLE } volchange = INVALID; +             +            pa_log_info(__FILE__": translated IR code '%s'\n", name); +             +            if (strcasecmp(name, "volume-up") == 0) +                volchange = UP; +            else if (strcasecmp(name, "volume-down") == 0) +                volchange = DOWN; +            else if (strcasecmp(name, "mute") == 0) +                volchange = MUTE; +            else if (strcasecmp(name, "mute-toggle") == 0) +                volchange = MUTE_TOGGLE; +            else if (strcasecmp(name, "reset") == 0) +                volchange = RESET; +             +            if (volchange == INVALID) +                pa_log_warn(__FILE__": recieved unknown IR code '%s'\n", name); +            else { +                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:     v  =  0; break; +                        case RESET:    v  =  1; 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)); +                } +            } +        } +    } + +    free(code); + +    return; +     +fail: +    u->module->core->mainloop->io_free(u->io); +    u->io = NULL; + +    pa_module_unload_request(u->module); + +    free(code); +} +     +int pa__init(struct pa_core *c, struct pa_module*m) { +    struct pa_modargs *ma = NULL; +    struct userdata *u; +    assert(c && m); + +    if (lirc_in_use) { +        pa_log(__FILE__": module-lirc may no be loaded twice.\n"); +        return -1; +    } +     +    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->config = NULL; +    u->sink_name = pa_xstrdup(pa_modargs_get_value(ma, "sink", NULL)); +    u->lirc_fd = -1; +    u->mute_toggle_save = 0; + +    if ((u->lirc_fd = lirc_init("polypaudio", 1)) < 0) { +        pa_log(__FILE__": lirc_init() failed.\n"); +        goto fail; +    } + +    if (lirc_readconfig((char*) pa_modargs_get_value(ma, "config", NULL), &u->config, NULL) < 0) { +        pa_log(__FILE__": lirc_readconfig() failed.\n"); +        goto fail; +    } +     +    u->io = c->mainloop->io_new(c->mainloop, u->lirc_fd, PA_IO_EVENT_INPUT|PA_IO_EVENT_HANGUP, io_callback, u); + +    lirc_in_use = 1; + +    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->config) +        lirc_freeconfig(u->config); + +    if (u->lirc_fd >= 0) +        lirc_deinit(); + +    pa_xfree(u->sink_name); +    pa_xfree(u); + +    lirc_in_use = 0; +} diff --git a/polyp/module-match.c b/polyp/module-match.c index 9d969b31..3599a830 100644 --- a/polyp/module-match.c +++ b/polyp/module-match.c @@ -179,12 +179,10 @@ static void callback(struct pa_core *c, enum pa_subscription_event_type t, uint3  int pa__init(struct pa_core *c, struct pa_module*m) {      struct pa_modargs *ma = NULL; -    const char *table_file;      struct userdata *u;      assert(c && m); -    if (!(ma = pa_modargs_new(m->argument, valid_modargs)) || -        !(table_file = pa_modargs_get_value(ma, "table", NULL))) { +    if (!(ma = pa_modargs_new(m->argument, valid_modargs))) {          pa_log(__FILE__": Failed to parse module arguments\n");          goto fail;      } @@ -194,7 +192,7 @@ int pa__init(struct pa_core *c, struct pa_module*m) {      u->subscription = NULL;      m->userdata = u; -    if (load_rules(u, table_file) < 0) +    if (load_rules(u, pa_modargs_get_value(ma, "table", NULL)) < 0)          goto fail;      u->subscription = pa_subscription_new(c, PA_SUBSCRIPTION_MASK_SINK_INPUT, callback, u); diff --git a/polyp/module-oss.c b/polyp/module-oss.c index 67922d82..02acc6f4 100644 --- a/polyp/module-oss.c +++ b/polyp/module-oss.c @@ -295,7 +295,6 @@ int pa__init(struct pa_core *c, struct pa_module*m) {      pa_log_info(__FILE__": device opened in %s mode.\n", mode == O_WRONLY ? "O_WRONLY" : (mode == O_RDONLY ? "O_RDONLY" : "O_RDWR")); -      if (nfrags >= 2 && frag_size >= 1)          if (pa_oss_set_fragments(fd, nfrags, frag_size) < 0)                 goto fail;    | 
