/* * haup_remote.c * * Module for handling the Hauppauge Remote Control. * Jukka Simila October 1999 * * Based on Demonstration of Hauppauge Remote Control by Roger Hardiman * February 1999 * * (C) 1999 Jukka Simila * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are * met: 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. 2. * Redistributions in binary form must reproduce the above copyright notice, * this list of conditions and the following disclaimer in the documentation * and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND ANY * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE * DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE FOR * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * */ #include #include #include #include #include #ifdef __NetBSD__ # include #endif #ifdef __FreeBSD__ #include #if __FreeBSD_version > 500000 #include #include #else #include #include #endif #endif #include "haup_remote.h" #include "remote.h" #include "tvdebug.h" #include "tvutil.h" #include "glob.h" static struct { int code; char *name; int is_numeric; } HAUP_keys[] = { { 0, "0", 1 }, { 4, "1", 1 }, { 8, "2", 1 }, { 12, "3", 1 }, { 16, "4", 1 }, { 20, "5", 1 }, { 24, "6", 1 }, { 28, "7", 1 }, { 32, "8", 1 }, { 36, "9", 1 }, { 48, "Radio", 0 }, { 52, "Mute", 0 }, { 60, "Tv", 0 }, { 64, "VolUp", 0 }, { 68, "VolDn", 0 }, {120, "Reserved", 0 }, {128, "ChanUp", 0 }, {132, "ChanDn", 0 }, {136, "Source", 0 }, {152, "Minimize", 0 }, {184, "FullScreen", 0 } }; #define NUM_KEYS (sizeof(HAUP_keys) / sizeof(HAUP_keys[0])) static TVREMOTE_CB_FUNCT *HaupRemote_cb = NULL; static int NumericKeysCountdownTimer = 0; /* Time delay before sending a simulated ENTER keypress */ static void HaupRemote(XtPointer cl_data, XtIntervalId *timer) { static unsigned char last_valid_b1; static int first_pass_complete = 0; TV_CAPTURE *c = &G_glob.capture; unsigned char b1, b2, b3; struct bktr_remote remote; int j; ioctl(c->tfd, REMOTE_GETKEY, &remote); /* The Hauppauge IR Remote returns 3 bytes */ b1 = remote.data[0]; b2 = remote.data[1]; b3 = remote.data[2]; /* On the first pass, initialise last_valid_b1. This means we ignore any */ /* left over key presses lurking in the IR Receiver's buffer */ if (first_pass_complete == 0) { last_valid_b1 = b1; first_pass_complete = 1; } /* only sequences starting 192 and 224 are valid. 000 and 255 are invalid */ if ((b1 == 224) || (b1 == 192)) { /* most keys do not have auto repeat except the volume */ if ((b2 == 64) || (b2 == 68)) /* VolUp and VolDn */ { for (j=0; j < NUM_KEYS; j++) if (b2==HAUP_keys[j].code) break; if (j< NUM_KEYS) { RMPRINTF(( "TVHAUPREMOTE: KEY EVENT = <%s>\n", HAUP_keys[j].name )); HaupRemote_cb(HAUP_keys[j].name); /* Register the keypress */ } else RMPRINTF(("TVHAUPREMOTE: Unknown key event...skipped\n")); last_valid_b1 = 0; } /* if the toggle code has changed, this is a new keypress */ else if (b1 != last_valid_b1) { for (j=0; j < NUM_KEYS; j++) if (b2==HAUP_keys[j].code) break; if (j\n", HAUP_keys[j].name )); HaupRemote_cb(HAUP_keys[j].name); /* Register the keypress */ /* The Hauppauge remote has no ENTER key, so for numeric */ /* entries, we set up to simulate an ENTER keypress */ /* after N invocations of this timer callback. */ /* NOTE: Numeric keys = '0'..'9'. */ if (HAUP_keys[j].is_numeric == 1) NumericKeysCountdownTimer = 20; } else RMPRINTF(("TVHAUPREMOTE: Unknown key event...skipped\n")); last_valid_b1 = b1; } } if (NumericKeysCountdownTimer > 0) { NumericKeysCountdownTimer--; if (NumericKeysCountdownTimer == 0) { /* Send the ENTER Key */ HaupRemote_cb("ENTER"); } } XtAppAddTimeOut(TVAPPCTX, 60, HaupRemote, NULL); } /* Open up the remote and hook in callbacks */ void TVHAUPREMOTEOpen( XtAppContext app_ctx, TVREMOTE_CB_FUNCT *cb ) { if ( HaupRemote_cb ) { fprintf( stderr, "TVHAUPREMOTEOpen: ERROR: Already open.\n" ); exit(1); } HaupRemote_cb=cb; /* FIXME: Probably want to suspend this timer while we're doing */ /* time critical things like capturing video/etc. */ XtAppAddTimeOut( app_ctx, 200, HaupRemote, NULL ); RMPRINTF(( "TVHAUPREMOTE: Ready.\n" )); } /* Clean out the event queue in case we get backed up during */ /* extended event processing. */ void TVHAUPREMOTEFlush( void ) { }