Ticket #5583: 5583-v1.patch

File 5583-v1.patch, 24.0 KB (added by danielk, 11 years ago)
  • libs/libmythui/lirc.h

     
    11#ifndef LIRC_H_
    22#define LIRC_H_
    33
    4 #include <lirc/lirc_client.h>
    54#include <QObject>
    65#include <QThread>
    76#include <QString>
     7#include <QMutex>
    88
    99#include "mythexp.h"
    1010
    11 class MPUBLIC LircThread : public QThread
     11class LIRCPriv;
     12class MPUBLIC LIRC : public QThread
    1213{
    1314    Q_OBJECT
     15
    1416  public:
    15     LircThread(QObject *main_window);
    16     ~LircThread();
    17     int Init(const QString &config_file, const QString &program,
    18                 bool ignoreExtApp=false);
    19     void Stop(void) { bStop = true; }
     17    LIRC(QObject *main_window,
     18         const QString &lircd_device,
     19         const QString &our_program,
     20         const QString &config_file,
     21         const QString &external_app);
     22    bool Init(void);
    2023
     24    virtual void start(void);
     25    virtual void deleteLater(void);
     26
    2127  private:
    22     void run(void);
     28    virtual ~LIRC();
     29    void TeardownAll();
     30
     31    bool IsDoRunSet(void) const;
     32    virtual void run(void);
    2333    void SpawnApp(void);
     34    QList<QByteArray> GetCodes(void);
     35    void Process(const QByteArray &data);
    2436
    25     struct lirc_config *lircConfig;
    26     QObject *mainWindow;
    27     volatile bool bStop;
    28     int fd;
    29 
    30     QString external_app;
     37    mutable QMutex  lock;
     38    static  QMutex  lirclib_lock;
     39    QObject        *mainWindow;  ///< window to send key events to
     40    QString         lircdDevice; ///< device on which to receive lircd data
     41    QString         program;     ///< program to extract from config file
     42    QString         configFile;  ///< config file containing LIRC->key mappings
     43    QString         externalApp; ///< external application for keys
     44    bool            doRun;
     45    int             lircd_socket;
     46    uint            buf_offset;
     47    QByteArray      buf;
     48    uint            eofCount;
     49    uint            retryCount;
     50    LIRCPriv       *d;
    3151};
    3252
    3353#endif
  • libs/libmythui/mythmainwindow.cpp

     
    123123    bool ignore_joystick_keys;
    124124
    125125#ifdef USE_LIRC
    126     LircThread *lircThread;
     126    LIRC *lircThread;
    127127#endif
    128128
    129129#ifdef USE_JOYSTICK_MENU
     
    327327        config_file = QDir::homePath() + "/.lircrc";
    328328
    329329    d->lircThread = NULL;
    330     d->lircThread = new LircThread(this);
    331     if (!d->lircThread->Init(config_file, "mythtv"))
     330    d->lircThread = new LIRC(
     331        this,
     332        GetMythDB()->GetSetting("LircSocket", "/dev/lircd"),
     333        "mythtv", config_file,
     334        GetMythDB()->GetSetting("LircKeyPressedApp", ""));
     335
     336    if (d->lircThread->Init())
    332337        d->lircThread->start();
    333338#endif
    334339
     
    412417#ifdef USE_LIRC
    413418    if (d->lircThread)
    414419    {
    415         if (d->lircThread->isRunning())
    416         {
    417             d->lircThread->Stop();
    418             d->lircThread->wait();
    419         }
    420 
    421         delete d->lircThread;
     420        d->lircThread->deleteLater();
    422421        d->lircThread = NULL;
    423422    }
    424423#endif
  • libs/libmythui/lirc.cpp

     
     1#include <algorithm>
     2#include <vector>
     3using namespace std;
     4
    15#include <QApplication>
    26#include <QEvent>
    37#include <QKeySequence>
     8#include <QStringList>
    49
    510#include <cstdio>
    611#include <cerrno>
     
    1520
    1621#include "lirc.h"
    1722#include "lircevent.h"
     23#include <lirc/lirc_client.h>
    1824
    19 /** \class LircThread
     25namespace POSIX
     26{
     27#include <sys/types.h>
     28#include <sys/select.h>
     29#include <sys/socket.h>
     30#include <sys/un.h>
     31#include <netinet/in.h>
     32#include <arpa/inet.h>
     33#include <netdb.h>
     34#include <unistd.h>
     35#include <fcntl.h>
     36};
     37using namespace POSIX;
     38
     39#define LOC      QString("LIRC: ")
     40#define LOC_WARN QString("LIRC, Warning: ")
     41#define LOC_ERR  QString("LIRC, Error: ")
     42
     43class LIRCPriv
     44{
     45  public:
     46    LIRCPriv() : lircConfig(NULL) {}
     47    ~LIRCPriv()
     48    {
     49        if (lircConfig)
     50        {
     51            lirc_freeconfig(lircConfig);
     52            lircConfig = NULL;
     53        }
     54    }
     55
     56    struct lirc_config *lircConfig;
     57};
     58
     59QMutex LIRC::lirclib_lock;
     60
     61/** \class LIRC
    2062 *  \brief Interface between mythtv and lircd
    2163 *
    2264 *   Create connection to the lircd daemon and translate remote keypresses
    2365 *   into custom events which are posted to the mainwindow.
    2466 */
    2567
    26 LircThread::LircThread(QObject *main_window)
    27           : QThread()
     68LIRC::LIRC(QObject *main_window,
     69           const QString &lircd_device,
     70           const QString &our_program,
     71           const QString &config_file,
     72           const QString &external_app)
     73    : QThread(),
     74      lock(QMutex::Recursive),
     75      mainWindow(main_window),
     76      lircdDevice(lircd_device),
     77      program(our_program),
     78      configFile(config_file),
     79      externalApp(external_app),
     80      doRun(false),
     81      lircd_socket(-1),
     82      buf_offset(0),
     83      eofCount(0),
     84      retryCount(0),
     85      d(new LIRCPriv())
    2886{
    29     mainWindow = main_window;
    30     bStop = false;
    31     lircConfig = NULL;
     87    lircdDevice.detach();
     88    program.detach();
     89    configFile.detach();
     90    externalApp.detach();
     91    buf.resize(128);
    3292}
    3393
    34 int LircThread::Init(const QString &config_file, const QString &program,
    35                         bool ignoreExtApp)
     94LIRC::~LIRC()
    3695{
    37     /* Connect the unix socket */
    38     fd = lirc_init((char *)qPrintable(program), 1);
    39     if (fd == -1)
     96    TeardownAll();
     97}
     98
     99void LIRC::deleteLater(void)
     100{
     101    TeardownAll();
     102    QThread::deleteLater();
     103}
     104
     105void LIRC::TeardownAll(void)
     106{
     107    QMutexLocker locker(&lock);
     108    if (doRun)
    40109    {
    41         VERBOSE(VB_IMPORTANT,
    42                 QString("lirc_init failed for %1, see preceding messages")
    43                 .arg(program));
    44         return -1;
     110        doRun = false;
     111        lock.unlock();
     112        wait();
     113        lock.lock();
    45114    }
    46115
    47     /* parse the config file */
    48     if (lirc_readconfig((char *)qPrintable(config_file), &lircConfig, NULL))
     116    if (lircd_socket >= 0)
    49117    {
    50         VERBOSE(VB_IMPORTANT,
    51                 QString("Failed to read lirc config %1 for %2")
    52                 .arg(config_file).arg(program));
    53         lirc_deinit();
    54         return -1;
     118        close(lircd_socket);
     119        lircd_socket = -1;
    55120    }
    56121
    57     if (!ignoreExtApp)
    58         external_app = GetMythDB()->GetSetting("LircKeyPressedApp", "");
     122    if (d)
     123    {
     124        delete d;
     125        d = NULL;
     126    }
     127}
    59128
    60     VERBOSE(VB_GENERAL,
    61             QString("lirc init success using configuration file: %1")
    62             .arg(config_file));
     129QByteArray get_ip(const QString &h)
     130{
     131    QByteArray hba = h.toLatin1();
     132    struct in_addr sin_addr;
     133    if (inet_aton(hba.constData(), &sin_addr))
     134        return hba;
    63135
    64     return 0;
    65 }
     136    struct addrinfo hints;
     137    memset(&hints, 0, sizeof(hints));
     138    hints.ai_family   = AF_INET;
     139    hints.ai_socktype = SOCK_STREAM;
     140    hints.ai_protocol = IPPROTO_TCP;
    66141
    67 LircThread::~LircThread()
    68 {
    69     lirc_deinit();
    70     if (lircConfig)
    71         lirc_freeconfig(lircConfig);
     142    struct addrinfo *result;
     143    int err = getaddrinfo(hba.constData(), NULL, &hints, &result);
     144    if (err)
     145    {
     146        VERBOSE(VB_IMPORTANT, QString("get_ip: %1").arg(gai_strerror(err)));
     147        return QString("").toLatin1();
     148    }
     149
     150    int addrlen = result->ai_addrlen;
     151    if (!addrlen)
     152    {
     153        freeaddrinfo(result);
     154        return QString("").toLatin1();
     155    }
     156
     157    if (result->ai_addr->sa_family != AF_INET)
     158    {
     159        freeaddrinfo(result);
     160        return QString("").toLatin1();
     161    }
     162
     163    sin_addr = ((struct sockaddr_in*)(result->ai_addr))->sin_addr;
     164    hba = QByteArray(inet_ntoa(sin_addr));
     165    freeaddrinfo(result);
     166
     167    return hba;
    72168}
    73169
    74 void LircThread::run(void)
     170bool LIRC::Init(void)
    75171{
    76     char *code = 0;
    77     char *ir = 0;
    78     int ret;
    79     fd_set readfds;
    80     struct timeval timeout;
     172    QMutexLocker locker(&lock);
    81173
    82     /* Process all events read */
    83     while (!bStop)
     174    if (lircd_socket >= 0)
     175        return true;
     176
     177    if (lircdDevice.startsWith('/'))
    84178    {
    85         FD_ZERO(&readfds);
    86         FD_SET(fd, &readfds);
     179        // Connect the unix socket
     180        QByteArray dev = lircdDevice.toLocal8Bit();
     181        if (dev.size() > 107)
     182        {
     183            VERBOSE(VB_IMPORTANT, LOC_ERR + QString("lircdDevice '%1'")
     184                    .arg(lircdDevice) +
     185                    " is too long for the 'unix' socket API");
    87186
    88         // the maximum time select() should wait
    89         timeout.tv_sec = 0;
    90         timeout.tv_usec = 100000;
     187            return false;
     188        }
    91189
    92         ret = select(fd + 1, &readfds, NULL, NULL, &timeout);
     190        lircd_socket = socket(AF_UNIX, SOCK_STREAM, 0);
     191        if (lircd_socket < 0)
     192        {
     193            VERBOSE(VB_IMPORTANT, LOC_ERR +
     194                    QString("Failed to open Unix socket '%1'")
     195                    .arg(lircdDevice) + ENO);
    93196
    94         if (ret == 0)
    95             continue;
     197            return false;
     198        }
    96199
    97         if (ret == -1)
     200        struct sockaddr_un addr;
     201        memset(&addr, 0, sizeof(sockaddr_un));
     202        addr.sun_family = AF_UNIX;
     203        strncpy(addr.sun_path, dev.constData(),107);
     204
     205        int ret = POSIX::connect(
     206            lircd_socket, (struct sockaddr*) &addr, sizeof(addr));
     207
     208        if (ret < 0)
    98209        {
    99             perror("LircThread - select");
    100             return;
     210            VERBOSE(VB_IMPORTANT, LOC_ERR +
     211                    QString("Failed to connect to Unix socket '%1'")
     212                    .arg(lircdDevice) + ENO);
     213
     214            close(lircd_socket);
     215            lircd_socket = -1;
     216            return false;
    101217        }
     218    }
     219    else
     220    {
     221        lircd_socket = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
     222        if (lircd_socket < 0)
     223        {
     224            VERBOSE(VB_IMPORTANT, LOC_ERR +
     225                    QString("Failed to open TCP socket '%1'")
     226                    .arg(lircdDevice) + ENO);
    102227
    103         if (ret == 1)
     228            return false;
     229        }
     230
     231        QString dev  = lircdDevice;
     232        uint    port = 8765;
     233        QStringList tmp = lircdDevice.split(':');
     234        if (2 == tmp.size())
    104235        {
    105             ret = lirc_nextcode(&ir);
     236            dev  = tmp[0];
     237            port = (tmp[1].toUInt()) ? tmp[1].toUInt() : port;
     238        }
     239        QByteArray device = get_ip(dev);
     240        struct sockaddr_in addr;
     241        memset(&addr, 0, sizeof(sockaddr_in));
     242        addr.sin_family = AF_INET;
     243        addr.sin_port   = htons(port);
    106244
    107             if (ret == -1)
     245        if (!inet_aton(device.constData(), &addr.sin_addr))
     246        {
     247            VERBOSE(VB_IMPORTANT, LOC_ERR +
     248                    QString("Failed to parse IP address '%1'").arg(dev));
     249
     250            close(lircd_socket);
     251            lircd_socket = -1;
     252            return false;
     253        }
     254
     255        int ret = POSIX::connect(
     256            lircd_socket, (struct sockaddr*) &addr, sizeof(addr));
     257        if (ret < 0)
     258        {
     259            VERBOSE(VB_IMPORTANT, LOC_ERR +
     260                    QString("Failed to connect TCP socket '%1'")
     261                    .arg(lircdDevice) + ENO);
     262
     263            close(lircd_socket);
     264            lircd_socket = -1;
     265            return false;
     266        }
     267
     268        // On Linux, select() can indicate data when there isn't
     269        // any due to TCP checksum in-particular; to avoid getting
     270        // stuck on a read() call add the O_NONBLOCK flag.
     271        int flags = fcntl(lircd_socket, F_GETFD);
     272        if (flags >= 0)
     273        {
     274            ret = fcntl(lircd_socket, F_SETFD, flags | O_NONBLOCK);
     275            if (ret < 0)
    108276            {
    109                 if (errno != 0)
    110                     VERBOSE(VB_IMPORTANT, QString("LircThread: lirc_nextcode failed"
    111                                                   "last error was: %1").arg(errno));
    112                 return;
     277                VERBOSE(VB_IMPORTANT, LOC_WARN +
     278                        QString("Failed set flags for socket '%1'")
     279                        .arg(lircdDevice) + ENO);
    113280            }
     281        }
    114282
    115             if (!ir)
    116                 continue;
     283        // Attempt to inline out-of-band messages and keep the connection open..
     284        int i = 1;
     285        setsockopt(lircd_socket, SOL_SOCKET, SO_OOBINLINE, &i, sizeof(i));
     286        i = 1;
     287        setsockopt(lircd_socket, SOL_SOCKET, SO_KEEPALIVE, &i, sizeof(i));
     288    }
    117289
    118             while ((ret = lirc_code2char(lircConfig, ir, &code)) == 0 &&
    119                 code != NULL)
     290    // parse the config file
     291    if (!d->lircConfig)
     292    {
     293        QMutexLocker static_lock(&lirclib_lock);
     294        QByteArray cfg = configFile.toLocal8Bit();
     295        if (lirc_readconfig(
     296                const_cast<char*>(cfg.constData()), &d->lircConfig, NULL))
     297        {
     298            VERBOSE(VB_IMPORTANT, LOC_ERR +
     299                    QString("Failed to read config file '%1'").arg(configFile));
     300
     301            close(lircd_socket);
     302            lircd_socket = -1;
     303            return false;
     304        }
     305
     306        // Get rid of the stuff we don't care about..
     307        vector<struct lirc_config_entry*> del;
     308        struct lirc_config_entry *it = d->lircConfig->first;
     309        while (it->next)
     310        {
     311            if (program == QString(it->next->prog))
    120312            {
    121                 QKeySequence a(code);
     313                it = it->next;
     314            }
     315            else
     316            {
     317                del.push_back(it->next);
     318                it->next = it->next->next;
     319            }
     320        }
     321        if (program != QString(d->lircConfig->first->prog))
     322        {
     323            del.push_back(d->lircConfig->first);
     324            d->lircConfig->first = d->lircConfig->first->next;
     325        }
     326        d->lircConfig->next = d->lircConfig->first;
    122327
    123                 int keycode = 0;
     328        for (uint i = 0; i < del.size(); i++)
     329        {
     330            struct lirc_config_entry *c = del[i];
     331            if (c->prog)
     332                free(c->prog);
     333            if (c->change_mode)
     334                free(c->change_mode);
     335            if (c->mode)
     336                free(c->mode);
    124337
    125                 // Send a dummy keycode if we couldn't convert the key sequence.
    126                 // This is done so the main code can output a warning for bad
    127                 // mappings.
    128                 if (!a.count())
    129                     QApplication::postEvent(mainWindow, new LircKeycodeEvent(code,
    130                                             keycode, true));
     338            struct lirc_code *code = c->code;
     339            while (code)
     340            {
     341                if (code->remote && code->remote!=LIRC_ALL)
     342                    free(code->remote);
     343                if (code->button && code->button!=LIRC_ALL)
     344                    free(code->button);
     345                struct lirc_code *code_temp = code->next;
     346                free(code);
     347                code = code_temp;
     348            }
    131349
    132                 for (unsigned int i = 0; i < a.count(); i++)
    133                 {
    134                     keycode = a[i];
     350            struct lirc_list *list = c->config;
     351            while (list)
     352            {
     353                if (list->string)
     354                    free(list->string);
     355                struct lirc_list *list_temp = list->next;
     356                free(list);
     357                list = list_temp;
     358            }
    135359
    136                     QApplication::postEvent(mainWindow, new LircKeycodeEvent(code,
    137                                             keycode, true));
    138                     QApplication::postEvent(mainWindow, new LircKeycodeEvent(code,
    139                                             keycode, false));
     360            free(c);
     361        }
     362    }
    140363
    141                     SpawnApp();
    142                 }
     364    VERBOSE(VB_GENERAL, LOC +
     365            QString("Successfully initialized '%1' using '%2' config")
     366            .arg(lircdDevice).arg(configFile));
     367
     368    return true;
     369}
     370
     371void LIRC::start(void)
     372{
     373    QMutexLocker locker(&lock);
     374
     375    if (lircd_socket < 0)
     376    {
     377        VERBOSE(VB_IMPORTANT, LOC_ERR + "start() called without lircd socket");
     378        return;
     379    }
     380
     381    doRun = true;
     382    QThread::start();
     383}
     384
     385bool LIRC::IsDoRunSet(void) const
     386{
     387    QMutexLocker locker(&lock);
     388    return doRun;
     389}
     390
     391void LIRC::Process(const QByteArray &data)
     392{
     393    QMutexLocker static_lock(&lirclib_lock);
     394
     395    // lirc_code2char will make code point to a static datafer..
     396    char *code = NULL;
     397    int ret = lirc_code2char(
     398        d->lircConfig, const_cast<char*>(data.constData()), &code);
     399
     400    while ((0 == ret) && code)
     401    {
     402        QString text(code);
     403        QKeySequence a(code);
     404
     405        int keycode = 0;
     406
     407        // Send a dummy keycode if we couldn't convert the key sequence.
     408        // This is done so the main code can output a warning for bad
     409        // mappings.
     410        if (!a.count())
     411        {
     412            QApplication::postEvent(
     413                mainWindow, new LircKeycodeEvent(text, keycode, true));
     414        }
     415
     416        for (unsigned int i = 0; i < a.count(); i++)
     417        {
     418            keycode = a[i];
     419
     420            QApplication::postEvent(
     421                mainWindow, new LircKeycodeEvent(text, keycode, true));
     422            QApplication::postEvent(
     423                mainWindow, new LircKeycodeEvent(text, keycode, false));
     424
     425            SpawnApp();
     426        }
     427        ret = lirc_code2char(
     428            d->lircConfig, const_cast<char*>(data.constData()), &code);
     429    }
     430}
     431
     432void LIRC::run(void)
     433{
     434    //VERBOSE(VB_GENERAL, LOC + "run -- start");
     435    /* Process all events read */
     436    while (IsDoRunSet())
     437    {
     438        if (eofCount && retryCount)
     439            usleep(100 * 1000);
     440
     441        if ((eofCount >= 10) || (lircd_socket < 0))
     442        {
     443            QMutexLocker locker(&lock);
     444            eofCount = 0;
     445            if (++retryCount > 1000)
     446            {
     447                VERBOSE(VB_IMPORTANT, LOC_ERR +
     448                        "Failed to reconnect, exiting LIRC thread.");
     449                doRun = false;
     450                continue;
    143451            }
     452            VERBOSE(VB_GENERAL, LOC_WARN + "EOF -- reconnecting");
    144453
    145             free(ir);
    146             if (ret == -1)
    147                 break;
     454            close(lircd_socket);
     455            lircd_socket = -1;
     456
     457            if (!Init())
     458                sleep(2); // wait a while before we retry..
     459
     460            continue;
    148461        }
     462
     463        fd_set readfds;
     464        FD_ZERO(&readfds);
     465        FD_SET(lircd_socket, &readfds);
     466
     467        // the maximum time select() should wait
     468        struct timeval timeout;
     469        timeout.tv_sec = 1; // 1 second
     470        timeout.tv_usec = 100 * 1000; // 100 ms
     471
     472        int ret = select(lircd_socket + 1, &readfds, NULL, NULL, &timeout);
     473
     474        if (ret < 0 && errno != EINTR)
     475        {
     476            VERBOSE(VB_IMPORTANT, LOC_ERR + "select() failed" + ENO);
     477            continue;
     478        }
     479
     480        //  0: Timer expired with no data, repeat select
     481        // -1: Iinterrupted while waiting, repeat select
     482        if (ret <= 0)
     483            continue;
     484
     485        QList<QByteArray> codes = GetCodes();
     486        for (uint i = 0; i < (uint) codes.size(); i++)
     487            Process(codes[i]);
    149488    }
     489    //VERBOSE(VB_GENERAL, LOC + "run -- end");
    150490}
    151491
     492QList<QByteArray> LIRC::GetCodes(void)
     493{
     494    QList<QByteArray> ret;
     495    ssize_t len = -1;
     496    do
     497    {
     498        len = read(lircd_socket,
     499                   buf.data() + buf_offset,
     500                   buf.size() - buf_offset - 1);
    152501
    153 void LircThread::SpawnApp(void)
     502        if (len >= 0)
     503            break;
     504
     505        if (EINTR == errno)
     506            continue;
     507        else if (EAGAIN == errno)
     508            return ret;
     509        else if (107 == errno)
     510        {
     511            if (!eofCount)
     512                VERBOSE(VB_GENERAL, LOC + "GetCodes -- EOF?");
     513            eofCount++;
     514            return ret;
     515        }
     516        else
     517        {
     518            VERBOSE(VB_IMPORTANT, LOC + "Error reading socket" + ENO);
     519            return ret;
     520        }
     521    } while (false);
     522
     523    if (0 == len)
     524    {
     525        if (!eofCount)
     526            VERBOSE(VB_GENERAL, LOC + "GetCodes -- eof?");
     527        eofCount++;
     528        return ret;
     529    }
     530
     531    eofCount   = 0;
     532    retryCount = 0;
     533
     534    buf_offset += len;
     535    if ((uint)buf.size() < buf_offset + 128)
     536        buf.reserve(buf.size() * 2);
     537    uint tmpc = std::max(buf.capacity() - 1,128);
     538
     539    buf.resize(buf_offset);
     540    ret = buf.split('\n');
     541    buf.resize(tmpc);
     542    if (buf.endsWith('\n'))
     543    {
     544        buf_offset = 0;
     545        return ret;
     546    }
     547
     548    buf = ret.back();
     549    ret.pop_back();
     550    buf_offset = std::max(buf.size() - 1, 0);
     551    buf.resize(tmpc);
     552
     553    return ret;
     554}
     555
     556void LIRC::SpawnApp(void)
    154557{
    155558    // Spawn app to illuminate led (or what ever the user has picked if
    156559    // anything) to give positive feedback that a key was received
    157     if (external_app.isEmpty())
     560    if (externalApp.isEmpty())
    158561        return;
    159562
    160     QString command = external_app + " &";
     563    QString command = externalApp + " &";
    161564
    162565    int status = myth_system(command);
    163566
  • programs/mythfrontend/globalsettings.cpp

     
    22732273    return ge;
    22742274}
    22752275
     2276static HostLineEdit *LircDaemonDevice()
     2277{
     2278    HostLineEdit *ge = new HostLineEdit("LircSocket");
     2279    ge->setLabel(QObject::tr("LIRC Daemon Socket"));
     2280    ge->setValue("/dev/lircd");
     2281    QString help = QObject::tr(
     2282        "UNIX socket or IP address[:port] to connect in "
     2283        "order to communicate with the LIRC Daemon.");
     2284    ge->setHelpText(help);
     2285    return ge;
     2286}
     2287
    22762288static HostLineEdit *LircKeyPressedApp()
    22772289{
    22782290    HostLineEdit *ge = new HostLineEdit("LircKeyPressedApp");
    2279     ge->setLabel(QObject::tr("Keypress Application"));
     2291    ge->setLabel(QObject::tr("LIRC Keypress Application"));
    22802292    ge->setValue("");
    22812293    ge->setHelpText(QObject::tr("External application or script to run when "
    22822294                    "a keypress is received by LIRC."));
     
    22862298static HostLineEdit *ScreenShotPath()
    22872299{
    22882300    HostLineEdit *ge = new HostLineEdit("ScreenShotPath");
    2289     ge->setLabel(QObject::tr("ScreenShotPath"));
     2301    ge->setLabel(QObject::tr("Screen Shot Path"));
    22902302    ge->setValue("/tmp/");
    22912303    ge->setHelpText(QObject::tr("Path to screenshot storage location. Should be writable by the frontend"));
    22922304    return ge;
     
    45714583    VerticalConfigurationGroup *general =
    45724584        new VerticalConfigurationGroup(false, true, false, false);
    45734585    general->setLabel(QObject::tr("General"));
     4586    general->addChild(AllowQuitShutdown());
    45744587    HorizontalConfigurationGroup *row =
    45754588        new HorizontalConfigurationGroup(false, false, true, true);
    4576     VerticalConfigurationGroup *col1 =
    4577         new VerticalConfigurationGroup(false, false, true, true);
    4578     VerticalConfigurationGroup *col2 =
    4579         new VerticalConfigurationGroup(false, false, true, true);
    4580     col1->addChild(AllowQuitShutdown());
    4581     col1->addChild(NoPromptOnExit());
    4582     col2->addChild(UseArrowAccels());
    4583     col2->addChild(NetworkControlEnabled());
    4584     row->addChild(col1);
    4585     row->addChild(col2);
    4586 
    4587     MythMediaSettings *mediaMon = new MythMediaSettings();
    4588 
    4589     general->addChild(LircKeyPressedApp());
     4589    row->addChild(NoPromptOnExit());
     4590    row->addChild(UseArrowAccels());
     4591    general->addChild(row);
     4592    general->addChild(new MythMediaSettings());
    45904593    general->addChild(ScreenShotPath());
    4591     general->addChild(row);
    4592     general->addChild(NetworkControlPort());
    4593     general->addChild(mediaMon);
    45944594    addChild(general);
    45954595
     4596    VerticalConfigurationGroup *remotecontrol =
     4597        new VerticalConfigurationGroup(false, true, false, false);
     4598    remotecontrol->setLabel(QObject::tr("Remote Control"));
     4599    remotecontrol->addChild(LircDaemonDevice());
     4600    remotecontrol->addChild(LircKeyPressedApp());
     4601    remotecontrol->addChild(NetworkControlEnabled());
     4602    remotecontrol->addChild(NetworkControlPort());
     4603    addChild(remotecontrol);
     4604
    45964605    VerticalConfigurationGroup* misc = new VerticalConfigurationGroup(false);
    45974606    misc->setLabel(QObject::tr("Miscellaneous"));
    45984607