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
--- 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 \