diff options
| author | Sebastian | 2010-05-12 19:42:27 +0200 |
|---|---|---|
| committer | Sebastian | 2010-05-12 19:42:27 +0200 |
| commit | ce3329047d378a14006ce74ec273ac59e3375303 (patch) | |
| tree | 782430f270b4c7aca1b35d5b7813518e3797c555 /src/util/vncClientThread.cpp | |
| download | pvs-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.cpp | 249 |
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)); +} |
