# HG changeset patch # User unc0rr # Date 1411337439 -14400 # Node ID 02c573d1922443993da910204f644c6a99da8c07 # Parent 091d2c0216c3b9727fbef9767c3b0d1c18f30352 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 diff -r 091d2c0216c3 -r 02c573d19224 hedgewars/uFLIPC.pas --- 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; diff -r 091d2c0216c3 -r 02c573d19224 hedgewars/uFLTypes.pas --- 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 diff -r 091d2c0216c3 -r 02c573d19224 hedgewars/uIO.pas --- 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); diff -r 091d2c0216c3 -r 02c573d19224 qmlFrontend/flib.h --- 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 diff -r 091d2c0216c3 -r 02c573d19224 qmlFrontend/hwengine.cpp --- 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 #include #include +#include #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 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(); + } } diff -r 091d2c0216c3 -r 02c573d19224 qmlFrontend/hwengine.h --- 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 #include #include +#include #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 m_argsList; QVector 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 diff -r 091d2c0216c3 -r 02c573d19224 qmlFrontend/main.cpp --- 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 +#include + #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(); diff -r 091d2c0216c3 -r 02c573d19224 qmlFrontend/previewimageprovider.cpp --- /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; +} diff -r 091d2c0216c3 -r 02c573d19224 qmlFrontend/previewimageprovider.h --- /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 +#include +#include + +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 diff -r 091d2c0216c3 -r 02c573d19224 qmlFrontend/qml/qmlFrontend/main.qml --- 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 + } } diff -r 091d2c0216c3 -r 02c573d19224 qmlFrontend/qmlFrontend.pro --- 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 \