flib: qmlfrontend
authorunc0rr
Mon, 22 Sep 2014 02:10:39 +0400
branchqmlfrontend
changeset 10420 02c573d19224
parent 10418 091d2c0216c3
child 10422 4cf23d4c7624
flib: - Ability to pass raw data via IPC qmlfrontend: - Pass message received by callback through event loop to handle it in main thread - Get preview image from engine on button click and render it in Image object
hedgewars/uFLIPC.pas
hedgewars/uFLTypes.pas
hedgewars/uIO.pas
qmlFrontend/flib.h
qmlFrontend/hwengine.cpp
qmlFrontend/hwengine.h
qmlFrontend/main.cpp
qmlFrontend/previewimageprovider.cpp
qmlFrontend/previewimageprovider.h
qmlFrontend/qml/qmlFrontend/main.qml
qmlFrontend/qmlFrontend.pro
--- a/hedgewars/uFLIPC.pas	Sun Sep 21 00:37:50 2014 +0400
+++ b/hedgewars/uFLIPC.pas	Mon Sep 22 02:10:39 2014 +0400
@@ -9,11 +9,12 @@
 procedure initIPC;
 procedure freeIPC;
 
-procedure ipcToEngine(len: byte; msg: PChar); cdecl; export;
-function  ipcReadFromEngine: shortstring;
-function  ipcCheckFromEngine: boolean;
+procedure ipcToEngine(p: PChar; len: byte); cdecl; export;
+//function  ipcReadFromEngine: shortstring;
+//function  ipcCheckFromEngine: boolean;
 
 procedure ipcToFrontend(s: shortstring);
+procedure ipcToFrontendRaw(p: pointer; len: Longword);
 function ipcReadFromFrontend: shortstring;
 function ipcCheckFromFrontend: boolean;
 
@@ -25,32 +26,37 @@
     callbackFunction: TIPCCallback;
     callbackListenerThread: PSDL_Thread;
 
-procedure ipcSend(var s: shortstring; var msg: TIPCMessage; mut: PSDL_mutex; cond: PSDL_cond);
+procedure ipcSend(var s: TIPCMessage; var msg: TIPCMessage; mut: PSDL_mutex; cond: PSDL_cond);
 begin
     SDL_LockMutex(mut);
 
     while (msg.str[0] > #0) or (msg.buf <> nil) do
         SDL_CondWait(cond, mut);
 
-    msg.str:= s;
+    msg:= s;
     SDL_CondSignal(cond);
     SDL_UnlockMutex(mut);
 end;
 
-function ipcRead(var msg: TIPCMessage; mut: PSDL_mutex; cond: PSDL_cond): shortstring;
+function ipcRead(var msg: TIPCMessage; mut: PSDL_mutex; cond: PSDL_cond): TIPCMessage;
+var tmp: pointer;
 begin
     SDL_LockMutex(mut);
     while (msg.str[0] = #0) and (msg.buf = nil) do
         SDL_CondWait(cond, mut);
 
-    ipcRead:= msg.str;
+    if msg.buf <> nil then
+    begin
+        tmp:= msg.buf;
+        msg.buf:= GetMem(msg.len);
+        Move(tmp^, msg.buf^, msg.len);
+        FreeMem(tmp, msg.len)
+    end;
+
+    ipcRead:= msg;
 
     msg.str[0]:= #0;
-    if msg.buf <> nil then
-    begin
-        FreeMem(msg.buf, msg.len);
-        msg.buf:= nil
-    end;
+    msg.buf:= nil;
 
     SDL_CondSignal(cond);
     SDL_UnlockMutex(mut)
@@ -63,28 +69,42 @@
     SDL_UnlockMutex(mut)
 end;
 
-procedure ipcToEngine(len: byte; msg: PChar); cdecl; export;
-var s: shortstring;
+procedure ipcToEngine(p: PChar; len: byte); cdecl; export;
+var msg: TIPCMessage;
 begin
     writeln(stderr, len);
-    Move(msg^, s[1], len);
-    s[0]:= char(len);
-    ipcSend(s, msgEngine, mutEngine, condEngine)
+    Move(p^, msg.str[1], len);
+    msg.str[0]:= char(len);
+    msg.buf:= nil;
+    ipcSend(msg, msgEngine, mutEngine, condEngine)
 end;
 
 procedure ipcToFrontend(s: shortstring);
+var msg: TIPCMessage;
 begin
-    ipcSend(s, msgFrontend, mutFrontend, condFrontend)
+    msg.str:= s;
+    msg.buf:= nil;
+    ipcSend(msg, msgFrontend, mutFrontend, condFrontend)
 end;
 
-function ipcReadFromEngine: shortstring;
+procedure ipcToFrontendRaw(p: pointer; len: Longword);
+var msg: TIPCMessage;
+begin
+    msg.str[0]:= #0;
+    msg.len:= len;
+    msg.buf:= GetMem(len);
+    Move(p^, msg.buf^, len);
+    ipcSend(msg, msgFrontend, mutFrontend, condFrontend)
+end;
+
+function ipcReadFromEngine: TIPCMessage;
 begin
     ipcReadFromEngine:= ipcRead(msgFrontend, mutFrontend, condFrontend)
 end;
 
 function ipcReadFromFrontend: shortstring;
 begin
-    ipcReadFromFrontend:= ipcRead(msgEngine, mutEngine, condEngine)
+    ipcReadFromFrontend:= ipcRead(msgEngine, mutEngine, condEngine).str
 end;
 
 function ipcCheckFromEngine: boolean;
@@ -98,12 +118,18 @@
 end;
 
 function  listener(p: pointer): Longint; cdecl; export;
-var s: shortstring;
+var msg: TIPCMessage;
 begin
     listener:= 0;
     repeat
-        s:= ipcReadFromEngine();
-        callbackFunction(callbackPointer, byte(s[0]), @s[1])
+        msg:= ipcReadFromEngine();
+        if msg.buf = nil then
+            callbackFunction(callbackPointer, @msg.str[1], byte(msg.str[0]))
+        else
+        begin
+            callbackFunction(callbackPointer, msg.buf, msg.len);
+            FreeMem(msg.buf, msg.len)
+        end
     until false
 end;
 
--- a/hedgewars/uFLTypes.pas	Sun Sep 21 00:37:50 2014 +0400
+++ b/hedgewars/uFLTypes.pas	Mon Sep 22 02:10:39 2014 +0400
@@ -6,7 +6,7 @@
                    len: Longword;
                    buf: Pointer
                end;
-    TIPCCallback = procedure (p: pointer; len: byte; msg: PChar);
+    TIPCCallback = procedure (p: pointer; msg: PChar; len: Longword);
 
 implementation
 
--- a/hedgewars/uIO.pas	Sun Sep 21 00:37:50 2014 +0400
+++ b/hedgewars/uIO.pas	Mon Sep 22 02:10:39 2014 +0400
@@ -242,10 +242,7 @@
 
 procedure SendIPCRaw(p: pointer; len: Longword);
 begin
-{    if IPCSock <> nil then
-    begin
-    SDLNet_TCP_Send(IPCSock, p, len)
-    end}
+    ipcToFrontendRaw(p, len)
 end;
 
 procedure SendIPCXY(cmd: char; X, Y: LongInt);
--- a/qmlFrontend/flib.h	Sun Sep 21 00:37:50 2014 +0400
+++ b/qmlFrontend/flib.h	Mon Sep 22 02:10:39 2014 +0400
@@ -19,8 +19,8 @@
     } string255;
 
 typedef void RunEngine_t(int argc, const char ** argv);
-typedef void registerIPCCallback_t(void * context, void (*)(void * context, uint8_t len, const char * msg));
-typedef void ipcToEngine_t(uint8_t len, const char * msg);
+typedef void registerIPCCallback_t(void * context, void (*)(void * context, const char * msg, uint32_t len));
+typedef void ipcToEngine_t(const char * msg, uint8_t len);
 typedef void flibInit_t();
 
 #ifdef __cplusplus
--- a/qmlFrontend/hwengine.cpp	Sun Sep 21 00:37:50 2014 +0400
+++ b/qmlFrontend/hwengine.cpp	Mon Sep 22 02:10:39 2014 +0400
@@ -1,8 +1,10 @@
 #include <QLibrary>
 #include <QtQml>
 #include <QDebug>
+#include <QPainter>
 
 #include "hwengine.h"
+#include "previewimageprovider.h"
 
 extern "C" {
     RunEngine_t *RunEngine;
@@ -10,8 +12,10 @@
     ipcToEngine_t *ipcToEngine;
     flibInit_t *flibInit;
 }
-HWEngine::HWEngine(QObject *parent) :
-    QObject(parent)
+
+HWEngine::HWEngine(QQmlEngine *engine, QObject *parent) :
+    QObject(parent),
+    m_engine(engine)
 {
     QLibrary hwlib("./libhwengine.so");
 
@@ -48,15 +52,16 @@
         m_args[i] = m_argsList[i].constData();
 
     RunEngine(m_args.size(), m_args.data());
+    sendIPC("eseed helloworld");
+    sendIPC("e$mapgen 0");
     sendIPC("!");
 }
 
 static QObject *hwengine_singletontype_provider(QQmlEngine *engine, QJSEngine *scriptEngine)
 {
-    Q_UNUSED(engine)
     Q_UNUSED(scriptEngine)
 
-    HWEngine *hwengine = new HWEngine();
+    HWEngine *hwengine = new HWEngine(engine);
     return hwengine;
 }
 
@@ -71,12 +76,41 @@
     quint8 len = b.size() > 255 ? 255 : b.size();
     qDebug() << "sendIPC: len = " << len;
 
-    ipcToEngine(len, b.constData());
+    ipcToEngine(b.constData(), len);
+}
+
+void HWEngine::engineMessageCallback(void *context, const char * msg, quint32 len)
+{
+    HWEngine * obj = (HWEngine *)context;
+    QByteArray b = QByteArray::fromRawData(msg, len);
+
+    qDebug() << "FLIPC in" << b.size() << b;
+
+    QMetaObject::invokeMethod(obj, "engineMessageHandler", Qt::QueuedConnection, Q_ARG(QByteArray, b));
 }
 
-void HWEngine::engineMessageCallback(void *context, quint8 len, const char *msg)
+void HWEngine::engineMessageHandler(const QByteArray &msg)
 {
-    QByteArray b = QByteArray::fromRawData(msg, len);
+    if(msg.size() == 128 * 256)
+    {
+        QVector<QRgb> colorTable;
+        colorTable.resize(256);
+        for(int i = 0; i < 256; ++i)
+            colorTable[i] = qRgba(255, 255, 0, i);
+
+        const quint8 *buf = (const quint8*) msg.constData();
+        QImage im(buf, 256, 128, QImage::Format_Indexed8);
+        im.setColorTable(colorTable);
 
-    qDebug() << "FLIPC in" << b;
+        QPixmap px = QPixmap::fromImage(im, Qt::ColorOnly);
+        //QPixmap pxres(px.size());
+        //QPainter p(&pxres);
+
+        //p.fillRect(pxres.rect(), linearGrad);
+        //p.drawPixmap(0, 0, px);
+
+        PreviewImageProvider * preview = (PreviewImageProvider *)m_engine->imageProvider(QLatin1String("preview"));
+        preview->setPixmap(px);
+        emit previewImageChanged();
+    }
 }
--- a/qmlFrontend/hwengine.h	Sun Sep 21 00:37:50 2014 +0400
+++ b/qmlFrontend/hwengine.h	Mon Sep 22 02:10:39 2014 +0400
@@ -4,29 +4,37 @@
 #include <QObject>
 #include <QByteArray>
 #include <QVector>
+#include <QPixmap>
 
 #include "flib.h"
 
+class QQmlEngine;
+
 class HWEngine : public QObject
 {
     Q_OBJECT
 public:
-    explicit HWEngine(QObject *parent = 0);
+    explicit HWEngine(QQmlEngine * engine, QObject *parent = 0);
     ~HWEngine();
 
     static void exposeToQML();
     Q_INVOKABLE void run();
     
 signals:
+    void previewImageChanged();
     
 public slots:
 
 private:
     QList<QByteArray> m_argsList;
     QVector<const char *> m_args;
+    QQmlEngine * m_engine;
 
-    static void engineMessageCallback(void *context, quint8 len, const char * msg);
+    static void engineMessageCallback(void *context, const char * msg, quint32 len);
     void sendIPC(const QByteArray &b);
+
+private slots:
+    void engineMessageHandler(const QByteArray &msg);
 };
 
 #endif // HWENGINE_H
--- a/qmlFrontend/main.cpp	Sun Sep 21 00:37:50 2014 +0400
+++ b/qmlFrontend/main.cpp	Mon Sep 22 02:10:39 2014 +0400
@@ -1,7 +1,10 @@
 #include <QtGui/QGuiApplication>
+#include <QQmlEngine>
+
 #include "qtquick2applicationviewer/qtquick2applicationviewer.h"
+#include "hwengine.h"
+#include "previewimageprovider.h"
 
-#include "hwengine.h"
 
 int main(int argc, char *argv[])
 {
@@ -10,6 +13,9 @@
     HWEngine::exposeToQML();
 
     QtQuick2ApplicationViewer viewer;
+
+    viewer.engine()->addImageProvider(QLatin1String("preview"), new PreviewImageProvider());
+
     viewer.setMainQmlFile(QStringLiteral("qml/qmlFrontend/main.qml"));
     viewer.showExpanded();
 
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/qmlFrontend/previewimageprovider.cpp	Mon Sep 22 02:10:39 2014 +0400
@@ -0,0 +1,22 @@
+#include "previewimageprovider.h"
+
+PreviewImageProvider::PreviewImageProvider()
+        : QQuickImageProvider(QQuickImageProvider::Pixmap)
+{
+}
+
+QPixmap PreviewImageProvider::requestPixmap(const QString &id, QSize *size, const QSize &requestedSize)
+{
+    Q_UNUSED(id);
+    Q_UNUSED(requestedSize);
+
+    if (size)
+        *size = m_px.size();
+
+    return m_px;
+}
+
+void PreviewImageProvider::setPixmap(const QPixmap & px)
+{
+    m_px = px;
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/qmlFrontend/previewimageprovider.h	Mon Sep 22 02:10:39 2014 +0400
@@ -0,0 +1,21 @@
+#ifndef PREVIEWIMAGEPROVIDER_H
+#define PREVIEWIMAGEPROVIDER_H
+
+#include <QQuickImageProvider>
+#include <QPixmap>
+#include <QSize>
+
+class PreviewImageProvider : public QQuickImageProvider
+{
+public:
+    PreviewImageProvider();
+
+    QPixmap requestPixmap(const QString &id, QSize *size, const QSize &requestedSize);
+
+    void setPixmap(const QPixmap & px);
+
+private:
+    QPixmap m_px;
+};
+
+#endif // PREVIEWIMAGEPROVIDER_H
--- a/qmlFrontend/qml/qmlFrontend/main.qml	Sun Sep 21 00:37:50 2014 +0400
+++ b/qmlFrontend/qml/qmlFrontend/main.qml	Mon Sep 22 02:10:39 2014 +0400
@@ -15,6 +15,11 @@
         onClicked: {
             HWEngine.run()
         }
+
+        Connections {
+            target: HWEngine
+            onPreviewImageChanged: previewImage.source = "image://preview/1"
+        }
     }
 
     HWButton {
@@ -24,4 +29,13 @@
         width: 200
         height: 139
     }
+
+    Image {
+        id: previewImage
+        x: 70
+        y: 250
+        width: 256
+        height: 128
+        cache: false
+    }
 }
--- a/qmlFrontend/qmlFrontend.pro	Sun Sep 21 00:37:50 2014 +0400
+++ b/qmlFrontend/qmlFrontend.pro	Mon Sep 22 02:10:39 2014 +0400
@@ -13,7 +13,8 @@
 
 # The .cpp file which was generated for your project. Feel free to hack it.
 SOURCES += main.cpp \
-    hwengine.cpp
+    hwengine.cpp \
+    previewimageprovider.cpp
 
 # Installation path
 # target.path =
@@ -25,7 +26,8 @@
 HEADERS += \
     qtquick2applicationviewer/qtquick2applicationviewer.h \
     hwengine.h \
-    flib.h
+    flib.h \
+    previewimageprovider.h
 
 OTHER_FILES += \
     qtquick2applicationviewer/qtquick2applicationviewer.pri \