Commit 5af11089 authored by Alberto Mardegan's avatar Alberto Mardegan

Add VncClient class

parent 1f074746
......@@ -8,5 +8,8 @@
"TARGET_SYSTEM": "UbuntuTouch"
},
"install_dir": "${BUILD_DIR}/release/install-root",
"install_lib": [
"/usr/lib/${ARCH_TRIPLET}/libvncclient.so.1*"
],
"default": "build install launch"
}
......@@ -23,6 +23,8 @@ Project {
Group {
prefix: "src/"
files: [
"vnc_client.cpp",
"vnc_client.h",
"main.cpp",
"types.cpp",
"types.h",
......@@ -55,6 +57,7 @@ Project {
Depends { name: "Qt.quickcontrols2" }
Depends { name: "Qt.svg" }
Depends { name: "freedesktop" }
Depends { name: "libvncclient" }
freedesktop.name: product.name
......
import LomiriVNC 1.0
import QtQuick 2.7
import QtQuick.Controls 2.2
import QtQuick.Layouts 1.3
......@@ -24,7 +25,7 @@ Page {
onAccepted: activate()
function activate() {
// TODO
vncClient.connectToServer(text);
}
}
......@@ -35,4 +36,9 @@ Page {
onClicked: urlField.activate()
}
}
VncClient {
id: vncClient
onConnectedChanged: console.log("Connected: " + connected)
}
}
......@@ -19,6 +19,8 @@
#include "types.h"
#include "vnc_client.h"
#include <QDebug>
#include <QQmlEngine>
......@@ -26,4 +28,5 @@ using namespace LomiriVNC;
void LomiriVNC::registerTypes()
{
qmlRegisterType<VncClient>("LomiriVNC", 1, 0, "VncClient");
}
/*
* Copyright (C) 2020 Alberto Mardegan <mardy@users.sourceforge.net>
*
* This file is part of LomiriVNC.
*
* LomiriVNC is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* LomiriVNC is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with LomiriVNC. If not, see <http://www.gnu.org/licenses/>.
*/
#include "vnc_client.h"
#include <QByteArrayList>
#include <QDebug>
#include <QImage>
#include <QList>
#include <QQuickItem>
#include <QScopedPointer>
#include <QSocketNotifier>
#include <rfb/rfbclient.h>
using namespace LomiriVNC;
namespace LomiriVNC {
class VncClientPrivate {
Q_DECLARE_PUBLIC(VncClient)
public:
VncClientPrivate(VncClient *q);
~VncClientPrivate();
static void *dataTag();
static void vncLog(const char *format, ...);
static void vncError(const char *format, ...);
static void gotFrameBufferUpdate(rfbClient *cl,
int x, int y, int w, int h);
static rfbBool mallocFrameBuffer(rfbClient* client);
void onUpdate(int x, int y, int w, int h);
void onResize();
bool connectToServer(const QString &host);
void disconnect();
void onSocketActivated();
private:
QScopedPointer<QSocketNotifier> m_notifier;
int m_bytesPerPixel;
QImage m_image;
QList<QQuickItem*> m_viewers;
rfbClient *m_client;
VncClient *q_ptr;
};
} // namespace
VncClientPrivate::VncClientPrivate(VncClient *q):
m_bytesPerPixel(4),
m_client(nullptr),
q_ptr(q)
{
rfbClientLog = vncLog;
rfbClientErr = vncError;
}
VncClientPrivate::~VncClientPrivate()
{
disconnect();
}
void *VncClientPrivate::dataTag()
{
return reinterpret_cast<void*>(dataTag);
}
void VncClientPrivate::vncLog(const char *format, ...)
{
va_list args;
va_start(args, format);
QString message = QString::vasprintf(format, args);
va_end(args);
qDebug() << "VNC:" << message.trimmed();
}
void VncClientPrivate::vncError(const char *format, ...)
{
va_list args;
va_start(args, format);
QString message = QString::vasprintf(format, args);
va_end(args);
qWarning() << "VNC:" << message.trimmed();
}
void VncClientPrivate::gotFrameBufferUpdate(rfbClient *client,
int x, int y, int w, int h)
{
void *ptr = rfbClientGetClientData(client, dataTag());
static_cast<VncClientPrivate*>(ptr)->onUpdate(x, y, w, h);
}
rfbBool VncClientPrivate::mallocFrameBuffer(rfbClient* client)
{
void *ptr = rfbClientGetClientData(client, dataTag());
static_cast<VncClientPrivate*>(ptr)->onResize();
return true;
}
void VncClientPrivate::onUpdate(int x, int y, int w, int h)
{
for (QQuickItem *viewer: m_viewers) {
// TODO: update only the changed area
viewer->update();
}
}
void VncClientPrivate::onResize()
{
int width = m_client->width;
int height = m_client->height;
qDebug() << Q_FUNC_INFO << width << height;
m_client->updateRect.x = m_client->updateRect.y = 0;
m_client->updateRect.w = width;
m_client->updateRect.h = height;
m_image = QImage(m_client->width, m_client->height, QImage::Format_RGB32);
m_client->frameBuffer = m_image.bits();
m_client->width = m_image.bytesPerLine() / m_bytesPerPixel;
m_client->format.bitsPerPixel = m_image.depth();
m_client->format.redShift=16;
m_client->format.greenShift=8;
m_client->format.blueShift=0;
m_client->format.redMax=0xff;
m_client->format.greenMax=0xff;
m_client->format.blueMax=0xff;
bool ok = SetFormatAndEncodings(m_client);
if (Q_UNLIKELY(!ok)) {
qWarning() << "Could not set format to server";
}
}
bool VncClientPrivate::connectToServer(const QString &host)
{
Q_Q(VncClient);
if (m_client) {
disconnect();
}
m_client = rfbGetClient(8, 3, m_bytesPerPixel);
m_client->MallocFrameBuffer = mallocFrameBuffer;
m_client->GotFrameBufferUpdate = gotFrameBufferUpdate;
rfbClientSetClientData(m_client, dataTag(), this);
QByteArrayList arguments = {
"lomiri-vnc",
};
arguments.append(host.toUtf8());
int argc = arguments.count();
QVector<char *> argv;
argv.reserve(argc + 1);
for (const QByteArray &a: arguments) {
argv.append((char*)a.constData());
}
argv.append(nullptr);
bool ok = rfbInitClient(m_client, &argc, argv.data());
if (Q_UNLIKELY(!ok)) {
qWarning() << "Could not initialize rfbClient";
m_client = nullptr;
return false;
}
m_notifier.reset(new QSocketNotifier(m_client->sock,
QSocketNotifier::Read));
QObject::connect(m_notifier.data(), &QSocketNotifier::activated,
q, [this]() { onSocketActivated(); });
return true;
}
void VncClientPrivate::disconnect()
{
Q_Q(VncClient);
m_notifier.reset();
if (m_client) {
rfbClientCleanup(m_client);
m_client = nullptr;
}
Q_EMIT q->connectionStatusChanged();
}
void VncClientPrivate::onSocketActivated()
{
bool ok = HandleRFBServerMessage(m_client);
if (Q_UNLIKELY(!ok)) {
qWarning() << "RFB failed to handle message";
}
}
VncClient::VncClient(QObject *parent):
QObject(parent),
d_ptr(new VncClientPrivate(this))
{
}
VncClient::~VncClient() = default;
bool VncClient::isConnected() const
{
Q_D(const VncClient);
return d->m_client != nullptr;
}
void VncClient::addViewer(QQuickItem *viewer)
{
Q_D(VncClient);
d->m_viewers.append(viewer);
}
void VncClient::removeViewer(QQuickItem *viewer)
{
Q_D(VncClient);
d->m_viewers.removeAll(viewer);
}
const QImage &VncClient::image() const
{
Q_D(const VncClient);
return d->m_image;
}
bool VncClient::connectToServer(const QString &host)
{
Q_D(VncClient);
return d->connectToServer(host);
}
void VncClient::disconnect()
{
Q_D(VncClient);
return d->disconnect();
}
/*
* Copyright (C) 2020 Alberto Mardegan <mardy@users.sourceforge.net>
*
* This file is part of LomiriVNC.
*
* LomiriVNC is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* LomiriVNC is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with LomiriVNC. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef LOMIRIVNC_VNC_CLIENT_H
#define LOMIRIVNC_VNC_CLIENT_H
#include <QObject>
#include <QScopedPointer>
class QImage;
class QQuickItem;
namespace LomiriVNC {
class VncClientPrivate;
class VncClient: public QObject
{
Q_OBJECT
Q_PROPERTY(bool connected READ isConnected NOTIFY connectionStatusChanged)
public:
VncClient(QObject *parent = nullptr);
virtual ~VncClient();
bool isConnected() const;
void addViewer(QQuickItem *viewer);
void removeViewer(QQuickItem *viewer);
const QImage &image() const;
Q_INVOKABLE bool connectToServer(const QString &host);
Q_INVOKABLE void disconnect();
Q_SIGNALS:
void connectionStatusChanged();
private:
Q_DECLARE_PRIVATE(VncClient)
QScopedPointer<VncClientPrivate> d_ptr;
};
} // namespace
#endif // LOMIRIVNC_VNC_CLIENT_H
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment