Index: libs/libmythtv/tv_play.cpp
===================================================================
--- libs/libmythtv/tv_play.cpp	(revision 8113)
+++ libs/libmythtv/tv_play.cpp	(working copy)
@@ -52,12 +52,12 @@
 
 void TV::InitKeys(void)
 {
-    REG_KEY("TV Frontend", "PAGEUP", "Page Up", "3");
-    REG_KEY("TV Frontend", "PAGEDOWN", "Page Down", "9");
+    REG_KEY("TV Frontend", "PAGEUP", "Page Up", "3,remote3");
+    REG_KEY("TV Frontend", "PAGEDOWN", "Page Down", "9,remote9");
     REG_KEY("TV Frontend", "DELETE", "Delete Program", "D");
-    REG_KEY("TV Frontend", "PLAYBACK", "Play Program", "P");
+    REG_KEY("TV Frontend", "PLAYBACK", "Play Program", "P,remotePlay");
     REG_KEY("TV Frontend", "TOGGLERECORD", "Toggle recording status of current "
-            "program", "R");
+            "program", "R,remoteRecord");
     REG_KEY("TV Frontend", "DAYLEFT", "Page the program guide back one day", 
             "Home,7");
     REG_KEY("TV Frontend", "DAYRIGHT", "Page the program guide forward one day",
@@ -80,37 +80,37 @@
     REG_KEY("TV Frontend", "DETAILS", "Show program details", "U");
 
     REG_KEY("TV Playback", "CLEAROSD", "Clear OSD", "Backspace");
-    REG_KEY("TV Playback", "PAUSE", "Pause", "P");
+    REG_KEY("TV Playback", "PAUSE", "Pause", "P,remotePause");
     REG_KEY("TV Playback", "DELETE", "Delete Program", "D");
-    REG_KEY("TV Playback", "SEEKFFWD", "Fast Forward", "Right");
-    REG_KEY("TV Playback", "SEEKRWND", "Rewind", "Left");
-    REG_KEY("TV Playback", "ARBSEEK", "Arbitrary Seek", "*");
-    REG_KEY("TV Playback", "CHANNELUP", "Channel up", "Up");
-    REG_KEY("TV Playback", "CHANNELDOWN", "Channel down", "Down");
+    REG_KEY("TV Playback", "SEEKFFWD", "Fast Forward", "Right,remoteRight");
+    REG_KEY("TV Playback", "SEEKRWND", "Rewind", "Left,remoteLeft");
+    REG_KEY("TV Playback", "ARBSEEK", "Arbitrary Seek", "*,remote*");
+    REG_KEY("TV Playback", "CHANNELUP", "Channel up", "Up,remoteCh+");
+    REG_KEY("TV Playback", "CHANNELDOWN", "Channel down", "Down,remoteCh-");
     REG_KEY("TV Playback", "NEXTFAV", "Switch to the next favorite channel",
             "/");
     REG_KEY("TV Playback", "PREVCHAN", "Switch to the previous channel", "H");
-    REG_KEY("TV Playback", "JUMPFFWD", "Jump ahead", "PgDown");
-    REG_KEY("TV Playback", "JUMPRWND", "Jump back", "PgUp");
+    REG_KEY("TV Playback", "JUMPFFWD", "Jump ahead", "PgDown,remoteDown");
+    REG_KEY("TV Playback", "JUMPRWND", "Jump back", "PgUp,remoteUp");
     REG_KEY("TV Playback", "JUMPBKMRK", "Jump to bookmark", "K");
     REG_KEY("TV Playback", "FFWDSTICKY", "Fast Forward (Sticky) or Forward one "
-            "frame while paused", ">,.");
+            "frame while paused", ">,.,remoteFastForward");
     REG_KEY("TV Playback", "RWNDSTICKY", "Rewind (Sticky) or Rewind one frame "
-            "while paused", ",,<");
+            "while paused", ",,<,remoteRewind");
     REG_KEY("TV Playback", "TOGGLEINPUTS", "Toggle Inputs", "C");
     REG_KEY("TV Playback", "SWITCHCARDS", "Switch Capture Cards", "Y");
-    REG_KEY("TV Playback", "SKIPCOMMERCIAL", "Skip Commercial", "Z,End");
+    REG_KEY("TV Playback", "SKIPCOMMERCIAL", "Skip Commercial", "Z,End,remoteSkipForward");
     REG_KEY("TV Playback", "SKIPCOMMBACK", "Skip Commercial (Reverse)",
-            "Q,Home");
+            "Q,Home,remoteSkipBackward");
     REG_KEY("TV Playback", "JUMPSTART", "Jump to the start of the recording.", "Ctrl+B");            
     REG_KEY("TV Playback", "TOGGLEBROWSE", "Toggle channel browse mode", "O");
     REG_KEY("TV Playback", "TOGGLERECORD", "Toggle recording status of current "
-            "program", "R");
+            "program", "R,remoteRecord");
     REG_KEY("TV Playback", "TOGGLEFAV", "Toggle the current channel as a "
             "favorite", "?");
-    REG_KEY("TV Playback", "VOLUMEDOWN", "Volume down", "[,{,F10");
-    REG_KEY("TV Playback", "VOLUMEUP", "Volume up", "],},F11");
-    REG_KEY("TV Playback", "MUTE", "Mute", "|,\\,F9");
+    REG_KEY("TV Playback", "VOLUMEDOWN", "Volume down", "[,{,F10,remoteVol+");
+    REG_KEY("TV Playback", "VOLUMEUP", "Volume up", "],},F11,remoteVol-");
+    REG_KEY("TV Playback", "MUTE", "Mute", "|,\\,F9,remoteMute");
     REG_KEY("TV Playback", "TOGGLEPIPMODE", "Toggle Picture-in-Picture mode",
             "V");
     REG_KEY("TV Playback", "TOGGLEPIPWINDOW", "Toggle active PiP window", "B");
@@ -137,9 +137,9 @@
     REG_KEY("TV Playback", "TOGGLERECCONTROLS", "Turn on the recording picture "
             "adjustment controls", "G");
     REG_KEY("TV Playback", "TOGGLEEDIT", "Start Edit Mode", "E");
-    REG_KEY("TV Playback", "GUIDE", "Show the Program Guide", "S");
+    REG_KEY("TV Playback", "GUIDE", "Show the Program Guide", "S,remoteGuide");
     REG_KEY("TV Playback", "TOGGLESLEEP", "Toggle the Sleep Timer", "F8");
-    REG_KEY("TV Playback", "PLAY", "Play", "Ctrl+P");
+    REG_KEY("TV Playback", "PLAY", "Play", "Ctrl+P,remotePlay");
     REG_KEY("TV Playback", "NEXTAUDIO", "Switch to the next audio track", "+");
     REG_KEY("TV Playback", "PREVAUDIO", "Switch to the previous audio track", "-");
     REG_KEY("TV Playback", "NEXTSUBTITLE", "Switch to the next subtitle track", "");
@@ -151,13 +151,13 @@
     REG_KEY("TV Editing", "INVERTMAP", "Invert Begin/End cut points", "I");
     REG_KEY("TV Editing", "LOADCOMMSKIP", "Load cut list from commercial skips",
             "Z,End");
-    REG_KEY("TV Editing", "NEXTCUT", "Jump to the next cut point", "PgDown");
-    REG_KEY("TV Editing", "PREVCUT", "Jump to the previous cut point", "PgUp");
+    REG_KEY("TV Editing", "NEXTCUT", "Jump to the next cut point", "PgDown,remoteDown");
+    REG_KEY("TV Editing", "PREVCUT", "Jump to the previous cut point", "PgUp,remoteUp");
     REG_KEY("TV Editing", "BIGJUMPREW", "Jump back 10x the normal amount",
-            ",,<");
+            ",,<,remoteRewind");
     REG_KEY("TV Editing", "BIGJUMPFWD", "Jump forward 10x the normal amount",
-            ">,.");
-    REG_KEY("TV Editing", "TOGGLEEDIT", "Exit out of Edit Mode", "E");
+            ">,.,remoteFastForward");
+    REG_KEY("TV Editing", "TOGGLEEDIT", "Exit out of Edit Mode", "E,remoteBack");
 /*
   keys already used:
 
Index: libs/libmyth/lirc.cpp
===================================================================
--- libs/libmyth/lirc.cpp	(revision 8113)
+++ libs/libmyth/lirc.cpp	(working copy)
@@ -6,6 +6,7 @@
 #include <sys/wait.h>
 #include <sys/types.h>
 #include <unistd.h>
+#include <stdio.h>
 
 #include "mythcontext.h"
 
@@ -43,8 +44,7 @@
     {
          cerr << "Failed to read lirc config " << config_file << " for " 
               << program << endl;
-        lirc_deinit();
-        return -1;
+         lircConfig = NULL;
     }
 
     external_app = gContext->GetSetting("LircKeyPressedApp") + " &";
@@ -63,16 +63,23 @@
     char *code = 0;
     char *ir = 0;
     int ret;
+    QString prevKey = "";
 
     /* Process all events read */
     while (lirc_nextcode(&ir) == 0)
     {
         if (!ir)
             continue;
-        while ((ret = lirc_code2char(lircConfig, ir, &code)) == 0 && 
+        QStringList parseKey = QStringList::split(" ", ir);
+        QString remKey = parseKey[2];
+
+        int naction = 0;
+
+        while (lircConfig && (ret = lirc_code2char(lircConfig, ir, &code)) == 0 && 
                code != NULL)
         {
             QKeySequence a(code);
+            naction++;
 
             int keycode = 0;
 
@@ -87,15 +94,37 @@
             {
                 keycode = a[i];
 
-                QApplication::postEvent(mainWindow, new LircKeycodeEvent(code, 
+                QApplication::postEvent(mainWindow, new LircKeycodeEvent(remKey, 
                                         keycode, true));
-                QApplication::postEvent(mainWindow, new LircKeycodeEvent(code, 
+                QApplication::postEvent(mainWindow, new LircKeycodeEvent(remKey, 
                                         keycode, false));
 
                 SpawnApp();
             }
         }
 
+        if (naction == 0)
+        {
+/* LIRC failed to give an action for this key.  Need to distinguish between
+ * 1) Key is held-down and LIRC is configured to not give repeat action (yet?)
+ * 2) Key is not configured in .mythtv/lircrc
+ * In the second case, issue event with remote keycode.  It is detectable
+ * because parseKey[1] for it is "00"
+ */
+            QString id = parseKey[1];
+            if (id == "00")
+            { 
+                QApplication::postEvent(mainWindow, new LircKeycodeEvent(remKey, 
+                                        0, true));
+                QApplication::postEvent(mainWindow, new LircKeycodeEvent(remKey, 
+                                        0, false));
+
+                SpawnApp();
+            }
+        }
+
+        prevKey = remKey;
+
         free(ir);
         if (ret == -1)
             break;
Index: libs/libmyth/mythdialogs.cpp
===================================================================
--- libs/libmyth/mythdialogs.cpp	(revision 8113)
+++ libs/libmyth/mythdialogs.cpp	(working copy)
@@ -42,6 +42,8 @@
 #include "screensaver.h"
 #include "mythdbcon.h"
 
+typedef QValueList<int> KeyList;
+
 #ifdef USE_LIRC
 static void *SpawnLirc(void *param)
 {
@@ -113,7 +115,9 @@
 class MythMainWindowPrivate
 {
   public:
-    int TranslateKeyNum(QKeyEvent *e);
+    MythMainWindowPrivate(void) { nextKeycode = Qt::UNICODE_ACCEL; }
+    KeyList TranslateKeyNum(QKeyEvent *e);
+    int TranslateRemoteKey(QString key);
 
     float wmult, hmult;
     int screenwidth, screenheight;
@@ -138,6 +142,11 @@
     QMap<QString, MHData> mediaHandlerMap;
     QMap<QString, MPData> mediaPluginMap;
 
+    QMap<QString, int> remoteKeymap;
+
+    QMap<QString, int> remoteMap;
+    int nextKeycode;
+
     void (*exitmenucallback)(void);
 
     void (*exitmenumediadevicecallback)(MythMediaDevice* mediadevice);
@@ -146,11 +155,27 @@
     int escapekey;
 };
 
+int MythMainWindowPrivate::TranslateRemoteKey(QString key)
+{
+    key = key.lower();
+    if (!remoteKeymap.contains(key))
+        remoteKeymap.insert(key, nextKeycode++);
+    return remoteKeymap[key];
+}
+
 // Make keynum in QKeyEvent be equivalent to what's in QKeySequence
-int MythMainWindowPrivate::TranslateKeyNum(QKeyEvent* e)
+KeyList MythMainWindowPrivate::TranslateKeyNum(QKeyEvent* e)
 {
+    KeyList rv;
     int keynum = e->key();
 
+    QString text = e->text();
+    if (text.left(6) == "remote")
+    {
+        QString remoteKey = text.mid(6);
+        rv.append(TranslateRemoteKey(remoteKey));
+    }
+
     if (keynum != Qt::Key_Escape &&
         (keynum <  Qt::Key_Shift || keynum > Qt::Key_ScrollLock))
     {
@@ -164,11 +189,13 @@
                          ((modifiers & Qt::MetaButton) ? Qt::META : 0) |
                          ((modifiers & Qt::AltButton) ? Qt::ALT : 0);
             modnum &= ~Qt::UNICODE_ACCEL;
-            return (keynum |= modnum);
+            rv.append(keynum | modnum);
+            return rv;
         }
     }
 
-    return keynum;
+    rv.append(keynum);
+    return rv;
 }
 
 MythMainWindow::MythMainWindow(QWidget *parent, const char *name, bool modal, 
@@ -207,13 +234,13 @@
 
     d->keyContexts.setAutoDelete(true);
 
-    RegisterKey("Global", "UP", "Up Arrow", "Up");
-    RegisterKey("Global", "DOWN", "Down Arrow", "Down");
-    RegisterKey("Global", "LEFT", "Left Arrow", "Left");
-    RegisterKey("Global", "RIGHT", "Right Arrow", "Right");
-    RegisterKey("Global", "SELECT", "Select", "Return,Enter,Space");
-    RegisterKey("Global", "ESCAPE", "Escape", "Esc");
-    RegisterKey("Global", "MENU", "Pop-up menu", "M");
+    RegisterKey("Global", "UP", "Up Arrow", "Up,remoteUp");
+    RegisterKey("Global", "DOWN", "Down Arrow", "Down,remoteDown");
+    RegisterKey("Global", "LEFT", "Left Arrow", "Left,remoteLeft");
+    RegisterKey("Global", "RIGHT", "Right Arrow", "Right,remoteRight");
+    RegisterKey("Global", "SELECT", "Select", "Return,Enter,Space,remoteOK,remoteEnter");
+    RegisterKey("Global", "ESCAPE", "Escape", "Esc,remoteBack");
+    RegisterKey("Global", "MENU", "Pop-up menu", "M,remoteMenu");
     RegisterKey("Global", "INFO", "More information", "I");
 
     RegisterKey("Global", "PAGEUP", "Page Up", "PgUp");
@@ -224,16 +251,16 @@
 
     RegisterKey("Global", "HELP", "Help", "F1");
 
-    RegisterKey("Global", "0", "0", "0");
-    RegisterKey("Global", "1", "1", "1");
-    RegisterKey("Global", "2", "2", "2");
-    RegisterKey("Global", "3", "3", "3");
-    RegisterKey("Global", "4", "4", "4");
-    RegisterKey("Global", "5", "5", "5");
-    RegisterKey("Global", "6", "6", "6");
-    RegisterKey("Global", "7", "7", "7");
-    RegisterKey("Global", "8", "8", "8");
-    RegisterKey("Global", "9", "9", "9");
+    RegisterKey("Global", "0", "0", "0,remote0");
+    RegisterKey("Global", "1", "1", "1,remote1");
+    RegisterKey("Global", "2", "2", "2,remote2");
+    RegisterKey("Global", "3", "3", "3,remote3");
+    RegisterKey("Global", "4", "4", "4,remote4");
+    RegisterKey("Global", "5", "5", "5,remote5");
+    RegisterKey("Global", "6", "6", "6,remote6");
+    RegisterKey("Global", "7", "7", "7,remote7");
+    RegisterKey("Global", "8", "8", "8,remote8");
+    RegisterKey("Global", "9", "9", "9,remote9");
 }
 
 MythMainWindow::~MythMainWindow()
@@ -410,28 +437,35 @@
                                        bool allowJumps)
 {
     actions.clear();
-    int keynum = d->TranslateKeyNum(e);
+    QString text = e->text();
 
-    if (allowJumps &&
-        d->jumpMap.count(keynum) > 0 && d->exitmenucallback == NULL)
-    {
-        d->exitingtomain = true;
-        d->exitmenucallback = d->jumpMap[keynum]->callback;
-        QApplication::postEvent(this, new ExitToMainMenuEvent());
-        return false;
-    }
+    KeyList keylist = d->TranslateKeyNum(e);
 
     bool retval = false;
 
-    if (d->keyContexts[context])
+    for (unsigned int i = 0; i < keylist.count(); i++)
     {
-        if (d->keyContexts[context]->GetMapping(keynum, actions))
-            retval = true;
+        int keynum = keylist[i];
+
+        if (allowJumps &&
+            d->jumpMap.count(keynum) > 0 && d->exitmenucallback == NULL)
+        {
+            d->exitingtomain = true;
+            d->exitmenucallback = d->jumpMap[keynum]->callback;
+            QApplication::postEvent(this, new ExitToMainMenuEvent());
+            return false;
+        }
+
+	    if (d->keyContexts[context])
+	    {
+	        if (d->keyContexts[context]->GetMapping(keynum, actions))
+	            retval = true;
+	    }
+	
+	    if (d->keyContexts["Global"]->GetMapping(keynum, actions))
+	        retval = true;
     }
 
-    if (d->keyContexts["Global"]->GetMapping(keynum, actions))
-        retval = true;
-
     return retval;
 }
 
@@ -463,18 +497,53 @@
     }
 }
 
+void MythMainWindow::ParseKeys(QString key, QValueList<int> &keyseq)
+{
+    /* This handles "," mappings funnily.  The first part produces
+     * empty entries in keys for them.  numremote ensures that these
+     * empty entries recreate the ,'s in the output, so that
+     * QKeySequence gets something it'll interpret as a comma.
+     */
+    keyseq.clear();
+    if (key.isEmpty()) return;
+    QStringList keys = QStringList::split(",", key, true);
+    QString nonremoteKeys = "";
+    int numremote = 0;
+    for (unsigned int i = 0; i < keys.count(); i++)
+    {
+        QString code = keys[i];
+        if (code.left(6) == "remote")
+            keyseq.append(d->TranslateRemoteKey(code.mid(6)));
+        else
+        {
+            if (numremote > 0) nonremoteKeys += ',';
+            nonremoteKeys += code;
+            numremote++;
+        }
+    }
+    if (!nonremoteKeys.isEmpty())
+    {
+        QKeySequence keycodeSeq(nonremoteKeys);
+        for (unsigned int i = 0; i < keycodeSeq.count(); i++)
+        {
+            keyseq.append(keycodeSeq[i] & ~Qt::UNICODE_ACCEL);
+        }
+    }
+}
+
+
 void MythMainWindow::BindKey(const QString &context, const QString &action,
 			     const QString &key)
 {
-    QKeySequence keyseq(key);
-
     if (!d->keyContexts[context])
         d->keyContexts.insert(context, new KeyContext());
 
+    QValueList<int> keyseq;
+    ParseKeys(key, keyseq);
+
     for (unsigned int i = 0; i < keyseq.count(); i++)
     {
         int keynum = keyseq[i];
-        keynum &= ~Qt::UNICODE_ACCEL;
 
         QStringList dummyaction = "";
         if (d->keyContexts[context]->GetMapping(keynum, dummyaction))
@@ -591,12 +660,12 @@
 	return;
     }
 
-    QKeySequence keyseq(key);
+    QValueList<int> keyseq;
+    ParseKeys(key, keyseq);
 
     if (!keyseq.isEmpty())
     {
         int keynum = keyseq[0];
-        keynum &= ~Qt::UNICODE_ACCEL;
 
         if (d->jumpMap.count(keynum) == 0)
         {
@@ -812,16 +881,17 @@
     {
         LircKeycodeEvent *lke = (LircKeycodeEvent *)ce;
         int keycode = lke->getKeycode();
+        QString text;
 
+        int mod = keycode & MODIFIER_MASK;
+        int ascii = 0;
+        int k = keycode & ~MODIFIER_MASK; /* trim off the mod */
+
+        gContext->ResetScreensaver();
+
         if (keycode) 
         {
-            gContext->ResetScreensaver();
 
-            int mod = keycode & MODIFIER_MASK;
-            int k = keycode & ~MODIFIER_MASK; /* trim off the mod */
-            int ascii = 0;
-            QString text;
-
             if (k & UNICODE_ACCEL)
             {
                 QChar c(k & ~UNICODE_ACCEL);
@@ -834,19 +904,20 @@
                   ((mod & Qt::ALT) ? Qt::AltButton : 0) |
                   ((mod & Qt::SHIFT) ? Qt::ShiftButton : 0);
 
-            QKeyEvent key(lke->isKeyDown() ? QEvent::KeyPress :
-                          QEvent::KeyRelease, k, ascii, mod, text);
+        }
+        text = QString("remote") + lke->getLircText();
 
-            QObject *key_target = getTarget(key);
+        QKeyEvent key(lke->isKeyDown() ? QEvent::KeyPress :
+                      QEvent::KeyRelease, k, ascii, mod, text);
 
-            QApplication::sendEvent(key_target, &key);
-        }
-        else
-        {
-            cerr << "LircClient warning: attempt to convert '"
-                 << lke->getLircText() << "' to a key sequence failed. Fix"
-                                           " your key mappings.\n";
-        }
+        QObject *key_target = getTarget(key);
+
+        QApplication::sendEvent(key_target, &key);
+        /*
+        cerr << "LircClient warning: attempt to convert '"
+             << lke->getLircText() << "' to a key sequence failed. Fix"
+                                       " your key mappings.\n";
+                                       */
     }
     else if (ce->type() == kLircMuteEventType)
     {
Index: libs/libmyth/mythdialogs.h
===================================================================
--- libs/libmyth/mythdialogs.h	(revision 8113)
+++ libs/libmyth/mythdialogs.h	(working copy)
@@ -118,7 +118,6 @@
     void JumpTo(const QString &destination);
     bool DestinationExists(const QString &destination) const;
 
-
   protected:
     void keyPressEvent(QKeyEvent *e);
     void customEvent(QCustomEvent *ce);
@@ -126,6 +125,7 @@
     
     void ExitToMainMenu();
 
+    void ParseKeys(QString key, QValueList<int> &keylist);
     QObject *getTarget(QKeyEvent &key);
 
     MythMainWindowPrivate *d;
