Code

native LIRC support for ncmpc
authorThomas Jansen <mithi@mithi.net>
Fri, 7 Nov 2008 07:16:41 +0000 (08:16 +0100)
committerMax Kellermann <max@duempel.org>
Fri, 7 Nov 2008 07:16:41 +0000 (08:16 +0100)
The attachment includes the patch and a sample .lircrc config for
testing purposes (i. e. only a few commands are mapped to IR events).
The config is rather simple to write: For each button add a block like
this to ~/.lircrc:

begin
     button = <button name from /etc/lircd.conf>
     prog = ncmpc
     config = <command name from src/command.c>
end

The patch is not finished, there are several problems that still need to
be solved:

1. the configure.ac modifications are just for testing purposes and
should be made optional with a parameter like --enable-lirc
for ./configure. Unfortunately I'm not an expert on autoconfig tools.

2. LIRC example code [1] suggests looping over lirc_code2char, probably
to have multiple actions that can be triggered from one button. Perhaps
lirc_event(...) should be moved to lirc.c and be heavily modified, no
longer being a mere copy of keyboard_event(...).

configure.ac
src/Makefile.am
src/lirc.c [new file with mode: 0644]
src/lirc.h [new file with mode: 0644]
src/main.c

index 8611c0da45946dc00f04f6c9d5a7c7c8b859113a..d46045fc5e004c446d67ec40e39558d068e552f7 100644 (file)
@@ -174,6 +174,11 @@ if test "x$use_colors" = "xyes" ; then
     AC_DEFINE([ENABLE_COLORS], [1], [Enable color support])
 fi
 
+dnl test for LIRC support
+AC_CHECK_LIB(lirc_client, lirc_init)
+AC_SUBST(LIRC_LIBS)
+AC_DEFINE([ENABLE_LIRC], [1], [Enable LIRC support])
+
 dnl Debugging 
 AC_MSG_CHECKING([whether to build with debug support])
 AC_ARG_ENABLE([debug], 
index 68af70ddd3b1a671fc3b457a22eafc3d0e657e4c..57d1eb605ac3af7e147a9501668a5a480dd2b2f9 100644 (file)
@@ -37,6 +37,7 @@ ncmpc_headers = \
        screen_browser.h \
        lyrics.h \
        str_pool.h \
+       lirc.h \
        gcc.h
 
 # $Id$
@@ -89,6 +90,10 @@ if ENABLE_LYRICS_SCREEN
 ncmpc_SOURCES += screen_lyrics.c lyrics.c
 endif
 
+if ENABLE_LIRC
+ncmpc_SOURCES += lirc.c
+endif
+
 ncmpc_SOURCES+=${ncmpc_headers}
 
 
diff --git a/src/lirc.c b/src/lirc.c
new file mode 100644 (file)
index 0000000..0ad34ca
--- /dev/null
@@ -0,0 +1,41 @@
+#include <lirc/lirc_client.h>
+#include "lirc.h"
+
+static struct lirc_config *lc = NULL;
+static int lirc_socket = 0;
+
+int ncmpc_lirc_open()
+{
+       if ((lirc_socket = lirc_init("ncmpc", 0)) == -1)
+               return -1;
+
+       if (lirc_readconfig(NULL, &lc, NULL)) {
+               lirc_deinit();
+               return -1;
+       }
+
+       return lirc_socket;
+}
+
+void ncmpc_lirc_close()
+{
+       if (lc)
+               lirc_freeconfig(lc);
+       lirc_deinit();
+}
+
+command_t ncmpc_lirc_get_command()
+{
+       char *code = NULL, *cmd = NULL;
+
+       if (lirc_nextcode(&code) != 0)
+               return CMD_NONE;
+
+       if (lirc_code2char(lc, code, &cmd) != 0)
+               return CMD_NONE;
+
+       if (!cmd)
+               return CMD_NONE;
+
+       return get_key_command_from_name(cmd);
+}
diff --git a/src/lirc.h b/src/lirc.h
new file mode 100644 (file)
index 0000000..9359898
--- /dev/null
@@ -0,0 +1,10 @@
+#ifndef LIRC_H
+#define LIRC_H
+
+#include "command.h"
+
+int ncmpc_lirc_open(void);
+void ncmpc_lirc_close(void);
+command_t ncmpc_lirc_get_command(void);
+
+#endif
index 5f55c490de59f9701e8a7c670a87d8397b43fe2c..49c813a7a49d83523b3b5012a14aee3b46136fca 100644 (file)
 #include "lyrics.h"
 #endif
 
+#ifdef ENABLE_LIRC
+#include "lirc.h"
+#endif
+
 #include <stdlib.h>
 #include <unistd.h>
 #include <signal.h>
@@ -292,6 +296,40 @@ keyboard_event(mpd_unused GIOChannel *source,
        return TRUE;
 }
 
+#ifdef ENABLE_LIRC
+static gboolean
+lirc_event(mpd_unused GIOChannel *source,
+          mpd_unused GIOCondition condition, mpd_unused gpointer data)
+{
+       command_t cmd;
+
+       /* remove the idle timeout; add it later with fresh interval */
+       g_source_remove(idle_source_id);
+
+       if ((cmd = ncmpc_lirc_get_command()) != CMD_NONE) {
+               if (cmd == CMD_QUIT) {
+                       g_main_loop_quit(main_loop);
+                       return FALSE;
+               }
+
+               screen_cmd(mpd, cmd);
+
+               if (cmd == CMD_VOLUME_UP || cmd == CMD_VOLUME_DOWN) {
+                       /* make sure we dont update the volume yet */
+                       g_source_remove(update_source_id);
+                       update_source_id = g_timeout_add(update_interval,
+                                                        timer_mpd_update,
+                                                        GINT_TO_POINTER(TRUE));
+               }
+       }
+
+       screen_update(mpd);
+
+       idle_source_id = g_timeout_add(idle_interval, timer_idle, NULL);
+       return TRUE;
+}
+#endif
+
 /**
  * Check the configured key bindings for errors, and display a status
  * message every 10 seconds.
@@ -321,6 +359,10 @@ main(int argc, const char *argv[])
        const char *charset = NULL;
 #endif
        GIOChannel *keyboard_channel;
+#ifdef ENABLE_LIRC
+       int lirc_socket;
+       GIOChannel *lirc_channel = NULL;
+#endif
 
 #ifdef HAVE_LOCALE_H
        /* time and date formatting */
@@ -426,6 +468,15 @@ main(int argc, const char *argv[])
        keyboard_channel = g_io_channel_unix_new(STDIN_FILENO);
        g_io_add_watch(keyboard_channel, G_IO_IN, keyboard_event, NULL);
 
+#ifdef ENABLE_LIRC
+       /* watch out for lirc input */
+       lirc_socket = ncmpc_lirc_open();
+       if (lirc_socket >= 0) {
+               lirc_channel = g_io_channel_unix_new(lirc_socket);
+               g_io_add_watch(lirc_channel, G_IO_IN, lirc_event, NULL);
+       }
+#endif
+
        /* attempt to connect */
        reconnect_source_id = g_timeout_add(1, timer_reconnect, NULL);
 
@@ -444,6 +495,12 @@ main(int argc, const char *argv[])
        g_main_loop_unref(main_loop);
        g_io_channel_unref(keyboard_channel);
 
+#ifdef ENABLE_LIRC
+       if (lirc_socket >= 0)
+               g_io_channel_unref(lirc_channel);
+       ncmpc_lirc_close();
+#endif
+
        exit_and_cleanup();
        ncu_deinit();