summaryrefslogtreecommitdiffstats
path: root/src/util/vncClientThread.cpp
diff options
context:
space:
mode:
authorSebastian2010-05-12 19:42:27 +0200
committerSebastian2010-05-12 19:42:27 +0200
commitce3329047d378a14006ce74ec273ac59e3375303 (patch)
tree782430f270b4c7aca1b35d5b7813518e3797c555 /src/util/vncClientThread.cpp
downloadpvs-ce3329047d378a14006ce74ec273ac59e3375303.tar.gz
pvs-ce3329047d378a14006ce74ec273ac59e3375303.tar.xz
pvs-ce3329047d378a14006ce74ec273ac59e3375303.zip
initial import of latest svn version
Diffstat (limited to 'src/util/vncClientThread.cpp')
-rw-r--r--src/util/vncClientThread.cpp249
1 files changed, 249 insertions, 0 deletions
diff --git a/src/util/vncClientThread.cpp b/src/util/vncClientThread.cpp
new file mode 100644
index 0000000..bb1d457
--- /dev/null
+++ b/src/util/vncClientThread.cpp
@@ -0,0 +1,249 @@
+/*
+ # Copyright (c) 2009, 2010 - OpenSLX Project, Computer Center University of
+ # Freiburg
+ #
+ # This program is free software distributed under the GPL version 2.
+ # See http://openslx.org/COPYING
+ #
+ # If you have any feedback please consult http://openslx.org/feedback and
+ # send your suggestions, praise, or complaints to feedback@openslx.org
+ #
+ # General information about OpenSLX can be found at http://openslx.org/
+ # -----------------------------------------------------------------------------
+ # vncClientThread.cpp
+ # - Connection to remove vnc server
+ # - Emits Qt signal on framebuffer updates
+ # -----------------------------------------------------------------------------
+ */
+
+#include "vncClientThread.h"
+
+VNCClientThread::VNCClientThread(QString host, int port, QString passwd,
+ int quality, int updatefreq) :
+ QThread(), _frameBuffer(0)
+{
+ _host = host;
+ _port = port;
+ _passwd = passwd;
+ _quality = quality;
+ _updatefreq = updatefreq;
+ terminate = false;
+ _client = NULL;
+ _connected = false;
+}
+
+VNCClientThread::~VNCClientThread()
+{
+ if (this->isRunning()) this->wait(2000);
+ if (_frameBuffer) delete[] _frameBuffer;
+ _frameBuffer = NULL;
+ if (_client != NULL)
+ {
+ ::close(_client->sock);
+ _client->frameBuffer = NULL;
+ rfbClientCleanup(_client);
+ _client = NULL;
+ }
+}
+
+////////////////////////////////////////////////////////////////////////////////
+// Public
+
+void VNCClientThread::run()
+{
+ qDebug("[%s] VNC client started.", metaObject()->className());
+ qDebug("[%s] Host: '%s' Port: %i Passwd: '%s' Quality: %i",
+ metaObject()->className(), qPrintable(_host), _port,
+ qPrintable(_passwd), _quality);
+
+ // setup network
+ _client = rfbGetClient(8, 3, 4);
+ _client->MallocFrameBuffer = frameBufferHandler;
+ _client->canHandleNewFBSize = true;
+ _client->serverHost = strdup(_host.toUtf8().constData());
+ _client->desktopName = NULL;
+ _client->serverPort = _port;
+ _client->GetPassword = passwdHandler;
+ _client->GotFrameBufferUpdate = updateImage;
+ _client->frameBuffer = NULL;
+
+ // save this instance in vnc-struct for callbacks
+ rfbClientSetClientData(_client, 0, this);
+
+ // start client
+ if (!rfbInitClient(_client, NULL, NULL))
+ {
+ _client = NULL; // !!! <- if you don't do this you will get a segfault
+ return; // later when you try to clean up _client, as rfbInitClient already did so
+ }
+
+ qDebug("[%s] Connection successful!", metaObject()->className());
+
+ // Main VNC event loop
+ while (!terminate)
+ {
+ _connected = true;
+ const int i = WaitForMessage(_client, 500); // its usec, not msec
+ if (i < 0)
+ break;
+ if (i) if (!HandleRFBServerMessage(_client))
+ break;
+
+ /*
+ //work yourself through event queue and fire every event...
+ while (!_eventQueue.isEmpty()) {
+ SomeEvent* event = _eventQueue.dequeue();
+ event->fire(_client);
+ delete event;
+ }*/
+
+ this->msleep(_updatefreq);
+ }
+
+ // cleanup
+ ::close(_client->sock);
+
+ qDebug("[%s] VNC client stopped.", metaObject()->className());
+ _connected = false;
+}
+
+QImage VNCClientThread::getImage()
+{
+ return _img;
+}
+
+QSize VNCClientThread::getSize()
+{
+ return _clientSize;
+}
+
+int VNCClientThread::getUpdatefreq()
+{
+ if (_updatefreq > 0)
+ return _updatefreq;
+ return 500;
+}
+
+void VNCClientThread::setUpdatefreq(int updatefreq)
+{
+ _updatefreq = updatefreq;
+}
+
+QString VNCClientThread::getDesktopName()
+{
+ if (_client == NULL || _client->desktopName == NULL) return QString();
+ return QString(_client->desktopName);
+}
+
+char* VNCClientThread::passwdHandler(rfbClient *client)
+{
+ VNCClientThread* t = (VNCClientThread*) rfbClientGetClientData(client, 0);
+ return strdup(t->_passwd.toLocal8Bit());
+}
+
+rfbBool VNCClientThread::frameBufferHandler(rfbClient *client)
+{
+ VNCClientThread *t = (VNCClientThread*) rfbClientGetClientData(client, 0);
+ const int width = client->width, height = client->height, depth =
+ client->format.bitsPerPixel;
+ const int size = width * height * (depth / 8);
+ qDebug("[%s] Remote desktop: %ix%ix%i", t->metaObject()->className(),
+ width, height, depth);
+
+ if (t->_frameBuffer)
+ delete[] t->_frameBuffer;
+
+ t->_frameBuffer = new uint8_t[size];
+ client->frameBuffer = t->_frameBuffer;
+ memset(client->frameBuffer, '\0', size);
+ client->format.bitsPerPixel = 32;
+ client->format.redShift = 16;
+ client->format.greenShift = 8;
+ client->format.blueShift = 0;
+ client->format.redMax = 0xff;
+ client->format.greenMax = 0xff;
+ client->format.blueMax = 0xff;
+
+ const int quality = t->_quality;
+ switch (quality)
+ {
+ case VNCClientThread::HIGH:
+ client->appData.useBGR233 = 0;
+ client->appData.encodingsString = "copyrect hextile raw";
+ client->appData.compressLevel = 0;
+ client->appData.qualityLevel = 9;
+ client->appData.scaleSetting = 10; // FIXME: Doesn't work
+ break;
+ case VNCClientThread::MEDIUM:
+ client->appData.useBGR233 = 0;
+ client->appData.encodingsString
+ = "tight zrle ultra copyrect hextile zlib corre rre raw";
+ client->appData.compressLevel = 5;
+ client->appData.qualityLevel = 7;
+ client->appData.scaleSetting = 10;
+ break;
+ case VNCClientThread::LOW:
+ default:
+ client->appData.useBGR233 = 1;
+ client->appData.encodingsString
+ = "tight zrle ultra copyrect hextile zlib corre rre raw";
+ client->appData.compressLevel = 9;
+ client->appData.qualityLevel = 1;
+ client->appData.scaleSetting = 10;
+ break;
+ }
+ SetFormatAndEncodings(client);
+
+ t->_clientSize = QSize(width, height);
+
+ // If something stops working with VNC images/updates, move these two
+ // commands back tp updateImage
+ const QImage img = QImage(client->frameBuffer, client->width,
+ client->height, QImage::Format_RGB32);
+ t->_img = img;
+ // <>
+
+ return true;
+}
+
+void VNCClientThread::updateImage(rfbClient* client, int x, int y, int w, int h)
+{
+ VNCClientThread* t = (VNCClientThread*) rfbClientGetClientData(client, 0);
+ emit t->imageUpdated(x, y, w, h);
+}
+
+/* rfbClient* VNCClientThread::getRfbClient(){
+ return _client;
+}*/
+
+SomeEvent::~SomeEvent()
+{
+}
+
+void PointerEvent::fire(rfbClient* cl)
+{
+ SendPointerEvent(cl, _x, _y, _buttonMask);
+}
+
+void KeyEvent::fire(rfbClient* cl)
+{
+ SendKeyEvent(cl, _key, _pressed);
+}
+
+void VNCClientThread::mouseEvent(int x, int y, int buttonMask)
+{
+ //QMutexLocker lock(&mutex);
+ if (terminate)
+ return;
+
+ _eventQueue.enqueue(new PointerEvent(x, y, buttonMask));
+}
+
+void VNCClientThread::keyEvent(int key, bool pressed)
+{
+ //QMutexLocker lock(&mutex);
+ if (terminate)
+ return;
+
+ _eventQueue.enqueue(new KeyEvent(key, pressed));
+}