Ticket #5583: 5583-v4.patch

File 5583-v4.patch, 28.2 KB (added by danielk, 11 years ago)

Adds SIGUSR2 handler, inspired by #5929.

  • libs/libmythui/lirc.h

     
    11#ifndef LIRC_H_
    22#define LIRC_H_
    33
     4#include <QByteArray>
     5#include <QString>
     6#include <QObject>
    47#include <QThread>
    5 #include <QString>
     8#include <QMutex>
     9#include <QList>
    610
    7 #include <lirc/lirc_client.h>
     11class LIRCPriv;
    812
    9 /** \class LircThread
    10  *  \brief Interface between mythtv and lircd
    11  *
    12  *   Create connection to the lircd daemon and translate remote keypresses
    13  *   into custom events which are posted to the mainwindow.
    14  */
    15 class LircThread : public QThread
     13class LIRC : public QThread
    1614{
    1715    Q_OBJECT
    1816  public:
    19     LircThread(QObject *main_window);
    20     ~LircThread();
    21     int Init(const QString &config_file, const QString &program,
    22                 bool ignoreExtApp=false);
    23     void Stop(void) { m_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);
    2423
     24    virtual void start(void);
     25    virtual void deleteLater(void);
     26
    2527  private:
    26     void run(void);
     28    virtual ~LIRC();
     29    void TeardownAll();
     30
     31    bool IsDoRunSet(void) const;
     32    virtual void run(void);
    2733    void SpawnApp(void);
    28 
    29     struct lirc_config *m_lircConfig;
    30     QObject *m_mainWindow;
    31     volatile bool m_bStop;
    32     int m_fd;
    33 
    34     QString m_externalApp;
     34    QList<QByteArray> GetCodes(void);
     35    void Process(const QByteArray &data);
     36 
     37    mutable QMutex  lock;
     38    static  QMutex  lirclib_lock;
     39    QObject        *m_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;    ///< file containing LIRC->key mappings
     43    QString         m_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;
    3551};
    3652
    3753#endif
  • libs/libmythui/mythmainwindow.cpp

     
    2424#include <HIToolbox/Menus.h>   // For GetMBarHeight()
    2525#endif
    2626
    27 #ifdef USE_LIRC
    2827#include "lirc.h"
    2928#include "lircevent.h"
    30 #endif
    3129
    3230#ifdef USING_APPLEREMOTE
    3331#include "AppleRemoteListener.h"
    34 #include "lircevent.h"
    3532#endif
    3633
    3734#ifdef USE_JOYSTICK_MENU
     
    118115    bool ignore_lirc_keys;
    119116    bool ignore_joystick_keys;
    120117
    121 #ifdef USE_LIRC
    122     LircThread *lircThread;
    123 #endif
     118    LIRC *lircThread;
    124119
    125120#ifdef USE_JOYSTICK_MENU
    126121    JoystickMenuThread *joystickThread;
     
    336331
    337332    installEventFilter(this);
    338333
    339 #ifdef USE_LIRC
    340     QString config_file = GetConfDir() + "/lircrc";
    341     if (!QFile::exists(config_file))
    342         config_file = QDir::homePath() + "/.lircrc";
    343 
    344334    d->lircThread = NULL;
    345     d->lircThread = new LircThread(this);
    346     if (!d->lircThread->Init(config_file, "mythtv"))
    347         d->lircThread->start();
    348 #endif
     335    StartLIRC();
    349336
    350337#ifdef USE_JOYSTICK_MENU
    351338    d->ignore_joystick_keys = false;
     
    449436#ifdef USE_LIRC
    450437    if (d->lircThread)
    451438    {
    452         if (d->lircThread->isRunning())
    453         {
    454             d->lircThread->Stop();
    455             d->lircThread->wait();
    456         }
    457 
    458         delete d->lircThread;
     439        d->lircThread->deleteLater();
    459440        d->lircThread = NULL;
    460441    }
    461442#endif
     
    17621743    return d->uiScreenRect;
    17631744}
    17641745
     1746void MythMainWindow::StartLIRC(void)
     1747{
     1748#ifdef USE_LIRC
     1749    if (d->lircThread)
     1750    {
     1751        d->lircThread->deleteLater();
     1752        d->lircThread = NULL;
     1753    }
     1754
     1755    QString config_file = GetConfDir() + "/lircrc";
     1756    if (!QFile::exists(config_file))
     1757        config_file = QDir::homePath() + "/.lircrc";
     1758
     1759    d->lircThread = new LIRC(
     1760        this,
     1761        GetMythDB()->GetSetting("LircSocket", "/dev/lircd"),
     1762        "mythtv", config_file,
     1763        GetMythDB()->GetSetting("LircKeyPressedApp", ""));
     1764
     1765    if (d->lircThread->Init())
     1766    {
     1767        d->lircThread->start();
     1768    }
     1769    else
     1770    {
     1771        d->lircThread->deleteLater();
     1772        d->lircThread = NULL;
     1773    }
     1774#endif
     1775}
     1776
    17651777/* vim: set expandtab tabstop=4 shiftwidth=4: */
  • libs/libmythui/lirc.cpp

     
     1// System headers
     2#include <lirc/lirc_client.h>
     3
     4// C headers
     5#include <cstdio>
     6#include <cerrno>
     7#include <cstdlib>
     8
     9// C++ headers
     10#include <algorithm>
     11#include <vector>
     12using namespace std;
     13
     14// Qt headers
    115#include <QApplication>
    216#include <QEvent>
    317#include <QKeySequence>
     18#include <QStringList>
    419
    5 #include <cstdio>
    6 #include <cerrno>
    7 #include <sys/wait.h>
    8 #include <sys/types.h>
    9 #include <unistd.h>
    10 #include <stdlib.h>
    11 
     20// MythTV headers
    1221#include "mythverbose.h"
    1322#include "mythdb.h"
    1423#include "mythsystem.h"
    15 
    1624#include "lirc.h"
    1725#include "lircevent.h"
    1826
    19 LircThread::LircThread(QObject *main_window)
     27// POSIX headers
     28namespace POSIX
     29{
     30#include <sys/types.h>
     31#include <sys/socket.h>
     32#include <sys/select.h>
     33#include <sys/un.h>
     34#include <netinet/in.h>
     35#include <arpa/inet.h>
     36#include <netdb.h>
     37#include <unistd.h>
     38#include <fcntl.h>
     39#include <sys/wait.h>
     40};
     41using namespace POSIX;
     42
     43#define LOC      QString("LIRC: ")
     44#define LOC_WARN QString("LIRC, Warning: ")
     45#define LOC_ERR  QString("LIRC, Error: ")
     46
     47class LIRCPriv
     48{
     49  public:
     50    LIRCPriv() : lircConfig(NULL) {}
     51    ~LIRCPriv()
     52    {
     53        if (lircConfig)
     54        {
     55            lirc_freeconfig(lircConfig);
     56            lircConfig = NULL;
     57        }
     58    }
     59
     60    struct lirc_config *lircConfig;
     61};
     62
     63QMutex LIRC::lirclib_lock;
     64
     65/** \class LIRC
     66 *  \brief Interface between mythtv and lircd
     67 *
     68 *   Create connection to the lircd daemon and translate remote keypresses
     69 *   into custom events which are posted to the mainwindow.
     70 */
     71
     72LIRC::LIRC(QObject *main_window,
     73           const QString &lircd_device,
     74           const QString &our_program,
     75           const QString &config_file,
     76           const QString &external_app)
    2077    : QThread(),
    21       m_lircConfig(NULL), m_mainWindow(main_window),
    22       m_bStop(false),     m_fd(-1),
    23       m_externalApp("")
     78      lock(QMutex::Recursive),
     79      m_mainWindow(main_window),
     80      lircdDevice(lircd_device),
     81      program(our_program),
     82      configFile(config_file),
     83      m_externalApp(external_app),
     84      doRun(false),
     85      lircd_socket(-1),
     86      buf_offset(0),
     87      eofCount(0),
     88      retryCount(0),
     89      d(new LIRCPriv())
    2490{
     91    lircdDevice.detach();
     92    program.detach();
     93    configFile.detach();
     94    m_externalApp.detach();
     95    buf.resize(128);
    2596}
     97 
     98LIRC::~LIRC()
     99{
     100    TeardownAll();
     101}
    26102
    27 /**
    28  *  \brief Initialise the class variables, read the lirc config and user
    29  *         settings
    30  */
    31 int LircThread::Init(const QString &config_file, const QString &program,
    32                         bool ignoreExtApp)
     103void LIRC::deleteLater(void)
    33104{
    34     /* Connect the unix socket */
    35     m_fd = lirc_init((char *)qPrintable(program), 1);
    36     if (m_fd == -1)
     105    TeardownAll();
     106    QThread::deleteLater();
     107}
     108
     109void LIRC::TeardownAll(void)
     110{
     111    QMutexLocker locker(&lock);
     112    if (doRun)
    37113    {
    38         VERBOSE(VB_IMPORTANT,
    39                 QString("lirc_init failed for %1, see preceding messages")
    40                 .arg(program));
    41         return -1;
     114        doRun = false;
     115        lock.unlock();
     116        wait();
     117        lock.lock();
    42118    }
     119 
     120    if (lircd_socket >= 0)
     121    {
     122        close(lircd_socket);
     123        lircd_socket = -1;
     124    }
     125 
     126    if (d)
     127    {
     128        delete d;
     129        d = NULL;
     130    }
     131}
     132 
     133QByteArray get_ip(const QString &h)
     134{
     135    QByteArray hba = h.toLatin1();
     136    struct in_addr sin_addr;
     137    if (inet_aton(hba.constData(), &sin_addr))
     138        return hba;
     139 
     140    struct addrinfo hints;
     141    memset(&hints, 0, sizeof(hints));
     142    hints.ai_family   = AF_INET;
     143    hints.ai_socktype = SOCK_STREAM;
     144    hints.ai_protocol = IPPROTO_TCP;
     145 
     146    struct addrinfo *result;
     147    int err = getaddrinfo(hba.constData(), NULL, &hints, &result);
     148    if (err)
     149    {
     150        VERBOSE(VB_IMPORTANT, QString("get_ip: %1").arg(gai_strerror(err)));
     151        return QString("").toLatin1();
     152    }
    43153
    44     /* parse the config file */
    45     if (lirc_readconfig((char *)qPrintable(config_file), &m_lircConfig, NULL))
     154    int addrlen = result->ai_addrlen;
     155    if (!addrlen)
    46156    {
    47         VERBOSE(VB_IMPORTANT,
    48                 QString("Failed to read lirc config %1 for %2")
    49                 .arg(config_file).arg(program));
    50         lirc_deinit();
    51         return -1;
     157        freeaddrinfo(result);
     158        return QString("").toLatin1();
    52159    }
    53160
    54     if (!ignoreExtApp)
    55         m_externalApp = GetMythDB()->GetSetting("LircKeyPressedApp", "");
     161    if (result->ai_addr->sa_family != AF_INET)
     162    {
     163        freeaddrinfo(result);
     164        return QString("").toLatin1();
     165    }
    56166
    57     VERBOSE(VB_GENERAL,
    58             QString("lirc init success using configuration file: %1")
    59             .arg(config_file));
     167    sin_addr = ((struct sockaddr_in*)(result->ai_addr))->sin_addr;
     168    hba = QByteArray(inet_ntoa(sin_addr));
     169    freeaddrinfo(result);
    60170
    61     return 0;
     171    return hba;
    62172}
     173 
     174bool LIRC::Init(void)
     175{
     176    QMutexLocker locker(&lock);
     177    if (lircd_socket >= 0)
     178        return true;
     179 
     180    if (lircdDevice.startsWith('/'))
     181    {
     182        // Connect the unix socket
     183        QByteArray dev = lircdDevice.toLocal8Bit();
     184        if (dev.size() > 107)
     185        {
     186            VERBOSE(VB_IMPORTANT, LOC_ERR + QString("lircdDevice '%1'")
     187                    .arg(lircdDevice) +
     188                    " is too long for the 'unix' socket API");
     189 
     190            return false;
     191        }
     192 
     193        lircd_socket = socket(AF_UNIX, SOCK_STREAM, 0);
     194        if (lircd_socket < 0)
     195        {
     196            VERBOSE(VB_IMPORTANT, LOC_ERR +
     197                    QString("Failed to open Unix socket '%1'")
     198                    .arg(lircdDevice) + ENO);
     199 
     200            return false;
     201        }
     202 
     203        struct sockaddr_un addr;
     204        memset(&addr, 0, sizeof(sockaddr_un));
     205        addr.sun_family = AF_UNIX;
     206        strncpy(addr.sun_path, dev.constData(),107);
    63207
    64 LircThread::~LircThread()
    65 {
    66     lirc_deinit();
    67     if (m_lircConfig)
    68         lirc_freeconfig(m_lircConfig);
     208        int ret = POSIX::connect(
     209            lircd_socket, (struct sockaddr*) &addr, sizeof(addr));
     210
     211        if (ret < 0)
     212        {
     213            VERBOSE(VB_IMPORTANT, LOC_ERR +
     214                    QString("Failed to connect to Unix socket '%1'")
     215                    .arg(lircdDevice) + ENO);
     216
     217            close(lircd_socket);
     218            lircd_socket = -1;
     219            return false;
     220        }
     221    }
     222    else
     223    {
     224        lircd_socket = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
     225        if (lircd_socket < 0)
     226        {
     227            VERBOSE(VB_IMPORTANT, LOC_ERR +
     228                    QString("Failed to open TCP socket '%1'")
     229                    .arg(lircdDevice) + ENO);
     230 
     231            return false;
     232        }
     233
     234        QString dev  = lircdDevice;
     235        uint    port = 8765;
     236        QStringList tmp = lircdDevice.split(':');
     237        if (2 == tmp.size())
     238        {
     239            dev  = tmp[0];
     240            port = (tmp[1].toUInt()) ? tmp[1].toUInt() : port;
     241        }
     242        QByteArray device = get_ip(dev);
     243        struct sockaddr_in addr;
     244        memset(&addr, 0, sizeof(sockaddr_in));
     245        addr.sin_family = AF_INET;
     246        addr.sin_port   = htons(port);
     247 
     248        if (!inet_aton(device.constData(), &addr.sin_addr))
     249        {
     250            VERBOSE(VB_IMPORTANT, LOC_ERR +
     251                    QString("Failed to parse IP address '%1'").arg(dev));
     252
     253            close(lircd_socket);
     254            lircd_socket = -1;
     255            return false;
     256        }
     257
     258        int ret = POSIX::connect(
     259            lircd_socket, (struct sockaddr*) &addr, sizeof(addr));
     260        if (ret < 0)
     261        {
     262            VERBOSE(VB_IMPORTANT, LOC_ERR +
     263                    QString("Failed to connect TCP socket '%1'")
     264                    .arg(lircdDevice) + ENO);
     265
     266            close(lircd_socket);
     267            lircd_socket = -1;
     268            return false;
     269        }
     270
     271        // On Linux, select() can indicate data when there isn't
     272        // any due to TCP checksum in-particular; to avoid getting
     273        // stuck on a read() call add the O_NONBLOCK flag.
     274        int flags = fcntl(lircd_socket, F_GETFD);
     275        if (flags >= 0)
     276        {
     277            ret = fcntl(lircd_socket, F_SETFD, flags | O_NONBLOCK);
     278            if (ret < 0)
     279            {
     280                VERBOSE(VB_IMPORTANT, LOC_WARN +
     281                        QString("Failed set flags for socket '%1'")
     282                        .arg(lircdDevice) + ENO);
     283            }
     284        }
     285 
     286        // Attempt to inline out-of-band messages and keep the connection open..
     287        int i = 1;
     288        setsockopt(lircd_socket, SOL_SOCKET, SO_OOBINLINE, &i, sizeof(i));
     289        i = 1;
     290        setsockopt(lircd_socket, SOL_SOCKET, SO_KEEPALIVE, &i, sizeof(i));
     291    }
     292 
     293    // parse the config file
     294    if (!d->lircConfig)
     295    {
     296        QMutexLocker static_lock(&lirclib_lock);
     297        QByteArray cfg = configFile.toLocal8Bit();
     298        if (lirc_readconfig(
     299                const_cast<char*>(cfg.constData()), &d->lircConfig, NULL))
     300        {
     301            VERBOSE(VB_IMPORTANT, LOC_ERR +
     302                    QString("Failed to read config file '%1'").arg(configFile));
     303
     304            close(lircd_socket);
     305            lircd_socket = -1;
     306            return false;
     307        }
     308
     309        // Get rid of the stuff we don't care about..
     310        vector<struct lirc_config_entry*> del;
     311        struct lirc_config_entry *it = d->lircConfig->first;
     312        while (it->next)
     313        {
     314            if (program == QString(it->next->prog))
     315            {
     316                it = it->next;
     317            }
     318            else
     319            {
     320                del.push_back(it->next);
     321                it->next = it->next->next;
     322            }
     323        }
     324        if (program != QString(d->lircConfig->first->prog))
     325        {
     326            del.push_back(d->lircConfig->first);
     327            d->lircConfig->first = d->lircConfig->first->next;
     328        }
     329        d->lircConfig->next = d->lircConfig->first;
     330 
     331        for (uint i = 0; i < del.size(); i++)
     332        {
     333            struct lirc_config_entry *c = del[i];
     334            if (c->prog)
     335                free(c->prog);
     336            if (c->change_mode)
     337                free(c->change_mode);
     338            if (c->mode)
     339                free(c->mode);
     340 
     341            struct lirc_code *code = c->code;
     342            while (code)
     343            {
     344                if (code->remote && code->remote!=LIRC_ALL)
     345                    free(code->remote);
     346                if (code->button && code->button!=LIRC_ALL)
     347                    free(code->button);
     348                struct lirc_code *code_temp = code->next;
     349                free(code);
     350                code = code_temp;
     351            }
     352 
     353            struct lirc_list *list = c->config;
     354            while (list)
     355            {
     356                if (list->string)
     357                    free(list->string);
     358                struct lirc_list *list_temp = list->next;
     359                free(list);
     360                list = list_temp;
     361            }
     362 
     363            free(c);
     364        }
     365    }
     366 
     367    VERBOSE(VB_GENERAL, LOC +
     368            QString("Successfully initialized '%1' using '%2' config")
     369            .arg(lircdDevice).arg(configFile));
     370   
     371    return true;
    69372}
    70373
    71 /**
    72  *  \brief Main thread loop
    73  */
    74 void LircThread::run(void)
     374void LIRC::start(void)
    75375{
    76     char *code = 0;
    77     char *ir = 0;
    78     int ret;
    79     fd_set readfds;
    80     struct timeval timeout;
     376    QMutexLocker locker(&lock);
    81377
    82     /* Process all events read */
    83     while (!m_bStop)
     378    if (lircd_socket < 0)
    84379    {
    85         FD_ZERO(&readfds);
    86         FD_SET(m_fd, &readfds);
     380        VERBOSE(VB_IMPORTANT, LOC_ERR + "start() called without lircd socket");
     381        return;
     382    }
    87383
    88         // the maximum time select() should wait
    89         timeout.tv_sec = 0;
    90         timeout.tv_usec = 100000;
     384    doRun = true;
     385    QThread::start();
     386}
    91387
    92         ret = select(m_fd + 1, &readfds, NULL, NULL, &timeout);
     388bool LIRC::IsDoRunSet(void) const
     389{
     390    QMutexLocker locker(&lock);
     391    return doRun;
     392}
    93393
    94         if (ret == 0)
    95             continue;
     394void LIRC::Process(const QByteArray &data)
     395{
     396    QMutexLocker static_lock(&lirclib_lock);
    96397
    97         if (ret == -1)
     398    // lirc_code2char will make code point to a static datafer..
     399    char *code = NULL;
     400    int ret = lirc_code2char(
     401        d->lircConfig, const_cast<char*>(data.constData()), &code);
     402
     403    while ((0 == ret) && code)
     404    {
     405        QString text(code);
     406        QKeySequence a(code);
     407
     408        int keycode = 0;
     409
     410        // Send a dummy keycode if we couldn't convert the key sequence.
     411        // This is done so the main code can output a warning for bad
     412        // mappings.
     413        if (!a.count())
    98414        {
    99             perror("LircThread - select");
    100             return;
     415            QApplication::postEvent(
     416                m_mainWindow, new LircKeycodeEvent(text, keycode, true));
    101417        }
    102418
    103         if (ret == 1)
     419        for (unsigned int i = 0; i < a.count(); i++)
    104420        {
    105             ret = lirc_nextcode(&ir);
     421            keycode = a[i];
    106422
    107             if (ret == -1)
     423            QApplication::postEvent(
     424                m_mainWindow, new LircKeycodeEvent(text, keycode, true));
     425            QApplication::postEvent(
     426                m_mainWindow, new LircKeycodeEvent(text, keycode, false));
     427
     428            SpawnApp();
     429        }
     430        ret = lirc_code2char(
     431            d->lircConfig, const_cast<char*>(data.constData()), &code);
     432    }
     433}
     434
     435void LIRC::run(void)
     436{
     437    //VERBOSE(VB_GENERAL, LOC + "run -- start");
     438    /* Process all events read */
     439    while (IsDoRunSet())
     440    {
     441        if (eofCount && retryCount)
     442            usleep(100 * 1000);
     443
     444        if ((eofCount >= 10) || (lircd_socket < 0))
     445        {
     446            QMutexLocker locker(&lock);
     447            eofCount = 0;
     448            if (++retryCount > 1000)
    108449            {
    109                 if (errno != 0)
    110                     VERBOSE(VB_IMPORTANT,
    111                                 QString("LircThread: lirc_nextcode failed"
    112                                         "last error was: %1").arg(errno));
    113                 return;
     450                VERBOSE(VB_IMPORTANT, LOC_ERR +
     451                        "Failed to reconnect, exiting LIRC thread.");
     452                doRun = false;
     453                continue;
    114454            }
     455            VERBOSE(VB_GENERAL, LOC_WARN + "EOF -- reconnecting");
     456 
     457            close(lircd_socket);
     458            lircd_socket = -1;
    115459
    116             if (!ir)
    117                 continue;
     460            if (!Init())
     461                sleep(2); // wait a while before we retry..
    118462
    119             while ((ret = lirc_code2char(m_lircConfig, ir, &code)) == 0 &&
    120                 code != NULL)
    121             {
    122                 QKeySequence a(code);
     463            continue;
     464        }
    123465
    124                 int keycode = 0;
     466        fd_set readfds;
     467        FD_ZERO(&readfds);
     468        FD_SET(lircd_socket, &readfds);
    125469
    126                 // Send a dummy keycode if we couldn't convert the key sequence.
    127                 // This is done so the main code can output a warning for bad
    128                 // mappings.
    129                 if (!a.count())
    130                     QApplication::postEvent(m_mainWindow,
    131                                             new LircKeycodeEvent(code, keycode,
    132                                                                  true));
     470        // the maximum time select() should wait
     471        struct timeval timeout;
     472        timeout.tv_sec = 1; // 1 second
     473        timeout.tv_usec = 100 * 1000; // 100 ms
    133474
    134                 for (unsigned int i = 0; i < a.count(); i++)
    135                 {
    136                     keycode = a[i];
     475        int ret = select(lircd_socket + 1, &readfds, NULL, NULL, &timeout);
    137476
    138                     QApplication::postEvent(m_mainWindow,
    139                                             new LircKeycodeEvent(code, keycode,
    140                                                                  true));
    141                     QApplication::postEvent(m_mainWindow,
    142                                             new LircKeycodeEvent(code, keycode,
    143                                                                  false));
     477        if (ret < 0 && errno != EINTR)
     478        {
     479            VERBOSE(VB_IMPORTANT, LOC_ERR + "select() failed" + ENO);
     480            continue;
     481        }
    144482
    145                     SpawnApp();
    146                 }
    147             }
     483        //  0: Timer expired with no data, repeat select
     484        // -1: Iinterrupted while waiting, repeat select
     485        if (ret <= 0)
     486            continue;
    148487
    149             free(ir);
    150             if (ret == -1)
    151                 break;
     488        QList<QByteArray> codes = GetCodes();
     489        for (uint i = 0; i < (uint) codes.size(); i++)
     490            Process(codes[i]);
     491    }
     492    //VERBOSE(VB_GENERAL, LOC + "run -- end");
     493}
     494 
     495QList<QByteArray> LIRC::GetCodes(void)
     496{
     497    QList<QByteArray> ret;
     498    ssize_t len = -1;
     499
     500    while (true)
     501    {
     502        len = read(lircd_socket,
     503                   buf.data() + buf_offset,
     504                   buf.size() - buf_offset - 1);
     505
     506        if (len >= 0)
     507            break;
     508
     509        if (EINTR == errno)
     510            continue;
     511        else if (EAGAIN == errno)
     512            return ret;
     513        else if (107 == errno)
     514        {
     515            if (!eofCount)
     516                VERBOSE(VB_GENERAL, LOC + "GetCodes -- EOF?");
     517            eofCount++;
     518            return ret;
    152519        }
     520        else
     521        {
     522            VERBOSE(VB_IMPORTANT, LOC + "Error reading socket" + ENO);
     523            return ret;
     524        }
     525
     526        break;
    153527    }
     528
     529    if (0 == len)
     530    {
     531        if (!eofCount)
     532            VERBOSE(VB_GENERAL, LOC + "GetCodes -- eof?");
     533        eofCount++;
     534        return ret;
     535    }
     536
     537    eofCount   = 0;
     538    retryCount = 0;
     539
     540    buf_offset += len;
     541    if ((uint)buf.size() < buf_offset + 128)
     542        buf.reserve(buf.size() * 2);
     543    uint tmpc = std::max(buf.capacity() - 1,128);
     544
     545    buf.resize(buf_offset);
     546    ret = buf.split('\n');
     547    buf.resize(tmpc);
     548    if (buf.endsWith('\n'))
     549    {
     550        buf_offset = 0;
     551        return ret;
     552    }
     553
     554    buf = ret.back();
     555    ret.pop_back();
     556    buf_offset = std::max(buf.size() - 1, 0);
     557    buf.resize(tmpc);
     558
     559    return ret;
    154560}
    155561
    156 /**
    157  *  \brief Spawn a user defined application which might do something like
    158  *         illuminating an led to give positive feedback that a key was received
    159  */
    160 void LircThread::SpawnApp(void)
     562void LIRC::SpawnApp(void)
    161563{
     564    // Spawn app to illuminate led (or what ever the user has picked if
     565    // anything) to give positive feedback that a key was received
    162566    if (m_externalApp.isEmpty())
    163567        return;
    164568
  • libs/libmythui/lircevent.h

     
    4747    void unlock();
    4848
    4949  private:
    50     bool m_eventsLocked;
     50    bool events_locked;
    5151};
    5252
    5353#endif
  • libs/libmythui/mythmainwindow.h

     
    9595    int NormY(const int y);
    9696    int fonTweak;
    9797
     98    void StartLIRC(void);
     99
    98100    /* compatability functions, to go away once everything's mythui */
    99101    void attach(QWidget *child);
    100102    void detach(QWidget *child);
  • libs/libmythui/lircevent.cpp

     
    44#include "mythmainwindow.h"
    55#include "lircevent.h"
    66
    7 LircEventLock::LircEventLock(bool lock_events)
    8              : m_eventsLocked(false)
     7LircEventLock::LircEventLock(bool lock_events) 
     8             : events_locked(false)
    99{
    1010    if (lock_events)
    1111        lock();
     
    1313
    1414LircEventLock::~LircEventLock()
    1515{
    16     if (m_eventsLocked)
     16    if (events_locked)
    1717        unlock();
    1818}
    1919
     
    2222    MythMainWindow *mw = GetMythMainWindow();
    2323    if (mw)
    2424    {
    25         m_eventsLocked = true;
     25        events_locked = true;
    2626        QApplication::postEvent((QObject *)mw,
    27                                 new LircMuteEvent(m_eventsLocked));
     27                                new LircMuteEvent(events_locked));
    2828    }
    2929}
    3030
     
    3333    MythMainWindow *mw = GetMythMainWindow();
    3434    if (mw)
    3535    {
    36         m_eventsLocked = false;
     36        events_locked = false;
    3737        QApplication::postEvent((QObject *)mw,
    38                                 new LircMuteEvent(m_eventsLocked));
     38                                new LircMuteEvent(events_locked));
    3939    }
    4040}
  • programs/mythfrontend/globalsettings.cpp

     
    23132313    return ge;
    23142314}
    23152315
     2316static HostLineEdit *LircDaemonDevice()
     2317{
     2318    HostLineEdit *ge = new HostLineEdit("LircSocket");
     2319    ge->setLabel(QObject::tr("LIRC Daemon Socket"));
     2320    ge->setValue("/dev/lircd");
     2321    QString help = QObject::tr(
     2322        "UNIX socket or IP address[:port] to connect in "
     2323        "order to communicate with the LIRC Daemon.");
     2324    ge->setHelpText(help);
     2325    return ge;
     2326}
     2327
    23162328static HostLineEdit *LircKeyPressedApp()
    23172329{
    23182330    HostLineEdit *ge = new HostLineEdit("LircKeyPressedApp");
    2319     ge->setLabel(QObject::tr("Keypress Application"));
     2331    ge->setLabel(QObject::tr("LIRC Keypress Application"));
    23202332    ge->setValue("");
    23212333    ge->setHelpText(QObject::tr("External application or script to run when "
    23222334                    "a keypress is received by LIRC."));
     
    23262338static HostLineEdit *ScreenShotPath()
    23272339{
    23282340    HostLineEdit *ge = new HostLineEdit("ScreenShotPath");
    2329     ge->setLabel(QObject::tr("ScreenShotPath"));
     2341    ge->setLabel(QObject::tr("Screen Shot Path"));
    23302342    ge->setValue("/tmp/");
    23312343    ge->setHelpText(QObject::tr("Path to screenshot storage location. Should be writable by the frontend"));
    23322344    return ge;
     
    46304642    general->setLabel(QObject::tr("General"));
    46314643    general->addChild(UseArrowAccels());
    46324644    general->addChild(EnableXbox());
    4633     general->addChild(LircKeyPressedApp());
    46344645    general->addChild(ScreenShotPath());
    4635     general->addChild(NetworkControlEnabled());
    4636     general->addChild(NetworkControlPort());
    46374646    addChild(general);
    46384647
    46394648    VerticalConfigurationGroup *media =
     
    46604669    exit->addChild(shutdownSettings);
    46614670    addChild(exit);
    46624671
     4672    VerticalConfigurationGroup *remotecontrol =
     4673        new VerticalConfigurationGroup(false, true, false, false);
     4674    remotecontrol->setLabel(QObject::tr("Remote Control"));
     4675    remotecontrol->addChild(LircDaemonDevice());
     4676    remotecontrol->addChild(LircKeyPressedApp());
     4677    remotecontrol->addChild(NetworkControlEnabled());
     4678    remotecontrol->addChild(NetworkControlPort());
     4679    addChild(remotecontrol);
     4680
    46634681    MythLogSettings *mythlog = new MythLogSettings();
    46644682    addChild(mythlog);
    46654683
  • programs/mythfrontend/main.cpp

     
    806806      gContext->ActivateSettingsCache(true);
    807807}
    808808
     809void signal_USR2_handler(int)
     810{
     811    VERBOSE(VB_GENERAL, "SIG USR2 received, restart LIRC handler");
     812    GetMythMainWindow()->StartLIRC();
     813}
     814
     815
    809816int internal_media_init()
    810817{
    811818    REG_MEDIAPLAYER("Internal", "MythTV's native media player.",
     
    13411348
    13421349    // Setup handler for USR1 signals to reload theme
    13431350    signal(SIGUSR1, &signal_USR1_handler);
     1351    // Setup handler for USR2 signals to restart LIRC
     1352    signal(SIGUSR2, &signal_USR2_handler);
    13441353
    13451354    qApp->exec();
    13461355