/* * pixelview_remote.c * * Module for handling the PixelView Remote Control. * Roger Hardiman * and Bryan Collins * November 1999. * * Based on the FXTV driver for Hauppauge cards from Jukka Simila * * (C) 1999 Roger Hardiman, Bryan Collins * * 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 "pixelview_remote.h" #include "remote.h" #include "tvdebug.h" #include "tvutil.h" #include "glob.h" static struct key { int code; char *name; int isnumeric; } PIXELVIEW_keys[] = { {10, "TrackDn", 0 }, {42, "Eject", 0 }, {63, "Text/cc", 0 }, {64, "0", 1 }, {65, "Scan", 0 }, {66, "SeekBk", 0 }, {71, "Mute", 0 }, {72, "Recall", 0 }, {73, "ChanUp", 0 }, {74, "VolUp", 0 }, {95, "10+", 0 }, {96, "4", 1 }, {97, "9", 1 }, {98, "5", 1 }, {103, "TrackUp", 0 }, {104, "Pause", 0 }, {105, "+/-", 0 }, {106, "VolDn", 0 }, {138, "Stop", 0 }, {170, "Power", 0 }, {191, "Zoom", 0 }, {192, "7", 1 }, {193, "ChanDn", 0 }, {194, "8", 1 }, {199, "SeekFw", 0 }, {200, "2", 1 }, {201, "6", 1 }, {202, "Play", 0 }, {223, "MTS", 0 }, {224, "1", 1 }, {225, "Source", 0 }, {231, "TV/FM", 0 }, {232, "3", 1 } }; #define NUM_KEYS (sizeof(PIXELVIEW_keys) / sizeof(struct key)) #define ELAPSED_MSEC(t1,t2) \ (( (t2).tv_usec - (t1).tv_usec ) / 1000 + \ ( (t2).tv_sec - (t1).tv_sec ) * 1000) static TVREMOTE_CB_FUNCT *PixelViewRemote_cb = NULL; static int NumericKeysCountdownTimer = 0; /* Time delay before sending a simulated ENTER keypress */ /**@BEGINFUNC************************************************************** Prototype : static int Debounce( int key) Purpose : Debounce the current key event Programmer : 17-May-98 Randall Hopper, 3-Nov-99 Bryan Collins Parameters : key - I: key event Returns : T = process key Globals : None. **@ENDFUNC*****************************************************************/ static int Debounce( int key) { static struct { int keycode; struct timeval time_1; struct timeval time_last; int skipped; } Deb; struct timeval time_cur; int process = 0; /* Update current time */ gettimeofday( &time_cur, NULL ); /* Handle other keys */ /* If new key, or last press too old, restart debounce */ if (( key != Deb.keycode ) || ( ELAPSED_MSEC( Deb.time_last, time_cur ) >= 500 )) { Deb.keycode = key; Deb.time_1 = time_cur; Deb.skipped = 0; process = 1; } else if ( ELAPSED_MSEC( Deb.time_1, time_cur ) >= 500 ) { /* If same key, hit lately, been a while since 1st hit, */ /* and we've skipped a few occurances of this key (i.e. */ /* we're pretty sure they're holding it down) */ /* process and let key repeat. */ if ( Deb.skipped >= 6 ) process = 1; /* If same key, hit lately, been a while since 1st hit, */ /* and we "haven't" skipped a few occurances of this key, */ /* it's likely that the user is just pressing it fast (channel */ /* surfing), not just holding it down. Process and restart */ /* debounce. */ else { Deb.keycode = key; Deb.time_1 = time_cur; Deb.skipped = 0; process = 1; } } /* If same key, hit lately, and "hasn't" been a while, debounce */ else { process = 0; Deb.skipped++; } Deb.time_last = time_cur; return process; } static void PixelViewRemote(XtPointer cl_data, XtIntervalId *timer) { static unsigned int old_key; TV_CAPTURE *c = &G_glob.capture; int i2c_read_addr, data; int key_code; int j; /* Use the IOCTL to read I2C devices */ i2c_read_addr = 0xc9; data = i2c_read_addr << 16; ioctl(c->tfd, BT848_I2CWR , &data); /* The PixelView Remote returns 1 byte */ key_code = data & 0xff; if (key_code != 0xff) { /* Ignore 0xff */ for(j=0;j\n", PIXELVIEW_keys[j].name )); PixelViewRemote_cb(PIXELVIEW_keys[j].name); /* Register the keypress */ /* The PixelView 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 (PIXELVIEW_keys[j].isnumeric == 1) NumericKeysCountdownTimer = 20; } else { RMPRINTF(("TVPIXELVIEWREMOTE: Unknown key event...skipped\n")); } } old_key = key_code; if (NumericKeysCountdownTimer > 0) { NumericKeysCountdownTimer--; if (NumericKeysCountdownTimer == 0) { /* Send the ENTER Key */ PixelViewRemote_cb("ENTER"); } } XtAppAddTimeOut(TVAPPCTX, 60, PixelViewRemote, NULL); } /* Open up the remote and hook in callbacks */ void TVPIXELVIEWREMOTEOpen( XtAppContext app_ctx, TVREMOTE_CB_FUNCT *cb ) { if ( PixelViewRemote_cb ) { fprintf( stderr, "TVPIXELVIEWREMOTEOpen: ERROR: Already open.\n" ); exit(1); } PixelViewRemote_cb=cb; /* FIXME: Probably want to suspend this timer while we're doing */ /* time critical things like capturing video/etc. */ XtAppAddTimeOut( app_ctx, 200, PixelViewRemote, NULL ); RMPRINTF(( "TVPIXELVIEWREMOTE: Ready.\n" )); } /* Clean out the event queue in case we get backed up during */ /* extended event processing. */ void TVPIXELVIEWREMOTEFlush( void ) { }