16 #include <QCoreApplication>
18 #include <QKeySequence>
19 #include <QStringList>
27 #include <sys/types.h>
28 #include <sys/socket.h>
29 #include <sys/select.h>
31 #include <netinet/in.h>
32 #include <arpa/inet.h>
39 #define LOC QString("LIRC: ")
44 LIRCPriv() : lircState(NULL), lircConfig(NULL) {}
73 const QString &lircd_device,
74 const QString &our_program,
75 const QString &config_file)
77 lock(QMutex::Recursive),
78 m_mainWindow(main_window),
79 lircdDevice(lircd_device),
81 configFile(config_file),
107 QMutexLocker locker(&
lock);
123 static QByteArray
get_ip(
const QString &h)
125 QByteArray hba = h.toLatin1();
126 struct in_addr sin_addr;
127 if (inet_aton(hba.constData(), &sin_addr))
130 struct addrinfo hints;
131 memset(&hints, 0,
sizeof(hints));
132 hints.ai_family = AF_INET;
133 hints.ai_socktype = SOCK_STREAM;
134 hints.ai_protocol = IPPROTO_TCP;
136 struct addrinfo *result;
137 int err = getaddrinfo(hba.constData(), NULL, &hints, &result);
140 LOG(VB_GENERAL, LOG_DEBUG,
141 QString(
"get_ip: %1").arg(gai_strerror(err)));
142 return QString(
"").toLatin1();
145 int addrlen = result->ai_addrlen;
148 freeaddrinfo(result);
149 return QString(
"").toLatin1();
152 if (result->ai_addr->sa_family != AF_INET)
154 freeaddrinfo(result);
155 return QString(
"").toLatin1();
158 sin_addr = ((
struct sockaddr_in*)(result->ai_addr))->sin_addr;
159 hba = QByteArray(inet_ntoa(sin_addr));
160 freeaddrinfo(result);
167 QMutexLocker locker(&
lock);
171 uint64_t vtype = (0 ==
retryCount) ? VB_GENERAL : VB_FILE;
173 int lircd_socket = -1;
178 if (dev.size() > 107)
180 LOG(vtype, LOG_ERR,
LOC +
182 " is too long for the 'unix' socket API");
187 lircd_socket = socket(AF_UNIX, SOCK_STREAM, 0);
188 if (lircd_socket < 0)
190 LOG(vtype, LOG_ERR,
LOC + QString(
"Failed to open Unix socket '%1'")
196 struct sockaddr_un addr;
197 memset(&addr, 0,
sizeof(sockaddr_un));
198 addr.sun_family = AF_UNIX;
199 strncpy(addr.sun_path, dev.constData(),107);
201 int ret = ::connect(lircd_socket, (
struct sockaddr*) &addr,
206 LOG(vtype, LOG_ERR,
LOC +
207 QString(
"Failed to connect to Unix socket '%1'")
216 lircd_socket = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
217 if (lircd_socket < 0)
219 LOG(vtype, LOG_ERR,
LOC + QString(
"Failed to open TCP socket '%1'")
231 port = (tmp[1].toUInt()) ? tmp[1].toUInt() : port;
233 QByteArray device =
get_ip(dev);
234 struct sockaddr_in addr;
235 memset(&addr, 0,
sizeof(sockaddr_in));
236 addr.sin_family = AF_INET;
237 addr.sin_port = htons(port);
239 if (!inet_aton(device.constData(), &addr.sin_addr))
241 LOG(vtype, LOG_ERR,
LOC + QString(
"Failed to parse IP address '%1'")
248 int ret = ::connect(lircd_socket, (
struct sockaddr*) &addr,
252 LOG(vtype, LOG_ERR,
LOC +
253 QString(
"Failed to connect TCP socket '%1'")
263 int flags = fcntl(lircd_socket, F_GETFD);
266 ret = fcntl(lircd_socket, F_SETFD, flags | O_NONBLOCK);
269 LOG(VB_GENERAL, LOG_WARNING,
LOC +
270 QString(
"Failed set flags for socket '%1'")
277 setsockopt(lircd_socket, SOL_SOCKET, SO_OOBINLINE, &i,
sizeof(i));
279 setsockopt(lircd_socket, SOL_SOCKET, SO_KEEPALIVE, &i,
sizeof(i));
297 LOG(vtype, LOG_ERR,
LOC +
298 QString(
"Failed to read config file '%1'").arg(
configFile));
306 LOG(VB_GENERAL, LOG_INFO,
LOC +
307 QString(
"Successfully initialized '%1' using '%2' config")
315 QMutexLocker locker(&
lock);
319 LOG(VB_GENERAL, LOG_ERR,
"start() called without lircd socket");
329 QMutexLocker locker(&
lock);
342 while ((0 == ret) && code)
344 QString lirctext(code);
345 QString qtcode = code;
346 qtcode.replace(
"ctrl-",
"ctrl+", Qt::CaseInsensitive);
347 qtcode.replace(
"alt-",
"alt+", Qt::CaseInsensitive);
348 qtcode.replace(
"shift-",
"shift+", Qt::CaseInsensitive);
349 qtcode.replace(
"meta-",
"meta+", Qt::CaseInsensitive);
350 QKeySequence a(qtcode);
357 QCoreApplication::postEvent(
360 (Qt::KeyboardModifiers)
362 QString(), lirctext));
365 vector<LircKeycodeEvent*> keyReleases;
366 for (
unsigned int i = 0; i < a.count(); i++)
369 Qt::KeyboardModifiers mod = Qt::NoModifier;
370 mod |= (Qt::SHIFT & keycode) ? Qt::ShiftModifier : Qt::NoModifier;
371 mod |= (Qt::META & keycode) ? Qt::MetaModifier : Qt::NoModifier;
372 mod |= (Qt::CTRL & keycode) ? Qt::ControlModifier: Qt::NoModifier;
373 mod |= (Qt::ALT & keycode) ? Qt::AltModifier : Qt::NoModifier;
375 keycode &= ~Qt::MODIFIER_MASK;
379 text = QString(QChar(keycode));
381 QCoreApplication::postEvent(
383 QEvent::KeyPress, keycode, mod, text, lirctext));
385 keyReleases.push_back(
387 QEvent::KeyRelease, keycode, mod, text, lirctext));
390 for (
int i = (
int)keyReleases.size() - 1; i>=0; i--)
391 QCoreApplication::postEvent(
m_mainWindow, keyReleases[i]);
402 LOG(VB_GENERAL, LOG_DEBUG,
LOC +
"run -- start");
412 QMutexLocker locker(&
lock);
416 LOG(VB_GENERAL, LOG_ERR,
LOC +
417 "Failed to reconnect, exiting LIRC thread.");
421 LOG(VB_FILE, LOG_WARNING,
LOC +
"EOF -- reconnecting");
439 struct timeval timeout;
441 timeout.tv_usec = 100 * 1000;
446 if (ret < 0 &&
errno != EINTR)
448 LOG(VB_GENERAL, LOG_ERR,
LOC +
"select() failed" + ENO);
457 QList<QByteArray> codes =
GetCodes();
458 for (
uint i = 0; i < (
uint) codes.size(); i++)
462 LOG(VB_GENERAL, LOG_DEBUG,
LOC +
"run -- end");
469 QList<QByteArray> ret;
472 uint buf_size =
buf.size() + 128;
473 buf.resize(buf_size);
491 LOG(VB_GENERAL, LOG_NOTICE,
LOC +
"GetCodes -- EOF?");
496 LOG(VB_GENERAL, LOG_ERR,
LOC +
"Could not read socket" + ENO);
504 LOG(VB_GENERAL, LOG_NOTICE,
LOC +
"GetCodes -- eof?");
514 ret =
buf.split(
'\n');
515 if (
buf.endsWith(
'\n'))
521 buf = ret.takeLast();