Ticket #757: remotekey.patch

File remotekey.patch, 18.9 KB (added by mythtv@…, 15 years ago)

proposed patch

  • libs/libmythtv/tv_play.cpp

     
    5252
    5353void TV::InitKeys(void)
    5454{
    55     REG_KEY("TV Frontend", "PAGEUP", "Page Up", "3");
    56     REG_KEY("TV Frontend", "PAGEDOWN", "Page Down", "9");
     55    REG_KEY("TV Frontend", "PAGEUP", "Page Up", "3,remote3");
     56    REG_KEY("TV Frontend", "PAGEDOWN", "Page Down", "9,remote9");
    5757    REG_KEY("TV Frontend", "DELETE", "Delete Program", "D");
    58     REG_KEY("TV Frontend", "PLAYBACK", "Play Program", "P");
     58    REG_KEY("TV Frontend", "PLAYBACK", "Play Program", "P,remotePlay");
    5959    REG_KEY("TV Frontend", "TOGGLERECORD", "Toggle recording status of current "
    60             "program", "R");
     60            "program", "R,remoteRecord");
    6161    REG_KEY("TV Frontend", "DAYLEFT", "Page the program guide back one day",
    6262            "Home,7");
    6363    REG_KEY("TV Frontend", "DAYRIGHT", "Page the program guide forward one day",
     
    8080    REG_KEY("TV Frontend", "DETAILS", "Show program details", "U");
    8181
    8282    REG_KEY("TV Playback", "CLEAROSD", "Clear OSD", "Backspace");
    83     REG_KEY("TV Playback", "PAUSE", "Pause", "P");
     83    REG_KEY("TV Playback", "PAUSE", "Pause", "P,remotePause");
    8484    REG_KEY("TV Playback", "DELETE", "Delete Program", "D");
    85     REG_KEY("TV Playback", "SEEKFFWD", "Fast Forward", "Right");
    86     REG_KEY("TV Playback", "SEEKRWND", "Rewind", "Left");
    87     REG_KEY("TV Playback", "ARBSEEK", "Arbitrary Seek", "*");
    88     REG_KEY("TV Playback", "CHANNELUP", "Channel up", "Up");
    89     REG_KEY("TV Playback", "CHANNELDOWN", "Channel down", "Down");
     85    REG_KEY("TV Playback", "SEEKFFWD", "Fast Forward", "Right,remoteRight");
     86    REG_KEY("TV Playback", "SEEKRWND", "Rewind", "Left,remoteLeft");
     87    REG_KEY("TV Playback", "ARBSEEK", "Arbitrary Seek", "*,remote*");
     88    REG_KEY("TV Playback", "CHANNELUP", "Channel up", "Up,remoteCh+");
     89    REG_KEY("TV Playback", "CHANNELDOWN", "Channel down", "Down,remoteCh-");
    9090    REG_KEY("TV Playback", "NEXTFAV", "Switch to the next favorite channel",
    9191            "/");
    9292    REG_KEY("TV Playback", "PREVCHAN", "Switch to the previous channel", "H");
    93     REG_KEY("TV Playback", "JUMPFFWD", "Jump ahead", "PgDown");
    94     REG_KEY("TV Playback", "JUMPRWND", "Jump back", "PgUp");
     93    REG_KEY("TV Playback", "JUMPFFWD", "Jump ahead", "PgDown,remoteDown");
     94    REG_KEY("TV Playback", "JUMPRWND", "Jump back", "PgUp,remoteUp");
    9595    REG_KEY("TV Playback", "JUMPBKMRK", "Jump to bookmark", "K");
    9696    REG_KEY("TV Playback", "FFWDSTICKY", "Fast Forward (Sticky) or Forward one "
    97             "frame while paused", ">,.");
     97            "frame while paused", ">,.,remoteFastForward");
    9898    REG_KEY("TV Playback", "RWNDSTICKY", "Rewind (Sticky) or Rewind one frame "
    99             "while paused", ",,<");
     99            "while paused", ",,<,remoteRewind");
    100100    REG_KEY("TV Playback", "TOGGLEINPUTS", "Toggle Inputs", "C");
    101101    REG_KEY("TV Playback", "SWITCHCARDS", "Switch Capture Cards", "Y");
    102     REG_KEY("TV Playback", "SKIPCOMMERCIAL", "Skip Commercial", "Z,End");
     102    REG_KEY("TV Playback", "SKIPCOMMERCIAL", "Skip Commercial", "Z,End,remoteSkipForward");
    103103    REG_KEY("TV Playback", "SKIPCOMMBACK", "Skip Commercial (Reverse)",
    104             "Q,Home");
     104            "Q,Home,remoteSkipBackward");
    105105    REG_KEY("TV Playback", "JUMPSTART", "Jump to the start of the recording.", "Ctrl+B");           
    106106    REG_KEY("TV Playback", "TOGGLEBROWSE", "Toggle channel browse mode", "O");
    107107    REG_KEY("TV Playback", "TOGGLERECORD", "Toggle recording status of current "
    108             "program", "R");
     108            "program", "R,remoteRecord");
    109109    REG_KEY("TV Playback", "TOGGLEFAV", "Toggle the current channel as a "
    110110            "favorite", "?");
    111     REG_KEY("TV Playback", "VOLUMEDOWN", "Volume down", "[,{,F10");
    112     REG_KEY("TV Playback", "VOLUMEUP", "Volume up", "],},F11");
    113     REG_KEY("TV Playback", "MUTE", "Mute", "|,\\,F9");
     111    REG_KEY("TV Playback", "VOLUMEDOWN", "Volume down", "[,{,F10,remoteVol+");
     112    REG_KEY("TV Playback", "VOLUMEUP", "Volume up", "],},F11,remoteVol-");
     113    REG_KEY("TV Playback", "MUTE", "Mute", "|,\\,F9,remoteMute");
    114114    REG_KEY("TV Playback", "TOGGLEPIPMODE", "Toggle Picture-in-Picture mode",
    115115            "V");
    116116    REG_KEY("TV Playback", "TOGGLEPIPWINDOW", "Toggle active PiP window", "B");
     
    137137    REG_KEY("TV Playback", "TOGGLERECCONTROLS", "Turn on the recording picture "
    138138            "adjustment controls", "G");
    139139    REG_KEY("TV Playback", "TOGGLEEDIT", "Start Edit Mode", "E");
    140     REG_KEY("TV Playback", "GUIDE", "Show the Program Guide", "S");
     140    REG_KEY("TV Playback", "GUIDE", "Show the Program Guide", "S,remoteGuide");
    141141    REG_KEY("TV Playback", "TOGGLESLEEP", "Toggle the Sleep Timer", "F8");
    142     REG_KEY("TV Playback", "PLAY", "Play", "Ctrl+P");
     142    REG_KEY("TV Playback", "PLAY", "Play", "Ctrl+P,remotePlay");
    143143    REG_KEY("TV Playback", "NEXTAUDIO", "Switch to the next audio track", "+");
    144144    REG_KEY("TV Playback", "PREVAUDIO", "Switch to the previous audio track", "-");
    145145    REG_KEY("TV Playback", "NEXTSUBTITLE", "Switch to the next subtitle track", "");
     
    151151    REG_KEY("TV Editing", "INVERTMAP", "Invert Begin/End cut points", "I");
    152152    REG_KEY("TV Editing", "LOADCOMMSKIP", "Load cut list from commercial skips",
    153153            "Z,End");
    154     REG_KEY("TV Editing", "NEXTCUT", "Jump to the next cut point", "PgDown");
    155     REG_KEY("TV Editing", "PREVCUT", "Jump to the previous cut point", "PgUp");
     154    REG_KEY("TV Editing", "NEXTCUT", "Jump to the next cut point", "PgDown,remoteDown");
     155    REG_KEY("TV Editing", "PREVCUT", "Jump to the previous cut point", "PgUp,remoteUp");
    156156    REG_KEY("TV Editing", "BIGJUMPREW", "Jump back 10x the normal amount",
    157             ",,<");
     157            ",,<,remoteRewind");
    158158    REG_KEY("TV Editing", "BIGJUMPFWD", "Jump forward 10x the normal amount",
    159             ">,.");
    160     REG_KEY("TV Editing", "TOGGLEEDIT", "Exit out of Edit Mode", "E");
     159            ">,.,remoteFastForward");
     160    REG_KEY("TV Editing", "TOGGLEEDIT", "Exit out of Edit Mode", "E,remoteBack");
    161161/*
    162162  keys already used:
    163163
  • libs/libmyth/lirc.cpp

     
    66#include <sys/wait.h>
    77#include <sys/types.h>
    88#include <unistd.h>
     9#include <stdio.h>
    910
    1011#include "mythcontext.h"
    1112
     
    4344    {
    4445         cerr << "Failed to read lirc config " << config_file << " for "
    4546              << program << endl;
    46         lirc_deinit();
    47         return -1;
     47         lircConfig = NULL;
    4848    }
    4949
    5050    external_app = gContext->GetSetting("LircKeyPressedApp") + " &";
     
    6363    char *code = 0;
    6464    char *ir = 0;
    6565    int ret;
     66    QString prevKey = "";
    6667
    6768    /* Process all events read */
    6869    while (lirc_nextcode(&ir) == 0)
    6970    {
    7071        if (!ir)
    7172            continue;
    72         while ((ret = lirc_code2char(lircConfig, ir, &code)) == 0 &&
     73        QStringList parseKey = QStringList::split(" ", ir);
     74        QString remKey = parseKey[2];
     75
     76        int naction = 0;
     77
     78        while (lircConfig && (ret = lirc_code2char(lircConfig, ir, &code)) == 0 &&
    7379               code != NULL)
    7480        {
    7581            QKeySequence a(code);
     82            naction++;
    7683
    7784            int keycode = 0;
    7885
     
    8794            {
    8895                keycode = a[i];
    8996
    90                 QApplication::postEvent(mainWindow, new LircKeycodeEvent(code,
     97                QApplication::postEvent(mainWindow, new LircKeycodeEvent(remKey,
    9198                                        keycode, true));
    92                 QApplication::postEvent(mainWindow, new LircKeycodeEvent(code,
     99                QApplication::postEvent(mainWindow, new LircKeycodeEvent(remKey,
    93100                                        keycode, false));
    94101
    95102                SpawnApp();
    96103            }
    97104        }
    98105
     106        if (naction == 0)
     107        {
     108/* LIRC failed to give an action for this key.  Need to distinguish between
     109 * 1) Key is held-down and LIRC is configured to not give repeat action (yet?)
     110 * 2) Key is not configured in .mythtv/lircrc
     111 * In the second case, issue event with remote keycode.  It is detectable
     112 * because parseKey[1] for it is "00"
     113 */
     114            QString id = parseKey[1];
     115            if (id == "00")
     116            {
     117                QApplication::postEvent(mainWindow, new LircKeycodeEvent(remKey,
     118                                        0, true));
     119                QApplication::postEvent(mainWindow, new LircKeycodeEvent(remKey,
     120                                        0, false));
     121
     122                SpawnApp();
     123            }
     124        }
     125
     126        prevKey = remKey;
     127
    99128        free(ir);
    100129        if (ret == -1)
    101130            break;
  • libs/libmyth/mythdialogs.cpp

     
    4242#include "screensaver.h"
    4343#include "mythdbcon.h"
    4444
     45typedef QValueList<int> KeyList;
     46
    4547#ifdef USE_LIRC
    4648static void *SpawnLirc(void *param)
    4749{
     
    113115class MythMainWindowPrivate
    114116{
    115117  public:
    116     int TranslateKeyNum(QKeyEvent *e);
     118    MythMainWindowPrivate(void) { nextKeycode = Qt::UNICODE_ACCEL; }
     119    KeyList TranslateKeyNum(QKeyEvent *e);
     120    int TranslateRemoteKey(QString key);
    117121
    118122    float wmult, hmult;
    119123    int screenwidth, screenheight;
     
    138142    QMap<QString, MHData> mediaHandlerMap;
    139143    QMap<QString, MPData> mediaPluginMap;
    140144
     145    QMap<QString, int> remoteKeymap;
     146
     147    QMap<QString, int> remoteMap;
     148    int nextKeycode;
     149
    141150    void (*exitmenucallback)(void);
    142151
    143152    void (*exitmenumediadevicecallback)(MythMediaDevice* mediadevice);
     
    146155    int escapekey;
    147156};
    148157
     158int MythMainWindowPrivate::TranslateRemoteKey(QString key)
     159{
     160    key = key.lower();
     161    if (!remoteKeymap.contains(key))
     162        remoteKeymap.insert(key, nextKeycode++);
     163    return remoteKeymap[key];
     164}
     165
    149166// Make keynum in QKeyEvent be equivalent to what's in QKeySequence
    150 int MythMainWindowPrivate::TranslateKeyNum(QKeyEvent* e)
     167KeyList MythMainWindowPrivate::TranslateKeyNum(QKeyEvent* e)
    151168{
     169    KeyList rv;
    152170    int keynum = e->key();
    153171
     172    QString text = e->text();
     173    if (text.left(6) == "remote")
     174    {
     175        QString remoteKey = text.mid(6);
     176        rv.append(TranslateRemoteKey(remoteKey));
     177    }
     178
    154179    if (keynum != Qt::Key_Escape &&
    155180        (keynum <  Qt::Key_Shift || keynum > Qt::Key_ScrollLock))
    156181    {
     
    164189                         ((modifiers & Qt::MetaButton) ? Qt::META : 0) |
    165190                         ((modifiers & Qt::AltButton) ? Qt::ALT : 0);
    166191            modnum &= ~Qt::UNICODE_ACCEL;
    167             return (keynum |= modnum);
     192            rv.append(keynum | modnum);
     193            return rv;
    168194        }
    169195    }
    170196
    171     return keynum;
     197    rv.append(keynum);
     198    return rv;
    172199}
    173200
    174201MythMainWindow::MythMainWindow(QWidget *parent, const char *name, bool modal,
     
    207234
    208235    d->keyContexts.setAutoDelete(true);
    209236
    210     RegisterKey("Global", "UP", "Up Arrow", "Up");
    211     RegisterKey("Global", "DOWN", "Down Arrow", "Down");
    212     RegisterKey("Global", "LEFT", "Left Arrow", "Left");
    213     RegisterKey("Global", "RIGHT", "Right Arrow", "Right");
    214     RegisterKey("Global", "SELECT", "Select", "Return,Enter,Space");
    215     RegisterKey("Global", "ESCAPE", "Escape", "Esc");
    216     RegisterKey("Global", "MENU", "Pop-up menu", "M");
     237    RegisterKey("Global", "UP", "Up Arrow", "Up,remoteUp");
     238    RegisterKey("Global", "DOWN", "Down Arrow", "Down,remoteDown");
     239    RegisterKey("Global", "LEFT", "Left Arrow", "Left,remoteLeft");
     240    RegisterKey("Global", "RIGHT", "Right Arrow", "Right,remoteRight");
     241    RegisterKey("Global", "SELECT", "Select", "Return,Enter,Space,remoteOK,remoteEnter");
     242    RegisterKey("Global", "ESCAPE", "Escape", "Esc,remoteBack");
     243    RegisterKey("Global", "MENU", "Pop-up menu", "M,remoteMenu");
    217244    RegisterKey("Global", "INFO", "More information", "I");
    218245
    219246    RegisterKey("Global", "PAGEUP", "Page Up", "PgUp");
     
    224251
    225252    RegisterKey("Global", "HELP", "Help", "F1");
    226253
    227     RegisterKey("Global", "0", "0", "0");
    228     RegisterKey("Global", "1", "1", "1");
    229     RegisterKey("Global", "2", "2", "2");
    230     RegisterKey("Global", "3", "3", "3");
    231     RegisterKey("Global", "4", "4", "4");
    232     RegisterKey("Global", "5", "5", "5");
    233     RegisterKey("Global", "6", "6", "6");
    234     RegisterKey("Global", "7", "7", "7");
    235     RegisterKey("Global", "8", "8", "8");
    236     RegisterKey("Global", "9", "9", "9");
     254    RegisterKey("Global", "0", "0", "0,remote0");
     255    RegisterKey("Global", "1", "1", "1,remote1");
     256    RegisterKey("Global", "2", "2", "2,remote2");
     257    RegisterKey("Global", "3", "3", "3,remote3");
     258    RegisterKey("Global", "4", "4", "4,remote4");
     259    RegisterKey("Global", "5", "5", "5,remote5");
     260    RegisterKey("Global", "6", "6", "6,remote6");
     261    RegisterKey("Global", "7", "7", "7,remote7");
     262    RegisterKey("Global", "8", "8", "8,remote8");
     263    RegisterKey("Global", "9", "9", "9,remote9");
    237264}
    238265
    239266MythMainWindow::~MythMainWindow()
     
    410437                                       bool allowJumps)
    411438{
    412439    actions.clear();
    413     int keynum = d->TranslateKeyNum(e);
     440    QString text = e->text();
    414441
    415     if (allowJumps &&
    416         d->jumpMap.count(keynum) > 0 && d->exitmenucallback == NULL)
    417     {
    418         d->exitingtomain = true;
    419         d->exitmenucallback = d->jumpMap[keynum]->callback;
    420         QApplication::postEvent(this, new ExitToMainMenuEvent());
    421         return false;
    422     }
     442    KeyList keylist = d->TranslateKeyNum(e);
    423443
    424444    bool retval = false;
    425445
    426     if (d->keyContexts[context])
     446    for (unsigned int i = 0; i < keylist.count(); i++)
    427447    {
    428         if (d->keyContexts[context]->GetMapping(keynum, actions))
    429             retval = true;
     448        int keynum = keylist[i];
     449
     450        if (allowJumps &&
     451            d->jumpMap.count(keynum) > 0 && d->exitmenucallback == NULL)
     452        {
     453            d->exitingtomain = true;
     454            d->exitmenucallback = d->jumpMap[keynum]->callback;
     455            QApplication::postEvent(this, new ExitToMainMenuEvent());
     456            return false;
     457        }
     458
     459            if (d->keyContexts[context])
     460            {
     461                if (d->keyContexts[context]->GetMapping(keynum, actions))
     462                    retval = true;
     463            }
     464       
     465            if (d->keyContexts["Global"]->GetMapping(keynum, actions))
     466                retval = true;
    430467    }
    431468
    432     if (d->keyContexts["Global"]->GetMapping(keynum, actions))
    433         retval = true;
    434 
    435469    return retval;
    436470}
    437471
     
    463497    }
    464498}
    465499
     500void MythMainWindow::ParseKeys(QString key, QValueList<int> &keyseq)
     501{
     502    /* This handles "," mappings funnily.  The first part produces
     503     * empty entries in keys for them.  numremote ensures that these
     504     * empty entries recreate the ,'s in the output, so that
     505     * QKeySequence gets something it'll interpret as a comma.
     506     */
     507    keyseq.clear();
     508    if (key.isEmpty()) return;
     509    QStringList keys = QStringList::split(",", key, true);
     510    QString nonremoteKeys = "";
     511    int numremote = 0;
     512    for (unsigned int i = 0; i < keys.count(); i++)
     513    {
     514        QString code = keys[i];
     515        if (code.left(6) == "remote")
     516            keyseq.append(d->TranslateRemoteKey(code.mid(6)));
     517        else
     518        {
     519            if (numremote > 0) nonremoteKeys += ',';
     520            nonremoteKeys += code;
     521            numremote++;
     522        }
     523    }
     524    if (!nonremoteKeys.isEmpty())
     525    {
     526        QKeySequence keycodeSeq(nonremoteKeys);
     527        for (unsigned int i = 0; i < keycodeSeq.count(); i++)
     528        {
     529            keyseq.append(keycodeSeq[i] & ~Qt::UNICODE_ACCEL);
     530        }
     531    }
     532}
     533
     534
    466535void MythMainWindow::BindKey(const QString &context, const QString &action,
    467536                             const QString &key)
    468537{
    469     QKeySequence keyseq(key);
    470 
    471538    if (!d->keyContexts[context])
    472539        d->keyContexts.insert(context, new KeyContext());
    473540
     541    QValueList<int> keyseq;
     542    ParseKeys(key, keyseq);
     543
    474544    for (unsigned int i = 0; i < keyseq.count(); i++)
    475545    {
    476546        int keynum = keyseq[i];
    477         keynum &= ~Qt::UNICODE_ACCEL;
    478547
    479548        QStringList dummyaction = "";
    480549        if (d->keyContexts[context]->GetMapping(keynum, dummyaction))
     
    591660        return;
    592661    }
    593662
    594     QKeySequence keyseq(key);
     663    QValueList<int> keyseq;
     664    ParseKeys(key, keyseq);
    595665
    596666    if (!keyseq.isEmpty())
    597667    {
    598668        int keynum = keyseq[0];
    599         keynum &= ~Qt::UNICODE_ACCEL;
    600669
    601670        if (d->jumpMap.count(keynum) == 0)
    602671        {
     
    812881    {
    813882        LircKeycodeEvent *lke = (LircKeycodeEvent *)ce;
    814883        int keycode = lke->getKeycode();
     884        QString text;
    815885
     886        int mod = keycode & MODIFIER_MASK;
     887        int ascii = 0;
     888        int k = keycode & ~MODIFIER_MASK; /* trim off the mod */
     889
     890        gContext->ResetScreensaver();
     891
    816892        if (keycode)
    817893        {
    818             gContext->ResetScreensaver();
    819894
    820             int mod = keycode & MODIFIER_MASK;
    821             int k = keycode & ~MODIFIER_MASK; /* trim off the mod */
    822             int ascii = 0;
    823             QString text;
    824 
    825895            if (k & UNICODE_ACCEL)
    826896            {
    827897                QChar c(k & ~UNICODE_ACCEL);
     
    834904                  ((mod & Qt::ALT) ? Qt::AltButton : 0) |
    835905                  ((mod & Qt::SHIFT) ? Qt::ShiftButton : 0);
    836906
    837             QKeyEvent key(lke->isKeyDown() ? QEvent::KeyPress :
    838                           QEvent::KeyRelease, k, ascii, mod, text);
     907        }
     908        text = QString("remote") + lke->getLircText();
    839909
    840             QObject *key_target = getTarget(key);
     910        QKeyEvent key(lke->isKeyDown() ? QEvent::KeyPress :
     911                      QEvent::KeyRelease, k, ascii, mod, text);
    841912
    842             QApplication::sendEvent(key_target, &key);
    843         }
    844         else
    845         {
    846             cerr << "LircClient warning: attempt to convert '"
    847                  << lke->getLircText() << "' to a key sequence failed. Fix"
    848                                            " your key mappings.\n";
    849         }
     913        QObject *key_target = getTarget(key);
     914
     915        QApplication::sendEvent(key_target, &key);
     916        /*
     917        cerr << "LircClient warning: attempt to convert '"
     918             << lke->getLircText() << "' to a key sequence failed. Fix"
     919                                       " your key mappings.\n";
     920                                       */
    850921    }
    851922    else if (ce->type() == kLircMuteEventType)
    852923    {
  • libs/libmyth/mythdialogs.h

     
    118118    void JumpTo(const QString &destination);
    119119    bool DestinationExists(const QString &destination) const;
    120120
    121 
    122121  protected:
    123122    void keyPressEvent(QKeyEvent *e);
    124123    void customEvent(QCustomEvent *ce);
     
    126125   
    127126    void ExitToMainMenu();
    128127
     128    void ParseKeys(QString key, QValueList<int> &keylist);
    129129    QObject *getTarget(QKeyEvent &key);
    130130
    131131    MythMainWindowPrivate *d;