From e48a4a6f34bd813c690d8066af39c781a922b532 Mon Sep 17 00:00:00 2001 From: Javier Date: Tue, 14 Apr 2015 23:36:29 +0200 Subject: allow writing images from dbus --- saltoqd/msolimageiohandler.cpp | 162 ++++++++++++++++++++++++++++++++ saltoqd/msolimageiohandler.h | 20 ++++ saltoqd/saltoq-bt-sniff-subrate.service | 2 +- saltoqd/saltoqd.pro | 6 +- saltoqd/toqmanageradaptor.cpp | 35 +++++++ saltoqd/toqmanageradaptor.h | 2 + 6 files changed, 224 insertions(+), 3 deletions(-) create mode 100644 saltoqd/msolimageiohandler.cpp create mode 100644 saltoqd/msolimageiohandler.h diff --git a/saltoqd/msolimageiohandler.cpp b/saltoqd/msolimageiohandler.cpp new file mode 100644 index 0000000..bd0b23c --- /dev/null +++ b/saltoqd/msolimageiohandler.cpp @@ -0,0 +1,162 @@ +#include +#include +#include +#include + +#include "msolimageiohandler.h" + +static const int header_size = 16; + +namespace +{ + +static inline uchar encode_color(QRgb c) +{ + return (qRed(c) & 0xC0) | ((qBlue(c) & 0xC0) >> 2) | ((qGreen(c) & 0xC0) >> 4) | 3; +} + +static inline QRgb decode_color(uchar p, uchar a = 255) +{ + return qRgba(p & 0xC0, (p & 0x30) << 2, (p & 0x0C) << 4, a); +} + +} + +MSOLImageIOHandler::MSOLImageIOHandler() : QImageIOHandler() +{ +} + +bool MSOLImageIOHandler::canRead() const +{ + char header[header_size]; + if (device()->peek(header, header_size) != header_size) { + return false; + } + + return strncmp(&header[0], "MSOL ", 6) == 0; +} + +bool MSOLImageIOHandler::read(QImage *image) +{ + QIODevice *dev = device(); + + uchar header[header_size]; + if (dev->read(reinterpret_cast(header), header_size) != header_size) { + return false; + } + + if (strncmp(reinterpret_cast(&header[0]), "MSOL ", 6) != 0) { + return false; + } + + const bool alpha = header[6]; + const int width = qFromLittleEndian(&header[8]); + const int height = qFromLittleEndian(&header[10]); + const int pixel_size = alpha ? 2 : 1; + const int line_size = width * pixel_size; + + if (alpha) { + *image = QImage(width, height, QImage::Format_ARGB32); + } else { + *image = QImage(width, height, QImage::Format_RGB32); + } + + Q_ASSERT(image->depth() == sizeof(QRgb) * 8); + + for (int y = 0; y < height; y++) { + QRgb *dst = reinterpret_cast(image->scanLine(y)); + uchar src[line_size]; + if (dev->read(reinterpret_cast(src), line_size) != line_size) { + qDebug() << "Could not read image line" << y; + return false; + } + for (int x = 0; x < width; x++) { + if (alpha) { + dst[x] = decode_color(src[x * pixel_size]); + } else { + dst[x] = decode_color(src[x * pixel_size], src[(x * pixel_size) + 1]); + } + } + } + + return true; +} + +bool MSOLImageIOHandler::write(const QImage &image) +{ + QIODevice *dev = device(); + const int height = image.height(); + const int width = image.width(); + const bool alpha = image.hasAlphaChannel(); + const int pixel_size = alpha ? 2 : 1; + const int line_size = width * pixel_size; + + QImage img = image.convertToFormat(alpha ? QImage::Format_ARGB32 : QImage::Format_RGB32); + + uchar header[header_size] = { 0 }; + strcpy(reinterpret_cast(&header[0]), "MSOL "); + if (alpha) header[6] = 0x80; + header[7] = 8; + + qToLittleEndian(width, &header[8]); + qToLittleEndian(height, &header[10]); + + if (dev->write(reinterpret_cast(header), header_size) != header_size) { + qDebug() << "Could not write header"; + return false; + } + + Q_ASSERT(img.depth() == sizeof(QRgb) * 8); + + for (int y = 0; y < height; y++) { + uchar dst[line_size]; + const QRgb *src = reinterpret_cast(img.constScanLine(y)); + for (int x = 0; x < width; x++) { + dst[x * pixel_size] = encode_color(src[x]); + if (alpha) { + dst[(x * pixel_size) + 1] = qAlpha(src[x]); + } + } + if (dev->write(reinterpret_cast(dst), line_size) != line_size) { + qDebug() << "Could not write image line " << y; + return false; + } + } + + return true; +} + +bool MSOLImageIOHandler::supportsOption(ImageOption option) const +{ + switch (option) { + case Size: + return true; + default: + return false; + } +} + +QVariant MSOLImageIOHandler::option(ImageOption option) const +{ + char header[header_size]; + + switch (option) { + case Size: + if (device()->peek(header, header_size) == header_size) { + const QSize size(qFromLittleEndian(reinterpret_cast(&header[8])), + qFromLittleEndian(reinterpret_cast(&header[10]))); + return QVariant::fromValue(size); + } else { + qDebug() << "Cannot read from device: " << device()->errorString(); + } + default: + break; + } + + return QVariant(); +} + +void MSOLImageIOHandler::setOption(ImageOption option, const QVariant &value) +{ + +} diff --git a/saltoqd/msolimageiohandler.h b/saltoqd/msolimageiohandler.h new file mode 100644 index 0000000..992c68e --- /dev/null +++ b/saltoqd/msolimageiohandler.h @@ -0,0 +1,20 @@ +#ifndef MSOLIMAGEIOHANDLER_H +#define MSOLIMAGEIOHANDLER_H + +#include + +class MSOLImageIOHandler : public QImageIOHandler +{ +public: + MSOLImageIOHandler(); + + bool canRead() const Q_DECL_OVERRIDE; + bool read(QImage *image) Q_DECL_OVERRIDE; + bool write(const QImage &image) Q_DECL_OVERRIDE; + + bool supportsOption(ImageOption option) const Q_DECL_OVERRIDE; + QVariant option(ImageOption option) const Q_DECL_OVERRIDE; + void setOption(ImageOption option, const QVariant &value) Q_DECL_OVERRIDE; +}; + +#endif // MSOLIMAGEIOHANDLER_H diff --git a/saltoqd/saltoq-bt-sniff-subrate.service b/saltoqd/saltoq-bt-sniff-subrate.service index 08bad83..83e992c 100644 --- a/saltoqd/saltoq-bt-sniff-subrate.service +++ b/saltoqd/saltoq-bt-sniff-subrate.service @@ -1,6 +1,6 @@ [Unit] Description=Set Bluetooth's sniff_max_interval -After=local-fs.target +After=bluetooth.service [Service] Type=oneshot diff --git a/saltoqd/saltoqd.pro b/saltoqd/saltoqd.pro index 4337097..b154491 100644 --- a/saltoqd/saltoqd.pro +++ b/saltoqd/saltoqd.pro @@ -26,7 +26,8 @@ SOURCES += main.cpp \ agendamanager.cpp \ settings.cpp \ settingsmanager.cpp \ - toqmanageradaptor.cpp + toqmanageradaptor.cpp \ + msolimageiohandler.cpp HEADERS += \ toqconnection.h \ @@ -46,7 +47,8 @@ HEADERS += \ agendamanager.h \ settings.h \ settingsmanager.h \ - toqmanageradaptor.h + toqmanageradaptor.h \ + msolimageiohandler.h DBUS_INTERFACES += com.nokia.profiled.xml org.nemomobile.voicecall.VoiceCallManager.xml org.nemomobile.voicecall.VoiceCall.xml QDBUSXML2CPP_INTERFACE_HEADER_FLAGS = -i voicecallmanager.h diff --git a/saltoqd/toqmanageradaptor.cpp b/saltoqd/toqmanageradaptor.cpp index d5ee41d..5ec11c2 100644 --- a/saltoqd/toqmanageradaptor.cpp +++ b/saltoqd/toqmanageradaptor.cpp @@ -1,6 +1,9 @@ #include +#include +#include #include "toqmanageradaptor.h" +#include "msolimageiohandler.h" #include "fmsmanager.h" ToqManagerAdaptor::ToqManagerAdaptor(FmsManager *fms, ToqManager *parent) @@ -11,6 +14,11 @@ ToqManagerAdaptor::ToqManagerAdaptor(FmsManager *fms, ToqManager *parent) setAutoRelaySignals(true); } +void ToqManagerAdaptor::PutData(const QByteArray &data, const QString &remoteFile) +{ + _fms->updateFile(remoteFile, data); +} + void ToqManagerAdaptor::PutFile(const QString &localFile, const QString &remoteFile, const QDBusMessage &msg) { QFile f(localFile); @@ -22,3 +30,30 @@ void ToqManagerAdaptor::PutFile(const QString &localFile, const QString &remoteF _fms->updateFile(remoteFile, f.readAll()); } + +void ToqManagerAdaptor::PutImage(const QString &localFile, const QString &remoteFile, const QDBusMessage &msg) +{ + QFile f(localFile); + if (!f.exists()) { + QDBusMessage reply = msg.createErrorReply("com.javispedro.saltoq.InvalidFile", "File does not exist"); + _conn.send(reply); + return; + } + QImage image(localFile); + if (image.isNull()) { + QDBusMessage reply = msg.createErrorReply("com.javispedro.saltoq.InvalidImage", "Cannot read image"); + _conn.send(reply); + return; + } + MSOLImageIOHandler msolio; + QBuffer msolImg; + msolImg.open(QBuffer::WriteOnly); + msolio.setDevice(&msolImg); + if (!msolio.write(image)) { + QDBusMessage reply = msg.createErrorReply("com.javispedro.saltoq.InvalidImage", "Cannot convert this image"); + _conn.send(reply); + return; + } + + _fms->updateFile(remoteFile, msolImg.data()); +} diff --git a/saltoqd/toqmanageradaptor.h b/saltoqd/toqmanageradaptor.h index c2e62e9..b867591 100644 --- a/saltoqd/toqmanageradaptor.h +++ b/saltoqd/toqmanageradaptor.h @@ -20,7 +20,9 @@ public: bool isConnected() const; public slots: + void PutData(const QByteArray &data, const QString &remoteFile); void PutFile(const QString &localFile, const QString &remoteFile, const QDBusMessage &msg); + void PutImage(const QString &localFile, const QString &remoteFile, const QDBusMessage &msg); signals: void connectedChanged(); -- cgit v1.2.3