Index: mythtv/libs/libmythui/lirc.h
===================================================================
--- mythtv/libs/libmythui/lirc.h	(révision 19114)
+++ mythtv/libs/libmythui/lirc.h	(copie de travail)
@@ -3,35 +3,53 @@
 
 #include <QThread>
 #include <QString>
+#include <QMutex>
 
-#include <lirc/lirc_client.h>
-
 /** \class LircThread
  *  \brief Interface between mythtv and lircd
  *
  *   Create connection to the lircd daemon and translate remote keypresses
  *   into custom events which are posted to the mainwindow.
  */
-class LircThread : public QThread
+class LIRCPriv;
+class MPUBLIC LIRC : public QThread
 {
     Q_OBJECT
   public:
-    LircThread(QObject *main_window);
-    ~LircThread();
-    int Init(const QString &config_file, const QString &program,
-                bool ignoreExtApp=false);
-    void Stop(void) { m_bStop = true; }
+    LIRC(QObject *main_window,
+         const QString &lircd_device,
+         const QString &our_program,
+         const QString &config_file,
+         const QString &external_app);
+    bool Init(void);
 
+    virtual void start(void);
+    virtual void deleteLater(void);
+
   private:
-    void run(void);
+    virtual ~LIRC();
+    void TeardownAll();
+
+    bool IsDoRunSet(void) const;
+    virtual void run(void);
     void SpawnApp(void);
+    QList<QByteArray> GetCodes(void);
+    void Process(const QByteArray &data);
 
-    struct lirc_config *m_lircConfig;
-    QObject *m_mainWindow;
-    volatile bool m_bStop;
-    int m_fd;
-
-    QString m_externalApp;
+    mutable QMutex  lock;
+    static  QMutex  lirclib_lock;
+    QObject        *m_mainWindow;  ///< window to send key events to
+    QString         lircdDevice; ///< device on which to receive lircd data
+    QString         program;     ///< program to extract from config file
+    QString         configFile;  ///< config file containing LIRC->key mappings
+    QString         m_externalApp; ///< external application for keys
+    bool            doRun;
+    int             lircd_socket;
+    uint            buf_offset;
+    QByteArray      buf;
+    uint            eofCount;
+    uint            retryCount;
+    LIRCPriv       *d;
 };
 
 #endif
Index: mythtv/libs/libmythui/mythmainwindow.cpp
===================================================================
--- mythtv/libs/libmythui/mythmainwindow.cpp	(revision 18470)
+++ mythtv/libs/libmythui/mythmainwindow.cpp	(working copy)
@@ -116,7 +116,7 @@
     bool ignore_joystick_keys;
 
 #ifdef USE_LIRC
-    LircThread *lircThread;
+    LIRC *lircThread;
 #endif
 
 #ifdef USE_JOYSTICK_MENU
@@ -319,8 +319,13 @@
         config_file = QDir::homePath() + "/.lircrc";
 
     d->lircThread = NULL;
-    d->lircThread = new LircThread(this);
-    if (!d->lircThread->Init(config_file, "mythtv"))
+    d->lircThread = new LIRC(
+        this,
+        GetMythDB()->GetSetting("LircSocket", "/dev/lircd"),
+        "mythtv", config_file,
+        GetMythDB()->GetSetting("LircKeyPressedApp", ""));
+
+    if (d->lircThread->Init())
         d->lircThread->start();
 #endif
 
@@ -426,13 +431,7 @@
 #ifdef USE_LIRC
     if (d->lircThread)
     {
-        if (d->lircThread->isRunning())
-        {
-            d->lircThread->Stop();
-            d->lircThread->wait();
-        }
-
-        delete d->lircThread;
+        d->lircThread->deleteLater();
         d->lircThread = NULL;
     }
 #endif
Index: mythtv/libs/libmythui/lirc.cpp
===================================================================
--- mythtv/libs/libmythui/lirc.cpp	(revision 18470)
+++ mythtv/libs/libmythui/lirc.cpp	(working copy)
@@ -1,6 +1,11 @@
+#include <algorithm>
+#include <vector>
+using namespace std;
+
 #include <QApplication>
 #include <QEvent>
 #include <QKeySequence>
+#include <QStringList>
 
 #include <cstdio>
 #include <cerrno>
@@ -15,150 +20,542 @@
 
 #include "lirc.h"
 #include "lircevent.h"
+#include <lirc/lirc_client.h>
 
-LircThread::LircThread(QObject *main_window)
+namespace POSIX
+{
+#include <sys/types.h>
+#include <sys/select.h>
+#include <sys/socket.h>
+#include <sys/un.h>
+#include <netinet/in.h>
+#include <arpa/inet.h>
+#include <netdb.h>
+#include <unistd.h>
+#include <fcntl.h>
+};
+using namespace POSIX;
+
+#define LOC      QString("LIRC: ")
+#define LOC_WARN QString("LIRC, Warning: ")
+#define LOC_ERR  QString("LIRC, Error: ")
+
+class LIRCPriv
+{
+  public:
+    LIRCPriv() : lircConfig(NULL) {}
+    ~LIRCPriv()
+    {
+        if (lircConfig)
+        {
+            lirc_freeconfig(lircConfig);
+            lircConfig = NULL;
+        }
+    }
+
+    struct lirc_config *lircConfig;
+};
+
+QMutex LIRC::lirclib_lock;
+
+/** \class LIRC
+ *  \brief Interface between mythtv and lircd
+ *
+ *   Create connection to the lircd daemon and translate remote keypresses
+ *   into custom events which are posted to the mainwindow.
+ */
+
+LIRC::LIRC(QObject *main_window,
+           const QString &lircd_device,
+           const QString &our_program,
+           const QString &config_file,
+           const QString &external_app)
     : QThread(),
-      m_lircConfig(NULL), m_mainWindow(main_window),
-      m_bStop(false),     m_fd(-1),
-      m_externalApp("")
+      lock(QMutex::Recursive),
+      m_mainWindow(main_window),
+      lircdDevice(lircd_device),
+      program(our_program),
+      configFile(config_file),
+      m_externalApp(external_app),
+      doRun(false),
+      lircd_socket(-1),
+      buf_offset(0),
+      eofCount(0),
+      retryCount(0),
+      d(new LIRCPriv())
 {
+    lircdDevice.detach();
+    program.detach();
+    configFile.detach();
+    m_externalApp.detach();
+    buf.resize(128);
 }
 
-/**
- *  \brief Initialise the class variables, read the lirc config and user
- *         settings
- */
-int LircThread::Init(const QString &config_file, const QString &program,
-                        bool ignoreExtApp)
+LIRC::~LIRC()
 {
-    /* Connect the unix socket */
-    m_fd = lirc_init((char *)qPrintable(program), 1);
-    if (m_fd == -1)
+    TeardownAll();
+}
+
+void LIRC::deleteLater(void)
+{
+    TeardownAll();
+    QThread::deleteLater();
+}
+
+void LIRC::TeardownAll(void)
+{
+    QMutexLocker locker(&lock);
+    if (doRun)
     {
-        VERBOSE(VB_IMPORTANT,
-                QString("lirc_init failed for %1, see preceding messages")
-                .arg(program));
-        return -1;
+        doRun = false;
+        lock.unlock();
+        wait();
+        lock.lock();
     }
 
-    /* parse the config file */
-    if (lirc_readconfig((char *)qPrintable(config_file), &m_lircConfig, NULL))
+    if (lircd_socket >= 0)
     {
-        VERBOSE(VB_IMPORTANT,
-                QString("Failed to read lirc config %1 for %2")
-                .arg(config_file).arg(program));
-        lirc_deinit();
-        return -1;
+        close(lircd_socket);
+        lircd_socket = -1;
     }
 
-    if (!ignoreExtApp)
-        m_externalApp = GetMythDB()->GetSetting("LircKeyPressedApp", "");
+    if (d)
+    {
+        delete d;
+        d = NULL;
+    }
+}
 
-    VERBOSE(VB_GENERAL,
-            QString("lirc init success using configuration file: %1")
-            .arg(config_file));
+QByteArray get_ip(const QString &h)
+{
+    QByteArray hba = h.toLatin1();
+    struct in_addr sin_addr;
+    if (inet_aton(hba.constData(), &sin_addr))
+        return hba;
 
-    return 0;
-}
+    struct addrinfo hints;
+    memset(&hints, 0, sizeof(hints));
+    hints.ai_family   = AF_INET;
+    hints.ai_socktype = SOCK_STREAM;
+    hints.ai_protocol = IPPROTO_TCP;
 
-LircThread::~LircThread()
-{
-    lirc_deinit();
-    if (m_lircConfig)
-        lirc_freeconfig(m_lircConfig);
+    struct addrinfo *result;
+    int err = getaddrinfo(hba.constData(), NULL, &hints, &result);
+    if (err)
+    {
+        VERBOSE(VB_IMPORTANT, QString("get_ip: %1").arg(gai_strerror(err)));
+        return QString("").toLatin1();
+    }
+
+    int addrlen = result->ai_addrlen;
+    if (!addrlen)
+    {
+        freeaddrinfo(result);
+        return QString("").toLatin1();
+    }
+
+    if (result->ai_addr->sa_family != AF_INET)
+    {
+        freeaddrinfo(result);
+        return QString("").toLatin1();
+    }
+
+    sin_addr = ((struct sockaddr_in*)(result->ai_addr))->sin_addr;
+    hba = QByteArray(inet_ntoa(sin_addr));
+    freeaddrinfo(result);
+
+    return hba;
 }
 
-/**
- *  \brief Main thread loop
- */
-void LircThread::run(void)
+bool LIRC::Init(void)
 {
-    char *code = 0;
-    char *ir = 0;
-    int ret;
-    fd_set readfds;
-    struct timeval timeout;
+    QMutexLocker locker(&lock);
+    if (lircd_socket >= 0)
+        return true;
 
-    /* Process all events read */
-    while (!m_bStop)
+    if (lircdDevice.startsWith('/'))
     {
-        FD_ZERO(&readfds);
-        FD_SET(m_fd, &readfds);
+        // Connect the unix socket
+        QByteArray dev = lircdDevice.toLocal8Bit();
+        if (dev.size() > 107)
+        {
+            VERBOSE(VB_IMPORTANT, LOC_ERR + QString("lircdDevice '%1'")
+                    .arg(lircdDevice) +
+                    " is too long for the 'unix' socket API");
 
-        // the maximum time select() should wait
-        timeout.tv_sec = 0;
-        timeout.tv_usec = 100000;
+            return false;
+        }
 
-        ret = select(m_fd + 1, &readfds, NULL, NULL, &timeout);
+        lircd_socket = socket(AF_UNIX, SOCK_STREAM, 0);
+        if (lircd_socket < 0)
+        {
+            VERBOSE(VB_IMPORTANT, LOC_ERR +
+                    QString("Failed to open Unix socket '%1'")
+                    .arg(lircdDevice) + ENO);
 
-        if (ret == 0)
-            continue;
+            return false;
+        }
 
-        if (ret == -1)
+        struct sockaddr_un addr;
+        memset(&addr, 0, sizeof(sockaddr_un));
+        addr.sun_family = AF_UNIX;
+        strncpy(addr.sun_path, dev.constData(),107);
+
+        int ret = POSIX::connect(
+            lircd_socket, (struct sockaddr*) &addr, sizeof(addr));
+
+        if (ret < 0)
         {
-            perror("LircThread - select");
-            return;
+            VERBOSE(VB_IMPORTANT, LOC_ERR +
+                    QString("Failed to connect to Unix socket '%1'")
+                    .arg(lircdDevice) + ENO);
+
+            close(lircd_socket);
+            lircd_socket = -1;
+            return false;
         }
+    }
+    else
+    {
+        lircd_socket = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
+        if (lircd_socket < 0)
+        {
+            VERBOSE(VB_IMPORTANT, LOC_ERR +
+                    QString("Failed to open TCP socket '%1'")
+                    .arg(lircdDevice) + ENO);
 
-        if (ret == 1)
+            return false;
+        }
+
+        QString dev  = lircdDevice;
+        uint    port = 8765;
+        QStringList tmp = lircdDevice.split(':');
+        if (2 == tmp.size())
         {
-            ret = lirc_nextcode(&ir);
+            dev  = tmp[0];
+            port = (tmp[1].toUInt()) ? tmp[1].toUInt() : port;
+        }
+        QByteArray device = get_ip(dev);
+        struct sockaddr_in addr;
+        memset(&addr, 0, sizeof(sockaddr_in));
+        addr.sin_family = AF_INET;
+        addr.sin_port   = htons(port);
 
-            if (ret == -1)
+        if (!inet_aton(device.constData(), &addr.sin_addr))
+        {
+            VERBOSE(VB_IMPORTANT, LOC_ERR +
+                    QString("Failed to parse IP address '%1'").arg(dev));
+
+            close(lircd_socket);
+            lircd_socket = -1;
+            return false;
+        }
+
+        int ret = POSIX::connect(
+            lircd_socket, (struct sockaddr*) &addr, sizeof(addr));
+        if (ret < 0)
+        {
+            VERBOSE(VB_IMPORTANT, LOC_ERR +
+                    QString("Failed to connect TCP socket '%1'")
+                    .arg(lircdDevice) + ENO);
+
+            close(lircd_socket);
+            lircd_socket = -1;
+            return false;
+        }
+
+        // On Linux, select() can indicate data when there isn't
+        // any due to TCP checksum in-particular; to avoid getting
+        // stuck on a read() call add the O_NONBLOCK flag.
+        int flags = fcntl(lircd_socket, F_GETFD); 
+        if (flags >= 0)
+        {
+            ret = fcntl(lircd_socket, F_SETFD, flags | O_NONBLOCK);
+            if (ret < 0)
             {
-                if (errno != 0)
-                    VERBOSE(VB_IMPORTANT,
-                                QString("LircThread: lirc_nextcode failed"
-                                        "last error was: %1").arg(errno));
-                return;
+                VERBOSE(VB_IMPORTANT, LOC_WARN +
+                        QString("Failed set flags for socket '%1'")
+                        .arg(lircdDevice) + ENO);
             }
+        }
 
-            if (!ir)
-                continue;
+        // Attempt to inline out-of-band messages and keep the connection open..
+        int i = 1;
+        setsockopt(lircd_socket, SOL_SOCKET, SO_OOBINLINE, &i, sizeof(i));
+        i = 1;
+        setsockopt(lircd_socket, SOL_SOCKET, SO_KEEPALIVE, &i, sizeof(i));
+    }
 
-            while ((ret = lirc_code2char(m_lircConfig, ir, &code)) == 0 &&
-                code != NULL)
+    // parse the config file
+    if (!d->lircConfig)
+    {
+        QMutexLocker static_lock(&lirclib_lock);
+        QByteArray cfg = configFile.toLocal8Bit();
+        if (lirc_readconfig(
+                const_cast<char*>(cfg.constData()), &d->lircConfig, NULL))
+        {
+            VERBOSE(VB_IMPORTANT, LOC_ERR +
+                    QString("Failed to read config file '%1'").arg(configFile));
+
+            close(lircd_socket);
+            lircd_socket = -1;
+            return false;
+        }
+
+        // Get rid of the stuff we don't care about..
+        vector<struct lirc_config_entry*> del;
+        struct lirc_config_entry *it = d->lircConfig->first;
+        while (it->next)
+        {
+            if (program == QString(it->next->prog))
             {
-                QKeySequence a(code);
+                it = it->next;
+            }
+            else
+            {
+                del.push_back(it->next);
+                it->next = it->next->next;
+            }
+        }
+        if (program != QString(d->lircConfig->first->prog))
+        {
+            del.push_back(d->lircConfig->first);
+            d->lircConfig->first = d->lircConfig->first->next;
+        }
+        d->lircConfig->next = d->lircConfig->first;
 
-                int keycode = 0;
+        for (uint i = 0; i < del.size(); i++)
+        {
+            struct lirc_config_entry *c = del[i];
+            if (c->prog)
+                free(c->prog);
+            if (c->change_mode)
+                free(c->change_mode);
+            if (c->mode)
+                free(c->mode);
 
-                // Send a dummy keycode if we couldn't convert the key sequence.
-                // This is done so the main code can output a warning for bad
-                // mappings.
-                if (!a.count())
-                    QApplication::postEvent(m_mainWindow,
-                                            new LircKeycodeEvent(code, keycode,
-                                                                 true));
+            struct lirc_code *code = c->code;
+            while (code)
+            {
+                if (code->remote && code->remote!=LIRC_ALL)
+                    free(code->remote);
+                if (code->button && code->button!=LIRC_ALL)
+                    free(code->button);
+                struct lirc_code *code_temp = code->next;
+                free(code);
+                code = code_temp;
+            }
 
-                for (unsigned int i = 0; i < a.count(); i++)
-                {
-                    keycode = a[i];
+            struct lirc_list *list = c->config;
+            while (list)
+            {
+                if (list->string)
+                    free(list->string);
+                struct lirc_list *list_temp = list->next;
+                free(list);
+                list = list_temp;
+            }
 
-                    QApplication::postEvent(m_mainWindow,
-                                            new LircKeycodeEvent(code, keycode,
-                                                                 true));
-                    QApplication::postEvent(m_mainWindow,
-                                            new LircKeycodeEvent(code, keycode,
-                                                                 false));
+            free(c);
+        }
+    }
 
-                    SpawnApp();
-                }
+    VERBOSE(VB_GENERAL, LOC +
+            QString("Successfully initialized '%1' using '%2' config")
+            .arg(lircdDevice).arg(configFile));
+
+    return true;
+}
+
+void LIRC::start(void)
+{
+    QMutexLocker locker(&lock);
+
+    if (lircd_socket < 0)
+    {
+        VERBOSE(VB_IMPORTANT, LOC_ERR + "start() called without lircd socket");
+        return;
+    }
+
+    doRun = true;
+    QThread::start();
+}
+
+bool LIRC::IsDoRunSet(void) const
+{
+    QMutexLocker locker(&lock);
+    return doRun;
+}
+
+void LIRC::Process(const QByteArray &data)
+{
+    QMutexLocker static_lock(&lirclib_lock);
+
+    // lirc_code2char will make code point to a static datafer..
+    char *code = NULL;
+    int ret = lirc_code2char(
+        d->lircConfig, const_cast<char*>(data.constData()), &code);
+
+    while ((0 == ret) && code)
+    {
+        QString text(code);
+        QKeySequence a(code);
+
+        int keycode = 0;
+
+        // Send a dummy keycode if we couldn't convert the key sequence.
+        // This is done so the main code can output a warning for bad
+        // mappings.
+        if (!a.count())
+        {
+            QApplication::postEvent(
+                m_mainWindow, new LircKeycodeEvent(text, keycode, true));
+        }
+
+        for (unsigned int i = 0; i < a.count(); i++)
+        {
+            keycode = a[i];
+
+            QApplication::postEvent(
+                m_mainWindow, new LircKeycodeEvent(text, keycode, true));
+            QApplication::postEvent(
+                m_mainWindow, new LircKeycodeEvent(text, keycode, false));
+
+            SpawnApp();
+        }
+        ret = lirc_code2char(
+            d->lircConfig, const_cast<char*>(data.constData()), &code);
+    }
+}
+
+void LIRC::run(void)
+{
+    //VERBOSE(VB_GENERAL, LOC + "run -- start");
+    /* Process all events read */
+    while (IsDoRunSet())
+    {
+        if (eofCount && retryCount)
+            usleep(100 * 1000);
+
+        if ((eofCount >= 10) || (lircd_socket < 0))
+        {
+            QMutexLocker locker(&lock);
+            eofCount = 0;
+            if (++retryCount > 1000)
+            {
+                VERBOSE(VB_IMPORTANT, LOC_ERR +
+                        "Failed to reconnect, exiting LIRC thread.");
+                doRun = false;
+                continue;
             }
+            VERBOSE(VB_GENERAL, LOC_WARN + "EOF -- reconnecting");
 
-            free(ir);
-            if (ret == -1)
-                break;
+            close(lircd_socket);
+            lircd_socket = -1;
+
+            if (!Init())
+                sleep(2); // wait a while before we retry..
+
+            continue;
         }
+
+        fd_set readfds;
+        FD_ZERO(&readfds);
+        FD_SET(lircd_socket, &readfds);
+
+        // the maximum time select() should wait
+        struct timeval timeout;
+        timeout.tv_sec = 1; // 1 second
+        timeout.tv_usec = 100 * 1000; // 100 ms
+
+        int ret = select(lircd_socket + 1, &readfds, NULL, NULL, &timeout);
+
+        if (ret < 0 && errno != EINTR)
+        {
+            VERBOSE(VB_IMPORTANT, LOC_ERR + "select() failed" + ENO);
+            continue;
+        }
+
+        //  0: Timer expired with no data, repeat select
+        // -1: Iinterrupted while waiting, repeat select
+        if (ret <= 0)
+            continue;
+
+        QList<QByteArray> codes = GetCodes();
+        for (uint i = 0; i < (uint) codes.size(); i++)
+            Process(codes[i]);
     }
+    //VERBOSE(VB_GENERAL, LOC + "run -- end");
 }
 
-/**
- *  \brief Spawn a user defined application which might do something like
- *         illuminating an led to give positive feedback that a key was received
- */
-void LircThread::SpawnApp(void)
+QList<QByteArray> LIRC::GetCodes(void)
 {
+    QList<QByteArray> ret;
+    ssize_t len = -1;
+    do
+    {
+        len = read(lircd_socket,
+                   buf.data() + buf_offset,
+                   buf.size() - buf_offset - 1);
+
+        if (len >= 0)
+            break;
+
+        if (EINTR == errno)
+            continue;
+        else if (EAGAIN == errno)
+            return ret;
+        else if (107 == errno)
+        {
+            if (!eofCount)
+                VERBOSE(VB_GENERAL, LOC + "GetCodes -- EOF?");
+            eofCount++;
+            return ret;
+        }
+        else
+        {
+            VERBOSE(VB_IMPORTANT, LOC + "Error reading socket" + ENO);
+            return ret;
+        }
+    } while (false);
+
+    if (0 == len)
+    {
+        if (!eofCount)
+            VERBOSE(VB_GENERAL, LOC + "GetCodes -- eof?");
+        eofCount++;
+        return ret;
+    }
+
+    eofCount   = 0;
+    retryCount = 0;
+
+    buf_offset += len;
+    if ((uint)buf.size() < buf_offset + 128)
+        buf.reserve(buf.size() * 2);
+    uint tmpc = std::max(buf.capacity() - 1,128);
+
+    buf.resize(buf_offset);
+    ret = buf.split('\n');
+    buf.resize(tmpc);
+    if (buf.endsWith('\n'))
+    {
+        buf_offset = 0;
+        return ret;
+    }
+
+    buf = ret.back();
+    ret.pop_back();
+    buf_offset = std::max(buf.size() - 1, 0);
+    buf.resize(tmpc);
+
+    return ret;
+}
+
+void LIRC::SpawnApp(void)
+{
+    // Spawn app to illuminate led (or what ever the user has picked if
+    // anything) to give positive feedback that a key was received
     if (m_externalApp.isEmpty())
         return;
 
Index: mythtv/programs/mythfrontend/globalsettings.cpp
===================================================================
--- mythtv/programs/mythfrontend/globalsettings.cpp	(revision 18470)
+++ mythtv/programs/mythfrontend/globalsettings.cpp	(working copy)
@@ -2273,10 +2273,22 @@
     return ge;
 }
 
+static HostLineEdit *LircDaemonDevice()
+{
+    HostLineEdit *ge = new HostLineEdit("LircSocket");
+    ge->setLabel(QObject::tr("LIRC Daemon Socket"));
+    ge->setValue("/dev/lircd");
+    QString help = QObject::tr(
+        "UNIX socket or IP address[:port] to connect in "
+        "order to communicate with the LIRC Daemon.");
+    ge->setHelpText(help);
+    return ge;
+}
+
 static HostLineEdit *LircKeyPressedApp()
 {
     HostLineEdit *ge = new HostLineEdit("LircKeyPressedApp");
-    ge->setLabel(QObject::tr("Keypress Application"));
+    ge->setLabel(QObject::tr("LIRC Keypress Application"));
     ge->setValue("");
     ge->setHelpText(QObject::tr("External application or script to run when "
                     "a keypress is received by LIRC."));
@@ -2286,7 +2298,7 @@
 static HostLineEdit *ScreenShotPath()
 {
     HostLineEdit *ge = new HostLineEdit("ScreenShotPath");
-    ge->setLabel(QObject::tr("ScreenShotPath"));
+    ge->setLabel(QObject::tr("Screen Shot Path"));
     ge->setValue("/tmp/");
     ge->setHelpText(QObject::tr("Path to screenshot storage location. Should be writable by the frontend"));
     return ge;
@@ -4571,28 +4583,25 @@
     VerticalConfigurationGroup *general =
         new VerticalConfigurationGroup(false, true, false, false);
     general->setLabel(QObject::tr("General"));
+    general->addChild(AllowQuitShutdown());
     HorizontalConfigurationGroup *row =
         new HorizontalConfigurationGroup(false, false, true, true);
-    VerticalConfigurationGroup *col1 =
-        new VerticalConfigurationGroup(false, false, true, true);
-    VerticalConfigurationGroup *col2 =
-        new VerticalConfigurationGroup(false, false, true, true);
-    col1->addChild(AllowQuitShutdown());
-    col1->addChild(NoPromptOnExit());
-    col2->addChild(UseArrowAccels());
-    col2->addChild(NetworkControlEnabled());
-    row->addChild(col1);
-    row->addChild(col2);
-
-    MythMediaSettings *mediaMon = new MythMediaSettings();
-
-    general->addChild(LircKeyPressedApp());
+    row->addChild(NoPromptOnExit());
+    row->addChild(UseArrowAccels());
+    general->addChild(row);
+    general->addChild(new MythMediaSettings());
     general->addChild(ScreenShotPath());
-    general->addChild(row);
-    general->addChild(NetworkControlPort());
-    general->addChild(mediaMon);
     addChild(general);
 
+    VerticalConfigurationGroup *remotecontrol =
+        new VerticalConfigurationGroup(false, true, false, false);
+    remotecontrol->setLabel(QObject::tr("Remote Control"));
+    remotecontrol->addChild(LircDaemonDevice());
+    remotecontrol->addChild(LircKeyPressedApp());
+    remotecontrol->addChild(NetworkControlEnabled());
+    remotecontrol->addChild(NetworkControlPort());
+    addChild(remotecontrol);
+
     VerticalConfigurationGroup* misc = new VerticalConfigurationGroup(false);
     misc->setLabel(QObject::tr("Miscellaneous"));
 
