fixed a lot of bugs and moved lib to subdir

This commit is contained in:
Steffen Vogel 2015-01-18 00:06:37 +01:00
parent cb69e2f558
commit fa67b56371
12 changed files with 345 additions and 250 deletions

View file

@ -1,207 +0,0 @@
#include <QtDebug>
#include <QUrl>
#include <QTcpSocket>
#include <QNetworkAccessManager>
#include <QNetworkReply>
#include <QNetworkRequest>
#include <QEventLoop>
#include "camera.h"
Camera::Camera() :
address("192.168.0.10")
{
networkManager = new QNetworkAccessManager;
connect(networkManager, &QNetworkAccessManager::finished, this, &Camera::requestFinished);
intialize();
}
void Camera::initialize()
{
requestCamInfo();
requestCapacity();
requestCommandList();
requestImageList();
completeRequests();
}
bool Camera::isOnline()
{
QTcpSocket socket;
socket.connectToHost(address, 80, QIODevice::ReadOnly);
return socket.waitForConnected(2000);
}
/********* Request handling ***********/
QNetworkRequest Camera::makeRequest(QString cgi, QPair<QString, QString> params)
{
QString tpl("http://%1/%2.cgi");
tpl.arg(address.toString()).arg(cgi);
QUrl url(tpl);
url.setQueryItems(params);
QNetworkRequest request(url);
request.setHeader(QNetworkRequest::UserAgentHeader, userAgent);
request.setAttribute(QNetworkRequest::User, QVariant(cgi));
request.setAttribute(QNetworkRequest::User+1, QVariant(params));
return request;
}
QNetworkReply Camera::get(QString cgi, QPair<QString, QString> params)
{
QNetworkRequest request = makeRequest(cgi, params);
// FIXME check with commandList
return networkManager.get(request);
}
QNetworkReply Camera::post(QString cgi, QPair<QString, QString> params, QDomDocument body)
{
QNetworkRequest request = makeRequest(cgi, params);
// FIXME check with commandList
return networkManager.post(request, body.toByteArray());
}
void Camera::completeAllRequests()
{
static QEventLoop loop;
while (!requests.empty())
loop.exec();
}
void Camera::requestFinished(QNetworkReply *reply)
{
QDomDocument xml;
if (reply->error() == QNetworkReply::NoError) {
QString contentType = reply->header(QNetworkRequest::ContentTypeHeader);
QString cgi = reply->attribute(QNetworkRequest::User);
cacheMap[cgi] = QDateTime::currentDateTimeUtc();
if (contentType == "text/xml" && reply->size() > 0) {
QDomDocument body;
if (body.setContent(reply->readAll()))
parseXml(cgi, body);
else
qCritical() << "Failed to parse XML reply";
}
else if (contentType == "text/plain" && reply->size() > 0)
parseList(cgi, reply->readAll());
else if (contentType == "www/unknown" && reply->size() == 0)
parse(cgi);
else if (contentType == "image/jpeg")
parseImage(reply->readAll());
else
qCritical() << "Failed to parse reply: Content-Type = " << contentType
<< ", Size = " << reply->size()
<< ", URI = " << reply->request().url();
}
else
qWarning() << "Request failed: " << reply->errorString();
requests.removeAll(reply);
}
/********* Requests **********/
void Camera::takeImage() { get("exec_takemotion"); }
void Camera::powerOff() { get("exec_pwoff"); }
void Camera::requestCamInfo() { get("get_caminfo"); }
void Camera::requestCapacity() { get("get_unusedcapacity"); }
void Camera::requestConnectMode() { get("get_connectmode"); }
void Camera::requestImageList(bool rsv) { get(rsv ? "get_rsvimglist" : "get_imglist"); }
void Camera::requestImage(QString name, QSize resolution)
{
}
void Camera::switchCamMode(CamMode mode)
{
QPair<QString, QString> params;
switch (mode) {
case PLAY:
params["mode"] = "play";
break;
case RECORD:
params["mode"] = "rec";
params["lvqty"] = liveViewQuality;
break;
case SHUTTER:
params["mode"] = "shutter";
break;
}
get("switch_cammode", params);
}
/*********** Reply parsers ************/
void Camera::parseXml(QString cgi, QDomDocument *body)
{
if (cgi == "get_unusedcapacity") parseCapacity(body);
else if (cgi == "get_commandlist") parseCommandList(body);
else if (cgi == "get_camprop") parseProperties(body);
else if (cgi == "set_camprop") parseProperties(body);
else if (cgi == "get_connectmode") parseConnectMode(body);
else if (cgi == "exec_takemotion") parseTakeMotion(body);
else if (cgi == "exec_takemisc") parseTakeMisc(body);
}
void Camera::parseList(QByteArray *body)
{
QList<QString> &list;
if (cgi == "get_imglist") list = imageList;
else if (cgi == "get_rsvimglist") list = reservedImageList;
}
void Camera::parseImage(QByteArray *body)
{
}
void Camera::parseCamInfo(QDomDocument *body)
{
QDomElement camInfo = body->firstChildElement("caminfo");
if (!camInfo.isNull()) {
QDomElement model = camInfo.firstChildElement("model");
camModel = model.text();
}
}
void Camera::parseCapacity(QDomDocument *body)
{
QDomElement camInfo = body->firstChildElement("caminfo");
if (!camInfo.isNull()) {
QDomElement model = camInfo.firstChildElement("model");
camModel = model.text();
}
}
void Camera::parseCommandList(QDomDocument *body)
{
commandList = *body;
}
void Camera::parseConnectMode(QDomDocument *body)
{
}

288
libqt-omd/camera.cpp Normal file
View file

@ -0,0 +1,288 @@
#include <QtDebug>
#include <QUrl>
#include <QUrlQuery>
#include <QTcpSocket>
#include <QNetworkAccessManager>
#include <QNetworkReply>
#include <QNetworkRequest>
#include <QEventLoop>
#include "camera.h"
const QString Camera::userAgent = "libqt-omd v0.1";
Camera::Camera() :
camAddress("192.168.0.10")
{
networkManager = new QNetworkAccessManager;
connect(networkManager, &QNetworkAccessManager::finished, this, &Camera::requestFinished);
initialize();
}
void Camera::initialize()
{
switchCamMode(MODE_PLAY);
//completePendingRequests();
requestCamInfo();
requestCapacity();
requestConnectMode();
requestCommandList();
requestImageList();
completePendingRequests();
}
bool Camera::isOnline()
{
QTcpSocket socket;
socket.connectToHost(camAddress, 80, QIODevice::ReadOnly);
return socket.waitForConnected(2000);
}
/********* Request handling ***********/
QNetworkRequest Camera::makeRequest(QString cgi, QMap<QString, QString> params)
{
QString tpl = QString("http://%1/%2.cgi").arg(camAddress.toString()).arg(cgi);
QUrl url(tpl);
QUrlQuery query(url);
QList<QPair<QString, QString>> paramList;
for (QString key : params.keys())
paramList.push_back(qMakePair(key, params[key]));
query.setQueryItems(paramList);
url.setQuery(query);
QNetworkRequest request(url);
request.setHeader(QNetworkRequest::UserAgentHeader, userAgent);
return request;
}
QNetworkReply * Camera::get(QString cgi, QMap<QString, QString> params)
{
QNetworkRequest request = makeRequest(cgi, params);
QNetworkReply *reply = networkManager->get(request);
qDebug() << "[libqt-omd] New GET request:" << request.url();
pendingReplies.append(reply);
return reply;
}
QNetworkReply * Camera::post(QString cgi, QMap<QString, QString> params, QDomDocument body)
{
QNetworkRequest request = makeRequest(cgi, params);
QNetworkReply *reply = networkManager->post(request, body.toByteArray());
qDebug() << "[libqt-omd] New POST request:" << request.url();
pendingReplies.append(reply);
return reply;
}
void Camera::completePendingRequests()
{
static QEventLoop loop;
connect(networkManager, &QNetworkAccessManager::finished, &loop, &QEventLoop::wakeUp);
while (!pendingReplies.empty()) {
qDebug() << "[libqt-omd] Entering event loop!";
loop.exec();
}
}
void Camera::requestFinished(QNetworkReply *reply)
{
QDomDocument xml;
qDebug() << "[libqt-omd] Request finished:" << reply->url();
if (reply->error() == QNetworkReply::NoError) {
QString contentType = reply->header(QNetworkRequest::ContentTypeHeader).toString();
QString cgi = reply->attribute(QNetworkRequest::User).toString();
cacheMap[cgi] = QDateTime::currentDateTimeUtc();
if (contentType == "text/xml" && reply->size() > 0) {
QDomDocument body;
if (body.setContent(reply->readAll())) {
qDebug() << "[libqt-omd] Content:" << body.toString();
parseXml(cgi, body);
}
else
qCritical() << "Failed to parse XML reply";
}
else if (contentType == "text/plain" && reply->size() > 0)
parseList(cgi, reply->readAll());
else if (contentType == "www/unknown" && reply->size() == 0)
parseEmpty(cgi);
else if (contentType == "image/jpeg")
parseImage(cgi, reply->readAll());
else
qCritical() << "Failed to parse reply: Content-Type = " << contentType
<< ", Size = " << reply->size()
<< ", URI = " << reply->request().url();
}
else
qWarning() << "Request failed: " << reply->errorString();
pendingReplies.removeAll(reply);
}
/********* Actions ***********/
void Camera::controlZoom(ZoomMode cmd)
{
// FIXME implement
}
void Camera::setTimeDiff(QDateTime t)
{
// FIXME implement
}
void Camera::reFocus(QPoint pos, QSize size)
{
// FIXME implement
}
/********* Requests **********/
void Camera::takeShot() { get("exec_takemotion"); }
void Camera::powerOff() { get("exec_pwoff"); }
void Camera::requestCamInfo() { get("get_caminfo"); }
void Camera::requestCapacity() { get("get_unusedcapacity"); }
void Camera::requestConnectMode() { get("get_connectmode"); }
void Camera::requestCommandList() { get("get_commandlist"); }
void Camera::requestImageList(QString dir, bool rsv) {
QMap<QString, QString> params;
params["DIR"] = dir.replace('/', "%2F");
get(rsv ? "get_rsvimglist" : "get_imglist", params);
}
void Camera::requestImage(QString name, QSize resolution)
{
QString tpl = QString("http://%1/DCIM/100OLYMP/%1.JPG").arg(camAddress.toString()).arg(name);
QUrl url(tpl);
QNetworkRequest request(url);
networkManager->get(request);
}
void Camera::switchCamMode(CamMode mode)
{
QMap<QString, QString> params;
switch (mode) {
case MODE_PLAY:
params["mode"] = "play";
break;
case MODE_RECORD:
params["mode"] = "rec";
params["lvqty"] = "0640x0480"; // FIXME allow other liveViewQualities
break;
case MODE_SHUTTER:
params["mode"] = "shutter";
break;
}
get("switch_cammode", params);
}
/*********** Reply parsers ************/
void Camera::parseXml(QString cgi, QDomDocument body)
{
if (cgi == "get_unusedcapacity") parseCapacity(body);
else if (cgi == "get_commandlist") parseCommandList(body);
else if (cgi == "get_camprop") parseProperties(body);
else if (cgi == "set_camprop") parseProperties(body);
else if (cgi == "get_connectmode") parseConnectMode(body);
else if (cgi == "exec_takemotion") parseTakeMotion(body);
else if (cgi == "exec_takemisc") parseTakeMisc(body);
}
void Camera::parseList(QString cgi, QByteArray body)
{
QList<QString> *list;
if (cgi == "get_imglist") list = &imageList;
else if (cgi == "get_rsvimglist") list = &reservedImageList;
for (QByteArray line : body.split('\n')) {
qDebug() << line;
}
}
void Camera::parseImage(QString cgi, QByteArray body)
{
QImage img = QImage::fromData(body.data());
emit receivedImage(img);
}
void Camera::parseEmpty(QString cgi)
{
// FIXME anything to do here?
}
void Camera::parseCamInfo(QDomDocument body)
{
QDomElement elm = body.firstChildElement("caminfo");
if (!elm.isNull()) {
QDomElement model = elm.firstChildElement("model");
camModel = model.text();
}
}
void Camera::parseCapacity(QDomDocument body)
{
QDomElement elm = body.firstChildElement("unused");
if (!elm.isNull())
unusedCapacity = elm.text().toInt();
}
void Camera::parseCommandList(QDomDocument body)
{
commandList = body;
}
void Camera::parseConnectMode(QDomDocument body)
{
QDomElement elm = body.firstChildElement("connectmode");
if (!elm.isNull()) {
if (elm.text() == "private")
connectMode = CONNECT_PRIVATE;
else if (elm.text() == "shared")
connectMode = CONNECT_SHARED;
else
qWarning() << "[libqt-omd] Warning: unknown connectMode:" << elm.text();
}
}
void Camera::parseProperties(QDomDocument body)
{
}
void Camera::parseTakeMisc(QDomDocument body)
{
}
void Camera::parseTakeMotion(QDomDocument body)
{
}

View file

@ -1,20 +1,21 @@
#ifndef CAMERA_H
#define CAMERA_H
#include <QPair>
#include <QString>
#include <QImage>
#include <QNetworkAccessManager>
#include <QHostAddress>
#include <QImage>
#include <QDateTime>
#include <QtXml/QDomDocument>
#include "liveview.h"
class Camera
class QNetworkAccessManager;
class QNetworkReply;
class QNetworkRequest;
class Camera : public QObject
{
Q_OBJECT
// FIXME add Q_PROPERTY
// FIXME add Q_PROPERTY's
public:
/* Enums */
@ -47,7 +48,7 @@ public:
void requestCapacity();
void requestConnectMode();
void requestCommandList();
void requestImageList(bool reserved = false);
void requestImageList(QString dir = "/DCIM/100OLYMP", bool reserved = false);
void requestImage(QString name = QString(), QSize resolution = QSize(-1, -1));
/* Synchronous getters */
@ -63,7 +64,7 @@ public:
/* Cached getters */
bool isOnline();
enum Mode getCamMode();
enum CamMode getCamMode();
public slots:
void switchCamMode(enum CamMode mode);
@ -74,9 +75,9 @@ public slots:
void setTimeDiff(QDateTime t);
signals:
void receivedImage(QImage *);
void receivedImage(QImage);
void changedProperty(QString key, QString value);
void changedMode(enum Mode);
void changedMode(enum CamMode);
void connected(enum ConnectMode);
protected slots:
@ -84,27 +85,34 @@ protected slots:
protected:
/* Network requests */
QNetworkRequest makeRequest(QString cgi, QPair<QString, QString> params);
QNetworkReply get(QString cgi, QPair<QString, QString> params = QPair<QString, QString>());
QNetworkReply post(QString cgi, QPair<QString, QString> params = QPair<QString, QString>(), QDomDocument body);
QNetworkRequest makeRequest(QString cgi, QMap<QString, QString> params);
QNetworkReply * get(QString cgi, QMap<QString, QString> params = QMap<QString, QString>());
QNetworkReply * post(QString cgi, QMap<QString, QString> params = QMap<QString, QString>(), QDomDocument body = QDomDocument());
/* Parsers */
void parseCamInfo(QDomDocument *body);
void parseCapacity(QDomDocument *body);
void parseConnectMode(QDomDocument *body);
void parseCommandList(QDomDocument *body);
void parseCamProperties(QDomDocument *body);
void parseImage(QByteArray *body);
void parseEmpty(QString cgi);
void parseXml(QString cgi, QDomDocument body);
void parseList(QString cgi, QByteArray body);
void parseImage(QString cgi, QByteArray body);
void parseCamInfo(QDomDocument body);
void parseCapacity(QDomDocument body);
void parseConnectMode(QDomDocument body);
void parseCommandList(QDomDocument body);
void parseProperties(QDomDocument body);
void parseTakeMotion(QDomDocument body);
void parseTakeMisc(QDomDocument body);
/* Helpers */
void completeRequests();
void completePendingRequests();
void initialize();
/* Members */
QHostAddress camAddress;
QList<QNetworkReply *> pendingReplies;
QMap<QString, QDateTime> cacheMap;
QNetworkAccessManager *networkManager;
LiveView *liveView;
QHostAddress camAddress;
QList<QNetworkReply *> pendingReplies;
QMap<QString, QDateTime> cacheMap;
QNetworkAccessManager * networkManager;
LiveView * liveView;
/* Properties */
enum CamMode camMode;
@ -121,7 +129,7 @@ protected:
QList<QString> reservedImageList;
/* Constants */
static const QString userAgent = "OI.Share v2";
static const QString userAgent;
};
#endif // CAMERA_H

View file

@ -0,0 +1,2 @@
// Add predefined macros for your project here. For example:
// #define THE_ANSWER 42

View file

@ -0,0 +1,6 @@
camera.cpp
camera.h
liveview.cpp
liveview.h
properties.cpp
properties.h

View file

@ -0,0 +1 @@
.

View file

@ -21,3 +21,5 @@ unix {
target.path = /usr/lib
INSTALLS += target
}
CONFIG += c++11

View file

@ -8,17 +8,14 @@ Properties::Properties(QDomNode desclist)
while (!desc.isNull()) {
Property prop(desc);
if (prop.isValid()) {
if (prop.isValid())
properties[prop.key] = prop;
qDebug() <<
}
desc = desc.nextSibling();
}
}
Property::Property(QDomNode desc) :
Property::Property(QDomNode desc)
{
key = desc.firstChildElement("propname").text();
value = desc.firstChildElement("value").text();
@ -26,22 +23,21 @@ Property::Property(QDomNode desc) :
QString attr = desc.firstChildElement("attribute").text();
if (attr.contains("set"))
flags |= PROP_SET;
flags |= PROP_SETABLE;
if (attr.contains("get"))
flags |= PROP_GET;
flags |= PROP_GETABLE;
if (valid.contains(value))
flags |= PROP_VALID;
}
Property& Property::operator =(const QString &newValue)
Property & Property::operator =(const QString &newValue)
{
if (valid.contains(newValue)) {
value = newValue;
flags |= PROP_CHANGED;
}
emit propertyChanged(key, value);
return *this;
}
bool Property::isValid(QString check)

View file

@ -16,11 +16,9 @@ public:
Property& operator[](const QString &key);
protected:
Camera *cam;
QMap<QString, Property> properties;
};
class Property
@ -35,15 +33,13 @@ class Property
};
public:
Property() { }
Property(QDomElement desc);
Property& operator =(const QString &value);
operator QString();
bool isValid(QString value = QString);
signals:
void changed(QString key, QString value);
bool isValid(QString value = QString());
protected:
Property(QDomNode desc);

3
omd.pro Normal file
View file

@ -0,0 +1,3 @@
TEMPLATE = subdirs
SUBDIRS = libqt-omd test