summaryrefslogtreecommitdiff
path: root/src/common/qt-glue.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/common/qt-glue.cpp')
-rw-r--r--src/common/qt-glue.cpp413
1 files changed, 413 insertions, 0 deletions
diff --git a/src/common/qt-glue.cpp b/src/common/qt-glue.cpp
new file mode 100644
index 0000000..8fbf636
--- /dev/null
+++ b/src/common/qt-glue.cpp
@@ -0,0 +1,413 @@
+/*
+ * Copyright (c) 2012, Intel Corporation
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *
+ * * Redistributions of source code must retain the above copyright notice,
+ * this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * * Neither the name of Intel Corporation nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "qt-glue-priv.h"
+#include "qt-glue-priv.moc.h"
+#include <sys/types.h>
+#include <sys/socket.h>
+
+#include <QObject>
+#include <QSocketNotifier>
+#include <QTimer>
+
+#include <murphy/config.h>
+#include <murphy/common/mm.h>
+#include <murphy/common/debug.h>
+#include <murphy/common/mainloop.h>
+#include <murphy/common/qt-glue.h>
+
+static mrp_mainloop_t *qt_ml;
+
+
+/*
+ * QtGlue
+ */
+
+QtGlue::QtGlue(QObject *parent)
+ : QObject(parent)
+{
+}
+
+
+/*
+ * QtIO
+ */
+
+QtIO::QtIO (int fd, EventMask events, QObject *parent)
+ : QObject (parent)
+ , m_events(events), m_fdIn(0), m_fdOut(0), m_fdExcep(0)
+ , cb(0), user_data(0)
+{
+ if (events & Read) {
+ m_fdIn = new QSocketNotifier(fd, QSocketNotifier::Read, this);
+
+ m_fdIn->setEnabled (true);
+
+ QObject::connect (m_fdIn, SIGNAL(activated(int)), this,
+ SLOT(readyRead(int)));
+ }
+ if (events & Write) {
+ m_fdOut = new QSocketNotifier(fd, QSocketNotifier::Write, this);
+
+ m_fdOut->setEnabled (true);
+
+ QObject::connect (m_fdOut, SIGNAL(activated(int)), this,
+ SLOT(readyWrite(int)));
+ }
+ if (events & Exception) {
+ m_fdExcep = new QSocketNotifier(fd, QSocketNotifier::Exception, this);
+
+ m_fdExcep->setEnabled (true);
+
+ QObject::connect (m_fdExcep, SIGNAL(activated(int)), this,
+ SLOT(exception(int)));
+ }
+}
+
+
+QtIO::~QtIO() {
+ if (m_fdIn)
+ delete m_fdIn;
+ if (m_fdOut)
+ delete m_fdOut;
+ if (m_fdExcep)
+ delete m_fdExcep;
+}
+
+
+void QtIO::readyRead (int fd)
+{
+ if(cb)
+ cb(parent(), this, fd, MRP_IO_EVENT_IN, user_data);
+}
+
+
+void QtIO::readyWrite (int fd)
+{
+ if (cb)
+ cb(parent(), this, fd, MRP_IO_EVENT_OUT, user_data);
+}
+
+
+static bool check_hup(int fd)
+{
+ char buf[1];
+ ssize_t n;
+
+ n = recv(fd, buf, sizeof(buf), MSG_DONTWAIT | MSG_PEEK);
+
+ if (n == 0)
+ return true;
+ else
+ return false;
+}
+
+
+void QtIO::exception (int fd)
+{
+ mrp_io_event_t events;
+
+ if (!check_hup(fd))
+ events = MRP_IO_EVENT_HUP;
+ else
+ events = (mrp_io_event_t)(MRP_IO_EVENT_ERR | MRP_IO_EVENT_HUP);
+
+ if (cb)
+ cb(parent(), this, fd, events, user_data);
+}
+
+
+/*
+ * QtTimer
+ */
+
+QtTimer::QtTimer (int msecs, QObject *parent)
+ : QObject (parent)
+ , m_timer(new QTimer(this)), m_interval(msecs >= 0 ? msecs : 0)
+ , cb(0), user_data(0)
+{
+ m_timer->setInterval (m_interval);
+ m_timer->setSingleShot (false);
+
+ QObject::connect (m_timer, SIGNAL(timeout()), this, SLOT(timedout()));
+}
+
+
+QtTimer::~QtTimer ()
+{
+ delete m_timer;
+}
+
+
+void QtTimer::setInterval (int msecs)
+{
+ m_interval = (msecs >= 0 ? msecs : 0);
+
+ m_timer->setInterval (m_interval);
+
+ if (m_timer->isActive()) {
+ m_timer->stop ();
+ m_timer->start ();
+ }
+}
+
+
+void QtTimer::start ()
+{
+ if (!m_timer->isActive())
+ m_timer->start ();
+}
+
+
+void QtTimer::stop ()
+{
+ if (m_timer->isActive())
+ m_timer->stop();
+}
+
+
+void QtTimer::disable()
+{
+ if (!m_disabled) {
+ delete m_timer;
+
+ m_timer = 0;
+ m_disabled = true;
+ }
+}
+
+
+void QtTimer::enable()
+{
+ if (m_disabled) {
+ m_timer = new QTimer(this);
+
+ setInterval (m_interval);
+
+ connect (m_timer, SIGNAL(timeout()), this, SLOT(timedout()));
+
+ m_timer->start ();
+ m_disabled = false;
+ }
+}
+
+
+void QtTimer::timedout()
+{
+ mrp_debug("timer %p latched", this);
+
+ if (cb)
+ cb(parent(), this, user_data);
+}
+
+
+static void *add_io(void *glue_data, int fd, mrp_io_event_t events,
+ void (*cb)(void *glue_data, void *id, int fd,
+ mrp_io_event_t events, void *user_data),
+ void *user_data)
+{
+ QtGlue *qt_glue = (QtGlue *)glue_data;
+ QtIO *io;
+ QtIO::EventMask mask;
+
+ mask = 0;
+ if (events & MRP_IO_EVENT_IN)
+ mask |= QtIO::Read;
+ if (events & MRP_IO_EVENT_OUT)
+ mask |= QtIO::Write;
+ if (events & (MRP_IO_EVENT_ERR | MRP_IO_EVENT_HUP))
+ mask |= QtIO::Exception;
+
+ io = new QtIO (fd, mask, qt_glue);
+
+ if (io) {
+ mrp_debug("added I/O watch %p (events 0x%x) on fd %d", io, events, fd);
+
+ io->cb = cb;
+ io->user_data = user_data;
+ }
+
+ return io;
+}
+
+
+static void del_io(void *glue_data, void *id)
+{
+ QtIO *io = (QtIO *)id;
+
+ MRP_UNUSED(glue_data);
+
+ mrp_debug("deleting I/O watch %p", io);
+
+ delete io;
+}
+
+
+static void *add_timer(void *glue_data, unsigned int msecs,
+ void (*cb)(void *glue_data, void *id, void *user_data),
+ void *user_data)
+{
+ QtGlue *qt_glue = (QtGlue *)glue_data;
+ QtTimer *t = new QtTimer(msecs, qt_glue);
+
+ mrp_debug("created timer %p with %d msecs interval", t, msecs);
+
+ if (t) {
+ t->cb = cb;
+ t->user_data = user_data;
+ t->start();
+ }
+
+ return t;
+}
+
+
+static void del_timer(void *glue_data, void *id)
+{
+ QtTimer *t = (QtTimer *)id;
+
+ MRP_UNUSED(glue_data);
+
+ mrp_debug("deleting timer %p", t);
+
+ delete t;
+}
+
+
+static void mod_timer(void *glue_data, void *id, unsigned int msecs)
+{
+ QtTimer *t = (QtTimer *)id;
+
+ MRP_UNUSED(glue_data);
+
+ mrp_debug("setting timer %p to %d msecs interval", t, msecs);
+
+ if (t != NULL)
+ t->setInterval(msecs);
+}
+
+
+static void *add_defer(void *glue_data,
+ void (*cb)(void *glue_data, void *id, void *user_data),
+ void *user_data)
+{
+ QtGlue *qt_glue = (QtGlue *)glue_data;
+ QtTimer *t = new QtTimer(0, qt_glue);
+
+ mrp_debug("created timer %p", t);
+
+ if (t) {
+ t->cb = cb;
+ t->user_data = user_data;
+ t->start();
+ }
+
+ return t;
+}
+
+
+static void del_defer(void *glue_data, void *id)
+{
+ QtTimer *t = (QtTimer *)id;
+
+ MRP_UNUSED(glue_data);
+
+ mrp_debug("deleting timer %p", t);
+
+ delete t;
+}
+
+
+static void mod_defer(void *glue_data, void *id, int enabled)
+{
+ QtTimer *t = (QtTimer *)id;
+
+ MRP_UNUSED(glue_data);
+
+ mrp_debug("%s timer %p", enabled ? "enabling" : "disabling", t);
+
+ if (enabled)
+ t->enable();
+ else
+ t->disable();
+}
+
+
+static void unregister(void *glue_data)
+{
+ QtGlue *qt_glue = (QtGlue *)glue_data;
+
+ mrp_debug("unregistering mainloop");
+
+ delete qt_glue;
+}
+
+
+int mrp_mainloop_register_with_qt(mrp_mainloop_t *ml)
+{
+ static mrp_superloop_ops_t qt_ops;
+ QtGlue *qt_glue;
+
+ qt_ops.add_io = add_io;
+ qt_ops.del_io = del_io;
+ qt_ops.add_timer = add_timer;
+ qt_ops.del_timer = del_timer;
+ qt_ops.mod_timer = mod_timer;
+ qt_ops.add_defer = add_defer;
+ qt_ops.del_defer = del_defer;
+ qt_ops.mod_defer = mod_defer;
+ qt_ops.unregister = unregister;
+
+ qt_glue = new QtGlue ();
+
+ return mrp_set_superloop(ml, &qt_ops, (void *)qt_glue);
+}
+
+
+int mrp_mainloop_unregister_from_qt(mrp_mainloop_t *ml)
+{
+ return mrp_mainloop_unregister(ml);
+}
+
+
+mrp_mainloop_t *mrp_mainloop_qt_get(void)
+{
+ if (qt_ml == NULL) {
+ qt_ml = mrp_mainloop_create();
+
+ if (qt_ml != NULL) {
+ if (!mrp_mainloop_register_with_qt(qt_ml)) {
+ mrp_mainloop_destroy(qt_ml);
+ qt_ml = NULL;
+ }
+ }
+ }
+
+ return qt_ml;
+}