Add capability to link recorded audio to text nodes

presentation
Ulrich Huber 7 years ago
parent 780fd08936
commit dc8f82a401
  1. 25
      src/control/xml/XmlAudioNode.cpp
  2. 37
      src/control/xml/XmlAudioNode.h
  3. 12
      src/control/xml/XmlPointNode.cpp
  4. 7
      src/control/xml/XmlPointNode.h
  5. 4
      src/control/xml/XmlTextNode.cpp
  6. 3
      src/control/xml/XmlTextNode.h
  7. 12
      src/control/xojfile/LoadHandler.cpp
  8. 4
      src/control/xojfile/SaveHandler.cpp
  9. 3
      src/control/xojfile/SaveHandler.h
  10. 11
      src/gui/PageView.cpp
  11. 4
      src/gui/PageViewFindObjectHelper.h
  12. 80
      src/model/AudioElement.cpp
  13. 50
      src/model/AudioElement.h
  14. 56
      src/model/Stroke.cpp
  15. 18
      src/model/Stroke.h
  16. 26
      src/model/Text.cpp
  17. 6
      src/model/Text.h
  18. 3
      src/util/XournalTypeList.h

@ -0,0 +1,25 @@
#include "XmlAudioNode.h"
XmlAudioNode::XmlAudioNode(const char* tag)
: XmlNode(tag),
audioFilename("")
{
XOJ_INIT_TYPE(XmlAudioNode);
}
XmlAudioNode::~XmlAudioNode()
{
XOJ_CHECK_TYPE(XmlAudioNode);
XOJ_RELEASE_TYPE(XmlAudioNode);
}
string XmlAudioNode::getAudioFilename()
{
return this->audioFilename;
}
void XmlAudioNode::setAudioFilename(string filename)
{
this->audioFilename = filename;
}

@ -0,0 +1,37 @@
/*
* Xournal++
*
* [Header description]
*
* @author Xournal++ Team
* https://github.com/xournalpp/xournalpp
*
* @license GNU GPLv2 or later
*/
#pragma once
#include "XmlNode.h"
class XmlAudioNode : public XmlNode
{
public:
XmlAudioNode(const char* tag);
virtual ~XmlAudioNode();
private:
XmlAudioNode(const XmlAudioNode& node);
void operator=(const XmlAudioNode& node);
public:
string getAudioFilename();
void setAudioFilename(string filename);
private:
XOJ_TYPE_ATTRIB;
string audioFilename;
};

@ -1,7 +1,7 @@
#include "XmlPointNode.h"
XmlPointNode::XmlPointNode(const char* tag)
: XmlNode(tag),
: XmlAudioNode(tag),
points(NULL)
{
XOJ_INIT_TYPE(XmlPointNode);
@ -22,16 +22,6 @@ XmlPointNode::~XmlPointNode()
XOJ_RELEASE_TYPE(XmlPointNode);
}
string XmlPointNode::getAudioFilename()
{
return this->audioFilename;
}
void XmlPointNode::setAudioFilename(string filename)
{
this->audioFilename = filename;
}
void XmlPointNode::addPoint(const Point* point)
{
XOJ_CHECK_TYPE(XmlPointNode);

@ -11,10 +11,10 @@
#pragma once
#include "XmlNode.h"
#include "model/Point.h"
#include "XmlAudioNode.h"
class XmlPointNode : public XmlNode
class XmlPointNode : public XmlAudioNode
{
public:
XmlPointNode(const char* tag);
@ -26,13 +26,10 @@ private:
public:
void addPoint(const Point* point);
string getAudioFilename();
void setAudioFilename(string filename);
virtual void writeOut(OutputStream* out);
private:
XOJ_TYPE_ATTRIB;
GList* points;
string audioFilename;
};

@ -2,14 +2,14 @@
#include <StringUtils.h>
XmlTextNode::XmlTextNode(const char* tag, const char* text) : XmlNode(tag)
XmlTextNode::XmlTextNode(const char* tag, const char* text) : XmlAudioNode(tag)
{
XOJ_INIT_TYPE(XmlTextNode);
this->text = g_strdup(text);
}
XmlTextNode::XmlTextNode(const char* tag) : XmlNode(tag)
XmlTextNode::XmlTextNode(const char* tag) : XmlAudioNode(tag)
{
XOJ_INIT_TYPE(XmlTextNode);

@ -12,8 +12,9 @@
#pragma once
#include "XmlNode.h"
#include "XmlAudioNode.h"
class XmlTextNode : public XmlNode
class XmlTextNode : public XmlAudioNode
{
public:
XmlTextNode(const char* tag, const char* text);

@ -639,6 +639,18 @@ void LoadHandler::parseText()
int color = 0;
LoadHandlerHelper::parseColor(sColor, color, this);
text->setColor(color);
const char* fn = LoadHandlerHelper::getAttrib("fn", true, this);
if (fn != NULL)
{
text->setAudioFilename(fn);
}
size_t ts = 0;
if (LoadHandlerHelper::getAttribSizeT("ts", true, this, ts))
{
text->setTimestamp(ts);
}
}
void LoadHandler::parseImage()

@ -105,7 +105,7 @@ string SaveHandler::getColorStr(int c, unsigned char alpha)
return color;
}
void SaveHandler::writeTimestamp(Stroke* s, XmlPointNode* stroke)
void SaveHandler::writeTimestamp(AudioElement* s, XmlAudioNode* stroke)
{
XOJ_CHECK_TYPE(SaveHandler);
@ -217,6 +217,8 @@ void SaveHandler::visitLayer(XmlNode* page, Layer* l)
text->setAttrib("x", t->getX());
text->setAttrib("y", t->getY());
text->setAttrib("color", getColorStr(t->getColor()).c_str());
writeTimestamp(t, text);
}
else if (e->getType() == ELEMENT_IMAGE)
{

@ -17,6 +17,7 @@
#include <OutputStream.h>
#include <XournalType.h>
#include <control/xml/XmlAudioNode.h>
class XmlNode;
class XmlPointNode;
@ -48,7 +49,7 @@ protected:
virtual void writeHeader();
virtual void writeSolidBackground(XmlNode* background, PageRef p);
virtual void writeTimestamp(Stroke* s, XmlPointNode* stroke);
virtual void writeTimestamp(AudioElement* s, XmlAudioNode* stroke);
protected:
XOJ_TYPE_ATTRIB;

@ -287,6 +287,15 @@ void XojPageView::startText(double x, double y)
text->setY(y);
text->setColor(h->getColor());
text->setFont(settings->getFont());
if (xournal->getControl()->getAudioController()->getAudioRecorder()->isRecording())
{
string audioFilename = xournal->getControl()->getAudioController()->getAudioFilename();
size_t sttime = xournal->getControl()->getAudioController()->getStartTime();
size_t milliseconds = ((g_get_monotonic_time() / 1000) - sttime);
text->setTimestamp(milliseconds);
text->setAudioFilename(audioFilename);
}
}
else
{
@ -303,6 +312,8 @@ void XojPageView::startText(double x, double y)
text->setColor(oldtext->getColor());
text->setFont(oldtext->getFont());
text->setText(oldtext->getText());
text->setTimestamp(oldtext->getTimestamp());
text->setAudioFilename(oldtext->getAudioFilename());
Layer* layer = this->page->getSelectedLayer();
layer->removeElement(this->oldtext, false);

@ -147,12 +147,12 @@ public:
protected:
virtual void checkElement(Element* e)
{
if (e->getType() != ELEMENT_STROKE)
if (e->getType() != ELEMENT_STROKE && e->getType() != ELEMENT_TEXT)
{
return;
}
Stroke* s = (Stroke*) e;
AudioElement* s = (AudioElement*) e;
double tmpGap = 0;
if ((s->intersects(x, y, 15, &tmpGap)))
{

@ -0,0 +1,80 @@
#include "AudioElement.h"
AudioElement::AudioElement(ElementType type) : Element(type)
{
XOJ_INIT_TYPE(AudioElement);
this->timestamp = 0;
}
AudioElement::~AudioElement()
{
XOJ_CHECK_TYPE(AudioElement);
this->timestamp = 0;
XOJ_RELEASE_TYPE(AudioElement);
}
void AudioElement::setAudioFilename(string fn)
{
XOJ_CHECK_TYPE(AudioElement);
this->audioFilename = fn;
}
string AudioElement::getAudioFilename() const
{
XOJ_CHECK_TYPE(AudioElement);
return this->audioFilename;
}
void AudioElement::setTimestamp(size_t timestamp)
{
XOJ_CHECK_TYPE(AudioElement);
this->timestamp = timestamp;
}
size_t AudioElement::getTimestamp() const
{
XOJ_CHECK_TYPE(AudioElement);
return this->timestamp;
}
void AudioElement::serializeAudioElement(ObjectOutputStream& out)
{
XOJ_CHECK_TYPE(AudioElement);
out.writeObject("AudioElement");
serializeElement(out);
out.writeString(this->audioFilename);
out.writeSizeT(this->timestamp);
out.endObject();
}
void AudioElement::readSerializedAudioElement(ObjectInputStream& in)
{
XOJ_CHECK_TYPE(AudioElement);
in.readObject("AudioElement");
readSerializedElement(in);
this->audioFilename = in.readString();
this->timestamp = in.readSizeT();
in.endObject();
}
void AudioElement::cloneAudioData(const AudioElement* other)
{
setAudioFilename(other->getAudioFilename());
setTimestamp(other->getTimestamp());
}

@ -0,0 +1,50 @@
/*
* Xournal++
*
* Element that is audio enabled
*
* @author Xournal++ Team
* https://github.com/xournalpp/xournalpp
*
* @license GNU GPLv2 or later
*/
#pragma once
#include "Element.h"
#include <XournalType.h>
#include <serializing/ObjectInputStream.h>
#include <serializing/ObjectOutputStream.h>
class AudioElement : public Element
{
protected:
AudioElement(ElementType type);
public:
~AudioElement() override;
void setTimestamp(size_t timestamp);
size_t getTimestamp() const;
void setAudioFilename(string fn);
string getAudioFilename() const;
virtual bool intersects(double x, double y, double halfSize) = 0;
virtual bool intersects(double x, double y, double halfSize, double* gap) = 0;
protected:
void serializeAudioElement(ObjectOutputStream& out);
void readSerializedAudioElement(ObjectInputStream& in);
void cloneAudioData(const AudioElement *other);
private:
XOJ_TYPE_ATTRIB;
// Stroke timestamp, to match it to the audio stream
size_t timestamp = 0;
string audioFilename = "";
};

@ -8,7 +8,7 @@
#include <math.h>
Stroke::Stroke()
: Element(ELEMENT_STROKE)
: AudioElement(ELEMENT_STROKE)
{
XOJ_INIT_TYPE(Stroke);
@ -19,8 +19,6 @@ Stroke::Stroke()
this->points = NULL;
this->toolType = STROKE_TOOL_PEN;
this->timestamp = 0;
this->eraseable = NULL;
this->fill = -1;
}
@ -34,8 +32,6 @@ Stroke::~Stroke()
this->pointCount = 0;
this->pointAllocCount = 0;
this->timestamp = 0;
XOJ_RELEASE_TYPE(Stroke);
}
@ -47,10 +43,10 @@ void Stroke::applyStyleFrom(const Stroke* other)
setColor(other->getColor());
setToolType(other->getToolType());
setWidth(other->getWidth());
setAudioFilename(other->getAudioFilename());
setTimestamp(other->getTimestamp());
setFill(other->getFill());
setLineStyle(other->getLineStyle());
cloneAudioData(other);
}
Stroke* Stroke::cloneStroke() const
@ -80,16 +76,12 @@ void Stroke::serialize(ObjectOutputStream& out)
out.writeObject("Stroke");
serializeElement(out);
serializeAudioElement(out);
out.writeDouble(this->width);
out.writeInt(this->toolType);
out.writeString(this->audioFilename);
out.writeSizeT(this->timestamp);
out.writeInt(fill);
out.writeData(this->points, this->pointCount, sizeof(Point));
@ -105,16 +97,12 @@ void Stroke::readSerialized(ObjectInputStream& in)
in.readObject("Stroke");
readSerializedElement(in);
readSerializedAudioElement(in);
this->width = in.readDouble();
this->toolType = (StrokeTool) in.readInt();
this->audioFilename = in.readString();
this->timestamp = in.readSizeT();
this->fill = in.readInt();
g_free(this->points);
@ -127,30 +115,6 @@ void Stroke::readSerialized(ObjectInputStream& in)
in.endObject();
}
void Stroke::setAudioFilename(string fn)
{
this->audioFilename = fn;
}
string Stroke::getAudioFilename() const
{
return this->audioFilename;
}
void Stroke::setTimestamp(size_t seconds)
{
XOJ_CHECK_TYPE(Stroke);
this->timestamp = seconds;
}
size_t Stroke::getTimestamp() const
{
XOJ_CHECK_TYPE(Stroke);
return this->timestamp;
}
/**
* Option to fill the shape:
* -1: The shape is not filled
@ -508,6 +472,16 @@ void Stroke::setPressure(const vector<double>& pressure)
}
}
/**
* split index is the split point, minimimum is 1 NOT 0
*/
bool Stroke::intersects(double x, double y, double halfEraserSize)
{
XOJ_CHECK_TYPE(Stroke);
return intersects(x, y, halfEraserSize, nullptr);
}
/**
* split index is the split point, minimimum is 1 NOT 0
*/

@ -11,9 +11,10 @@
#pragma once
#include "Element.h"
#include "AudioElement.h"
#include "Point.h"
#include "LineStyle.h"
#include "Element.h"
#include <Arrayiterator.h>
@ -24,7 +25,7 @@ enum StrokeTool
class EraseableStroke;
class Stroke : public Element
class Stroke : public AudioElement
{
public:
Stroke();
@ -42,12 +43,6 @@ public:
void setWidth(double width);
double getWidth() const;
void setTimestamp(size_t seconds);
size_t getTimestamp() const;
void setAudioFilename(string fn);
string getAudioFilename() const;
/**
* Option to fill the shape:
* -1: The shape is not filled
@ -85,7 +80,8 @@ public:
const LineStyle& getLineStyle() const;
void setLineStyle(const LineStyle& style);
bool intersects(double x, double y, double halfSize, double* gap = NULL);
bool intersects(double x, double y, double halfSize) override;
bool intersects(double x, double y, double halfSize, double* gap) override;
void setPressure(const vector<double>& pressure);
void setLastPressure(double pressure);
@ -133,10 +129,6 @@ private:
*/
LineStyle lineStyle;
// Stroke timestamp, to match it to the audio stream
size_t timestamp = 0;
string audioFilename;
EraseableStroke* eraseable;
/**

@ -7,7 +7,7 @@
#include <Stacktrace.h>
Text::Text()
: Element(ELEMENT_TEXT)
: AudioElement(ELEMENT_TEXT)
{
XOJ_INIT_TYPE(Text);
@ -31,6 +31,7 @@ Element* Text::clone()
text->setColor(this->getColor());
text->x = this->x;
text->y = this->y;
text->cloneAudioData(this);
return text;
}
@ -136,13 +137,32 @@ bool Text::rescaleOnlyAspectRatio()
return true;
}
bool Text::intersects(double x, double y, double halfEraserSize)
{
XOJ_CHECK_TYPE(Text);
return intersects(x, y, halfEraserSize, nullptr);
}
bool Text::intersects(double x, double y, double halfEraserSize, double* gap)
{
XOJ_CHECK_TYPE(Text);
double x1 = this->x - halfEraserSize;
double x2 = this->x + this->getElementWidth() + halfEraserSize;
double y1 = this->y - halfEraserSize;
double y2 = this->y + this->getElementHeight() + halfEraserSize;
return x >= x1 && x <= x2 && y >= y1 && y <= y2;
}
void Text::serialize(ObjectOutputStream& out)
{
XOJ_CHECK_TYPE(Text);
out.writeObject("Text");
serializeElement(out);
serializeAudioElement(out);
out.writeString(this->text);
@ -157,7 +177,7 @@ void Text::readSerialized(ObjectInputStream& in)
in.readObject("Text");
readSerializedElement(in);
readSerializedAudioElement(in);
this->text = in.readString();

@ -13,10 +13,11 @@
#include "Element.h"
#include "Font.h"
#include "AudioElement.h"
#include <gtk/gtk.h>
class Text : public Element
class Text : public AudioElement
{
public:
Text();
@ -45,6 +46,9 @@ public:
*/
virtual Element* clone();
bool intersects(double x, double y, double halfSize) override;
bool intersects(double x, double y, double halfSize, double* gap) override;
public:
// Serialize interface
void serialize(ObjectOutputStream& out);

@ -277,4 +277,5 @@ XOJ_DECLARE_TYPE(AudioPlayer, 267);
XOJ_DECLARE_TYPE(VorbisConsumer, 268);
XOJ_DECLARE_TYPE(VorbisProducer, 269);
XOJ_DECLARE_TYPE(FullscreenHandler, 270);
XOJ_DECLARE_TYPE(AudioElement, 271);
XOJ_DECLARE_TYPE(XmlAudioNode, 272);

Loading…
Cancel
Save