summaryrefslogtreecommitdiff
path: root/saltoqd
AgeCommit message (Expand)AuthorFilesLines
2015-04-04make boostable, add systemd serviceJavier8-6/+59
2015-04-04add agenda supportJavier10-20/+225
2015-04-01escape notification textJavier3-5/+33
2015-03-31implement the voicecallmanager (dialer, etc.)Javier9-39/+365
2015-03-31listen to incoming connections tooJavier4-13/+73
2015-03-31prepend notificationsJavier1-1/+1
2015-03-31add fms delete files supportJavier3-19/+72
2015-03-31parse incoming card eventsJavier7-15/+120
2015-03-31allow non-json message payloadsJavier7-24/+43
2015-03-31notifications partially workingJavier11-71/+566
2015-03-30experiment with new notificationmonitor approachJavier9-27/+323
2015-03-29fix profile change detectionJavier7-13/+61
2015-03-29load address from settingsJavier10-21/+51
2015-03-29support recent comms and contactsJavier10-52/+295
2015-03-28implement storagemanagerJavier4-17/+175
2015-03-28implement fms file transfer (via bt obex push)Javier11-27/+721
2015-03-23use plain glibc for tz informationJavier5-17/+26
2015-03-23use profiled via proxyJavier6-15/+55
2015-03-23initial importJavier24-0/+1296
/*
 * scribiu -- read notebooks and voice memos from Livescribe pens
 * Copyright (C) 2021 Javier S. Pedro <javier@javispedro.com>
 *
 * This program 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.
 *
 * This program 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 this program.  If not, see <http://www.gnu.org/licenses/>.
 */

#include <QtCore/QDebug>
#include <QtCore/QTextStream>
#include <QtCore/QXmlStreamWriter>

#include "stfexporter.h"

#define XMLNS_INK "http://www.w3.org/2003/InkML"

class StfToTXYP : public StfReader::StrokeHandler {
	QTextStream _out;
	QPoint _lastP;
	int _lastForce;
	qint64 _startTime;
	bool _relativeTime;

public:
	StfToTXYP(QIODevice *out, bool relativeTime)
	    : _out(out), _lastP(), _lastForce(0), _startTime(0), _relativeTime(relativeTime) {
		_out << "T\tX\tY\tP\n";
	}

	bool startStroke(const QPoint& p, int force, qint64 time) {
		if (_relativeTime && _startTime == 0) {
			_startTime = time;
		}
		_out << (time - _startTime) << '\t' << p.x() << '\t' << p.y() << '\t' << force << '\n';
		_lastP = p;
		_lastForce = force;
		return true;
	}

	bool strokePoint(const QPoint& p, int force, qint64 time) {
		_out << (time - _startTime) << '\t' << p.x() << '\t' << p.y() << '\t' << force << '\n';
		_lastP = p;
		_lastForce = force;
		return true;
	}

	bool endStroke(qint64 time) {
		// Ensure there is a entry with force=0, in case the pen didn't provide it
		if (_lastForce != 0) {
			_out << (time - _startTime) << '\t' << _lastP.x() << '\t' << _lastP.y() << '\t' << 0 << '\n';
			_lastForce = 0;
		}
		return true;
	}
};

class StfToInkML : public StfReader::StrokeHandler {
	QXmlStreamWriter *_out;
	QPoint _lastP;
	qint64 _startTime;

public:
	StfToInkML(QXmlStreamWriter *out)
	    : _out(out), _lastP(), _startTime(0) {
	}

	bool startStroke(const QPoint& p, int force, qint64 time) {
		if (_startTime == 0) {
			_startTime = time;
		}

		_out->writeStartElement(XMLNS_INK, "trace");
		_out->writeAttribute("timeOffset", QString::number(time - _startTime));

		_out->writeCharacters(QString("%1 %2").arg(p.x()).arg(p.y()));

		_lastP = p;
		return true;
	}

	bool strokePoint(const QPoint& p, int force, qint64 time) {
		QPoint delta = p - _lastP;

		_out->writeCharacters(QString(", %1 %2").arg(delta.x()).arg(delta.y()));

		_lastP = p;
		return true;
	}

	bool endStroke(qint64 time) {
		_out->writeEndElement();
		return true;
	}
};

StfExporter::StfExporter(AfdNotebook *nb)
    : _nb(nb)
{
}

void StfExporter::exportToTXYP(QIODevice *out, int pageNum, bool relativeTime)
{
	QStringList pens = _nb->penSerials();
	if (pens.isEmpty()) return;

	StfToTXYP h(out, relativeTime);

	exportPage(&h, pageNum);
}

void StfExporter::exportToInkML(QIODevice *out, int pageNum)
{
	QStringList pens = _nb->penSerials();
	if (pens.isEmpty()) return;

	QXmlStreamWriter writer(out);
	writer.setAutoFormatting(true);
	writer.writeStartDocument();
	writer.writeDefaultNamespace(XMLNS_INK);
	writer.writeStartElement(XMLNS_INK, "ink");

#if 0 /* No need to write out inkSource element, since default trace format is OK for now */
	writer.writeStartElement(XMLNS_INK, "inkSource");
	writer.writeAttribute("manufacturer", "Livescribe");
	writer.writeAttribute("description", "Dumped by Scribiu");
	writer.writeStartElement(XMLNS_INK, "traceFormat");
	writer.writeEmptyElement(XMLNS_INK, "channel");
	writer.writeAttribute("name", "X");
	writer.writeAttribute("type", "integer");
	writer.writeEmptyElement(XMLNS_INK, "channel");
	writer.writeAttribute("name", "Y");
	writer.writeAttribute("type", "integer");
	writer.writeEndElement();
	writer.writeEmptyElement(XMLNS_INK, "sampleRate");
	writer.writeAttribute("uniform", "true");
	writer.writeAttribute("value", "75");
	writer.writeEndElement();
#endif

	StfToInkML h(&writer);

	exportPage(&h, pageNum);

	writer.writeEndElement();
	writer.writeEndDocument();
}

bool StfExporter::exportPage(StfReader::StrokeHandler *handler, int pageNum)
{
	QStringList pens = _nb->penSerials();
	if (pens.isEmpty()) return true; // No pen wrote on this page

	StfReader r;
	r.setStrokeHandler(handler);

	foreach (const QString &pen, pens) {
		QStringList strokeFiles = _nb->strokeFiles(pen, pageNum);
		foreach (const QString &strokeFile, strokeFiles) {
			QFile in(strokeFile);
			if (!in.open(QIODevice::ReadOnly)) {
				qWarning() << "Could not open stroke file:" << strokeFile;
				continue;
			}

			if (!r.parse(&in)) {
				qWarning() << "Could not parse stroke file:" << strokeFile;
				continue;
			}
		}
	}

	return true;
}