diff options
author | Dimitri John Ledkov <dimitri.ledkov@canonical.com> | 2014-02-20 16:10:52 +0000 |
---|---|---|
committer | Dimitri John Ledkov <dimitri.ledkov@canonical.com> | 2014-02-20 19:15:57 +0000 |
commit | d20f4a64eba38690337ac914a04a113de7caf125 (patch) | |
tree | 6828990e93ca5d8847b8cde2f2febb6566b0d53f /src/player | |
parent | 28161e9209f21be1a600f637565ecede94855a36 (diff) |
New upstream release. Closes: #721047debian/1.8.0-1
Drop all patches, none are needed with this new upstream release.
Port to dh.
Specify foreign in configure.ac.
Diffstat (limited to 'src/player')
173 files changed, 6858 insertions, 4732 deletions
diff --git a/src/player/AVGNode.cpp b/src/player/AVGNode.cpp index 524bab5..e7c94bc 100644 --- a/src/player/AVGNode.cpp +++ b/src/player/AVGNode.cpp @@ -1,6 +1,6 @@ // // libavg - Media Playback Engine. -// Copyright (C) 2003-2011 Ulrich von Zadow +// Copyright (C) 2003-2014 Ulrich von Zadow // // This library is free software; you can redistribute it and/or // modify it under the terms of the GNU Lesser General Public @@ -22,7 +22,7 @@ #include "AVGNode.h" #include "Player.h" -#include "NodeDefinition.h" +#include "TypeDefinition.h" #include "KeyEvent.h" #include "../base/FileHelper.h" @@ -33,20 +33,17 @@ using namespace std; namespace avg { -NodeDefinition AVGNode::createDefinition() +void AVGNode::registerType() { - return NodeDefinition("avg", Node::buildNode<AVGNode>) - .extendDefinition(CanvasNode::createDefinition()) - .addArg(Arg<string>("onkeyup", "")) - .addArg(Arg<string>("onkeydown", "")); + TypeDefinition def = TypeDefinition("avg", "canvasbase", + ExportedObject::buildObject<AVGNode>); + TypeRegistry::get()->registerType(def); } AVGNode::AVGNode(const ArgList& args) : CanvasNode(args) { args.setMembers(this); - addArgEventHandler(Event::KEYUP, Event::NONE, args.getArgVal<string>("onkeyup")); - addArgEventHandler(Event::KEYDOWN, Event::NONE, args.getArgVal<string>("onkeydown")); } AVGNode::~AVGNode() diff --git a/src/player/AVGNode.h b/src/player/AVGNode.h index ade1f79..fead377 100644 --- a/src/player/AVGNode.h +++ b/src/player/AVGNode.h @@ -1,6 +1,6 @@ // // libavg - Media Playback Engine. -// Copyright (C) 2003-2011 Ulrich von Zadow +// Copyright (C) 2003-2014 Ulrich von Zadow // // This library is free software; you can redistribute it and/or // modify it under the terms of the GNU Lesser General Public @@ -32,7 +32,7 @@ namespace avg { class AVG_API AVGNode : public CanvasNode { public: - static NodeDefinition createDefinition(); + static void registerType(); AVGNode(const ArgList& args); virtual ~AVGNode(); diff --git a/src/player/AppleTrackpadInputDevice.cpp b/src/player/AppleTrackpadInputDevice.cpp index d78e946..63059ae 100644 --- a/src/player/AppleTrackpadInputDevice.cpp +++ b/src/player/AppleTrackpadInputDevice.cpp @@ -1,6 +1,6 @@ // // libavg - Media Playback Engine. -// Copyright (C) 2003-2011 Ulrich von Zadow +// Copyright (C) 2003-2014 Ulrich von Zadow // // This library is free software; you can redistribute it and/or // modify it under the terms of the GNU Lesser General Public @@ -57,27 +57,28 @@ void AppleTrackpadInputDevice::start() m_Device = MTDeviceCreateDefault(); MTRegisterContactFrameCallback(m_Device, callback); MTDeviceStart(m_Device, 0); - AVG_TRACE(Logger::CONFIG, "Apple Trackpad Multitouch event source created."); + AVG_TRACE(Logger::category::CONFIG, Logger::severity::INFO, + "Apple Trackpad Multitouch event source created."); } void AppleTrackpadInputDevice::onData(int device, Finger* pFingers, int numFingers, - double timestamp, int frame) + float timestamp, int frame) { - boost::mutex::scoped_lock lock(getMutex()); + lock_guard lock(getMutex()); for (int i = 0; i < numFingers; i++) { Finger* pFinger = &pFingers[i]; TouchStatusPtr pTouchStatus = getTouchStatus(pFinger->identifier); if (!pTouchStatus) { m_LastID++; - TouchEventPtr pEvent = createEvent(m_LastID, pFinger, Event::CURSORDOWN); + TouchEventPtr pEvent = createEvent(m_LastID, pFinger, Event::CURSOR_DOWN); addTouchStatus(pFinger->identifier, pEvent); } else { Event::Type eventType; if (pFinger->state == 7) { - eventType = Event::CURSORUP; + eventType = Event::CURSOR_UP; removeTouchStatus(pFinger->identifier); } else { - eventType = Event::CURSORMOTION; + eventType = Event::CURSOR_MOTION; } TouchEventPtr pEvent = createEvent(0, pFinger, eventType); pTouchStatus->pushEvent(pEvent); @@ -96,13 +97,14 @@ int AppleTrackpadInputDevice::callback(int device, Finger *data, int nFingers, TouchEventPtr AppleTrackpadInputDevice::createEvent(int avgID, Finger* pFinger, Event::Type eventType) { - DPoint size = getWindowSize(); - IntPoint pos(pFinger->normalized.pos.x*size.x, (1-pFinger->normalized.pos.y)*size.y); - DPoint speed(pFinger->normalized.vel.x*size.x, pFinger->normalized.vel.y*size.y); - double eccentricity = pFinger->majorAxis/pFinger->minorAxis; - DPoint majorAxis = DPoint::fromPolar(pFinger->angle, pFinger->majorAxis); + glm::vec2 size = getTouchArea(); + IntPoint pos = getScreenPos(glm::vec2(pFinger->normalized.pos.x, + 1-pFinger->normalized.pos.y)); + glm::vec2 speed(pFinger->normalized.vel.x*size.x, pFinger->normalized.vel.y*size.y); + float eccentricity = pFinger->majorAxis/pFinger->minorAxis; + glm::vec2 majorAxis = fromPolar(pFinger->angle, pFinger->majorAxis); majorAxis.y = -majorAxis.y; - DPoint minorAxis = DPoint::fromPolar(pFinger->angle+1.57, pFinger->minorAxis); + glm::vec2 minorAxis = fromPolar(pFinger->angle+1.57, pFinger->minorAxis); minorAxis.y = -minorAxis.y; TouchEventPtr pEvent(new TouchEvent(avgID, eventType, pos, Event::TOUCH, diff --git a/src/player/AreaNode.cpp b/src/player/AreaNode.cpp index 64e2ae8..b09f4a6 100644 --- a/src/player/AreaNode.cpp +++ b/src/player/AreaNode.cpp @@ -1,6 +1,6 @@ // // libavg - Media Playback Engine. -// Copyright (C) 2003-2011 Ulrich von Zadow +// Copyright (C) 2003-2014 Ulrich von Zadow // // This library is free software; you can redistribute it and/or // modify it under the terms of the GNU Lesser General Public @@ -26,7 +26,8 @@ #include "MouseEvent.h" #include "DivNode.h" #include "ArgList.h" -#include "NodeDefinition.h" +#include "TypeDefinition.h" +#include "TypeRegistry.h" #include "BoostPython.h" #include "../base/MathHelper.h" @@ -43,29 +44,32 @@ #include <iostream> using namespace boost; -using namespace boost::python; using namespace std; namespace avg { -NodeDefinition AreaNode::createDefinition() +void AreaNode::registerType() { - return NodeDefinition("areanode") - .extendDefinition(Node::createDefinition()) - .addArg(Arg<double>("x", 0.0, false, offsetof(AreaNode, m_RelViewport.tl.x))) - .addArg(Arg<double>("y", 0.0, false, offsetof(AreaNode, m_RelViewport.tl.y))) - .addArg(Arg<DPoint>("pos", DPoint(0.0, 0.0))) - .addArg(Arg<double>("width", 0.0, false, offsetof(AreaNode, m_UserSize.x))) - .addArg(Arg<double>("height", 0.0, false, offsetof(AreaNode, m_UserSize.y))) - .addArg(Arg<DPoint>("size", DPoint(0.0, 0.0))) - .addArg(Arg<double>("angle", 0.0, false, offsetof(AreaNode, m_Angle))) - .addArg(Arg<DPoint>("pivot", DPoint(-32767, -32767), false, - offsetof(AreaNode, m_Pivot))); + TypeDefinition def = TypeDefinition("areanode", "node") + .addArg(Arg<float>("x", 0.0, false, offsetof(AreaNode, m_RelViewport.tl.x))) + .addArg(Arg<float>("y", 0.0, false, offsetof(AreaNode, m_RelViewport.tl.y))) + .addArg(Arg<glm::vec2>("pos", glm::vec2(0.0, 0.0))) + .addArg(Arg<float>("width", 0.0, false, offsetof(AreaNode, m_UserSize.x))) + .addArg(Arg<float>("height", 0.0, false, offsetof(AreaNode, m_UserSize.y))) + .addArg(Arg<glm::vec2>("size", glm::vec2(0.0, 0.0))) + .addArg(Arg<float>("angle", 0.0, false, offsetof(AreaNode, m_Angle))) + .addArg(Arg<glm::vec2>("pivot", glm::vec2(-32767, -32767), false, + offsetof(AreaNode, m_Pivot))) + .addArg(Arg<string>("elementoutlinecolor", "", false, + offsetof(AreaNode, m_sElementOutlineColor))); + TypeRegistry::get()->registerType(def); } AreaNode::AreaNode() - : m_RelViewport(0,0,0,0) + : m_RelViewport(0,0,0,0), + m_Transform(glm::mat4(0)), + m_bTransformChanged(true) { ObjectCounter::get()->incRef(&typeid(*this)); } @@ -83,170 +87,202 @@ void AreaNode::setArgs(const ArgList& args) m_RelViewport.setWidth(m_UserSize.x); m_RelViewport.setHeight(m_UserSize.y); m_bHasCustomPivot = ((m_Pivot.x != -32767) && (m_Pivot.y != -32767)); + setElementOutlineColor(m_sElementOutlineColor); } void AreaNode::connectDisplay() { IntPoint MediaSize = getMediaSize(); if (m_UserSize.x == 0.0) { - m_RelViewport.setWidth(MediaSize.x); + m_RelViewport.setWidth(float(MediaSize.x)); } else { - m_RelViewport.setWidth(m_UserSize.x); + m_RelViewport.setWidth(float(m_UserSize.x)); } if (m_UserSize.y == 0.0) { - m_RelViewport.setHeight(MediaSize.y); + m_RelViewport.setHeight(float(MediaSize.y)); } else { - m_RelViewport.setHeight(m_UserSize.y); + m_RelViewport.setHeight(float(m_UserSize.y)); } + if (m_UserSize.x == 0.0 || m_UserSize.y == 0) { + notifySubscribers("SIZE_CHANGED", m_RelViewport.size()); + } + m_bTransformChanged = true; Node::connectDisplay(); } -double AreaNode::getX() const +float AreaNode::getX() const { return m_RelViewport.tl.x; } -void AreaNode::setX(double x) +void AreaNode::setX(float x) { setViewport(x, -32767, -32767, -32767); } -double AreaNode::getY() const +float AreaNode::getY() const { return m_RelViewport.tl.y; } -void AreaNode::setY(double y) +void AreaNode::setY(float y) { setViewport(-32767, y, -32767, -32767); } -const DPoint& AreaNode::getPos() const +const glm::vec2& AreaNode::getPos() const { return m_RelViewport.tl; } -void AreaNode::setPos(const DPoint& pt) +void AreaNode::setPos(const glm::vec2& pt) { setViewport(pt.x, pt.y, -32767, -32767); } -double AreaNode::getWidth() const +float AreaNode::getWidth() const { return getRelViewport().width(); } -void AreaNode::setWidth(double width) +void AreaNode::setWidth(float width) { m_UserSize.x = width; setViewport(-32767, -32767, -32767, -32767); } -double AreaNode::getHeight() const +float AreaNode::getHeight() const { return getRelViewport().height(); } -void AreaNode::setHeight(double height) +void AreaNode::setHeight(float height) { m_UserSize.y = height; setViewport(-32767, -32767, -32767, -32767); } -DPoint AreaNode::getSize() const +glm::vec2 AreaNode::getSize() const { return getRelViewport().size(); } -void AreaNode::setSize(const DPoint& pt) +void AreaNode::setSize(const glm::vec2& pt) { m_UserSize = pt; setViewport(-32767, -32767, -32767, -32767); } -double AreaNode::getAngle() const +float AreaNode::getAngle() const { return m_Angle; } -void AreaNode::setAngle(double angle) +void AreaNode::setAngle(float angle) { - m_Angle = fmod(angle, 2*M_PI); + m_Angle = fmod(angle, 2*PI); + m_bTransformChanged = true; } -DPoint AreaNode::getPivot() const +glm::vec2 AreaNode::getPivot() const { if (m_bHasCustomPivot) { return m_Pivot; } else { - return getSize()/2; + return getSize()/2.f; } } -void AreaNode::setPivot(const DPoint& pt) +void AreaNode::setPivot(const glm::vec2& pt) { m_Pivot.x = pt.x; m_Pivot.y = pt.y; m_bHasCustomPivot = true; + m_bTransformChanged = true; +} + +const std::string& AreaNode::getElementOutlineColor() const +{ + return m_sElementOutlineColor; +} + +void AreaNode::setElementOutlineColor(const std::string& sColor) +{ + m_sElementOutlineColor = sColor; + if (sColor == "") { + m_ElementOutlineColor = Pixel32(0,0,0,0); + } else { + m_ElementOutlineColor = colorStringToColor(m_sElementOutlineColor); + } } -DPoint AreaNode::toLocal(const DPoint& globalPos) const +glm::vec2 AreaNode::toLocal(const glm::vec2& globalPos) const { - DPoint localPos = globalPos-m_RelViewport.tl; - return localPos.getRotatedPivot(-getAngle(), getPivot()); + glm::vec2 localPos = globalPos-m_RelViewport.tl; + return getRotatedPivot(localPos, -getAngle(), getPivot()); } -DPoint AreaNode::toGlobal(const DPoint& localPos) const +glm::vec2 AreaNode::toGlobal(const glm::vec2& localPos) const { - DPoint globalPos = localPos.getRotatedPivot(getAngle(), getPivot()); + glm::vec2 globalPos = getRotatedPivot(localPos, getAngle(), getPivot()); return globalPos+m_RelViewport.tl; } -void AreaNode::getElementsByPos(const DPoint& pos, vector<NodeWeakPtr>& pElements) +void AreaNode::getElementsByPos(const glm::vec2& pos, vector<NodePtr>& pElements) { if (pos.x >= 0 && pos.y >= 0 && pos.x < getSize().x && pos.y < getSize().y && reactsToMouseEvents()) { - pElements.push_back(shared_from_this()); + pElements.push_back(getSharedThis()); } } -void AreaNode::maybeRender(const DRect& rect) +void AreaNode::maybeRender(const glm::mat4& parentTransform) { AVG_ASSERT(getState() == NS_CANRENDER); if (isVisible()) { - if (getID() != "") { - AVG_TRACE(Logger::BLTS, "Rendering " << getTypeStr() << - " with ID " << getID()); - } else { - AVG_TRACE(Logger::BLTS, "Rendering " << getTypeStr()); - } - GLContext * pContext = GLContext::getCurrent(); - pContext->pushTransform(getRelViewport().tl, getAngle(), getPivot()); - render(rect); - pContext->popTransform(); + calcTransform(); + m_Transform = parentTransform*m_LocalTransform; + render(); + } +} + +void AreaNode::renderOutlines(const VertexArrayPtr& pVA, Pixel32 parentColor) +{ + Pixel32 effColor = getEffectiveOutlineColor(parentColor); + if (effColor != Pixel32(0,0,0,0)) { + glm::vec2 size = getSize(); + glm::vec2 p0 = getAbsPos(glm::vec2(0.5, 0.5)); + glm::vec2 p1 = getAbsPos(glm::vec2(size.x+0.5,0.5)); + glm::vec2 p2 = getAbsPos(glm::vec2(size.x+0.5,size.y+0.5)); + glm::vec2 p3 = getAbsPos(glm::vec2(0.5,size.y+0.5)); + pVA->addLineData(effColor, p0, p1, 1); + pVA->addLineData(effColor, p1, p2, 1); + pVA->addLineData(effColor, p2, p3, 1); + pVA->addLineData(effColor, p3, p0, 1); } } -void AreaNode::setViewport(double x, double y, double width, double height) +void AreaNode::setViewport(float x, float y, float width, float height) { + glm::vec2 oldSize = getRelViewport().size(); if (x == -32767) { x = getRelViewport().tl.x; } if (y == -32767) { y = getRelViewport().tl.y; } - IntPoint MediaSize = getMediaSize(); + glm::vec2 mediaSize = glm::vec2(getMediaSize()); if (width == -32767) { if (m_UserSize.x == 0.0) { - width = MediaSize.x; + width = mediaSize.x; } else { width = m_UserSize.x; } } if (height == -32767) { if (m_UserSize.y == 0.0) { - height = MediaSize.y; + height = mediaSize.y; } else { height = m_UserSize.y; } @@ -254,10 +290,14 @@ void AreaNode::setViewport(double x, double y, double width, double height) if (width < 0 || height < 0) { throw Exception(AVG_ERR_OUT_OF_RANGE, "Negative size for a node."); } - m_RelViewport = DRect (x, y, x+width, y+height); + m_RelViewport = FRect(x, y, x+width, y+height); + if (oldSize != m_RelViewport.size()) { + notifySubscribers("SIZE_CHANGED", m_RelViewport.size()); + } + m_bTransformChanged = true; } -const DRect& AreaNode::getRelViewport() const +const FRect& AreaNode::getRelViewport() const { // cerr << "Node " << getID() << ": " << m_RelViewport << endl; return m_RelViewport; @@ -275,9 +315,36 @@ string AreaNode::dump(int indent) return dumpStr; } -DPoint AreaNode::getUserSize() const +const glm::mat4& AreaNode::getTransform() const +{ + return m_Transform; +} + +glm::vec2 AreaNode::getUserSize() const { return m_UserSize; } +Pixel32 AreaNode::getEffectiveOutlineColor(Pixel32 parentColor) const +{ + if (m_ElementOutlineColor == Pixel32(0,0,0,0)) { + return parentColor; + } else { + return m_ElementOutlineColor; + } +} + +void AreaNode::calcTransform() +{ + if (m_bTransformChanged) { + glm::vec3 pos(m_RelViewport.tl.x, m_RelViewport.tl.y, 0); + glm::vec3 pivot(getPivot().x, getPivot().y, 0); + glm::mat4 transform = glm::translate(glm::mat4(1.0f), pos); + transform = glm::translate(transform, pivot); + transform = glm::rotate(transform, (180.f/PI)*m_Angle, glm::vec3(0,0,1)); + m_LocalTransform = glm::translate(transform, -pivot); + m_bTransformChanged = false; + } +} + } diff --git a/src/player/AreaNode.h b/src/player/AreaNode.h index 65bb3bf..7a65c52 100644 --- a/src/player/AreaNode.h +++ b/src/player/AreaNode.h @@ -1,6 +1,6 @@ // // libavg - Media Playback Engine. -// Copyright (C) 2003-2011 Ulrich von Zadow +// Copyright (C) 2003-2014 Ulrich von Zadow // // This library is free software; you can redistribute it and/or // modify it under the terms of the GNU Lesser General Public @@ -26,7 +26,7 @@ #include "Node.h" -#include "../base/Point.h" +#include "../base/GLMHelper.h" #include "../base/Rect.h" #include "../graphics/OGLShader.h" @@ -44,9 +44,6 @@ class DivNode; class ArgList; typedef boost::shared_ptr<AreaNode> AreaNodePtr; -typedef boost::weak_ptr<AreaNode> AreaNodeWeakPtr; -typedef boost::shared_ptr<DivNode> DivNodePtr; -typedef boost::weak_ptr<DivNode> DivNodeWeakPtr; class AVG_API AreaNode: public Node { @@ -56,45 +53,49 @@ class AVG_API AreaNode: public Node { return NodePtr(new NodeType(args)); } - static NodeDefinition createDefinition(); + static void registerType(); virtual ~AreaNode() = 0; virtual void setArgs(const ArgList& args); virtual void connectDisplay(); - double getX() const; - void setX(double x); + float getX() const; + void setX(float x); - double getY() const; - void setY(double Y); + float getY() const; + void setY(float Y); - const DPoint& getPos() const; - void setPos(const DPoint& pt); + const glm::vec2& getPos() const; + void setPos(const glm::vec2& pt); - virtual double getWidth() const; - virtual void setWidth(double width); + virtual float getWidth() const; + virtual void setWidth(float width); - virtual double getHeight() const; - virtual void setHeight(double height); + virtual float getHeight() const; + virtual void setHeight(float height); - virtual DPoint getSize() const; - virtual void setSize(const DPoint& pt); + virtual glm::vec2 getSize() const; + virtual void setSize(const glm::vec2& pt); - double getAngle() const; - void setAngle(double angle); + float getAngle() const; + void setAngle(float angle); - virtual DPoint getPivot() const; - void setPivot(const DPoint& pt); + virtual glm::vec2 getPivot() const; + void setPivot(const glm::vec2& pt); - virtual DPoint toLocal(const DPoint& globalPos) const; - virtual DPoint toGlobal(const DPoint& localPos) const; + const std::string& getElementOutlineColor() const; + void setElementOutlineColor(const std::string& sColor); + + virtual glm::vec2 toLocal(const glm::vec2& globalPos) const; + virtual glm::vec2 toGlobal(const glm::vec2& localPos) const; - virtual void getElementsByPos(const DPoint& pos, - std::vector<NodeWeakPtr>& pElements); + virtual void getElementsByPos(const glm::vec2& pos, + std::vector<NodePtr>& pElements); - virtual void maybeRender(const DRect& rect); - virtual void setViewport(double x, double y, double width, double height); - virtual const DRect& getRelViewport() const; + virtual void maybeRender(const glm::mat4& parentTransform); + virtual void renderOutlines(const VertexArrayPtr& pVA, Pixel32 parentColor); + virtual void setViewport(float x, float y, float width, float height); + virtual const FRect& getRelViewport() const; virtual std::string dump(int indent = 0); @@ -102,18 +103,27 @@ class AVG_API AreaNode: public Node virtual IntPoint getMediaSize() { return IntPoint(0,0); }; + const glm::mat4& getTransform() const; protected: AreaNode(); - DPoint getUserSize() const; + glm::vec2 getUserSize() const; + Pixel32 getEffectiveOutlineColor(Pixel32 parentColor) const; private: - DRect m_RelViewport; // In coordinates relative to the parent. - double m_Angle; - DPoint m_Pivot; + void calcTransform(); + + FRect m_RelViewport; // In coordinates relative to the parent. + float m_Angle; + glm::vec2 m_Pivot; bool m_bHasCustomPivot; + std::string m_sElementOutlineColor; + Pixel32 m_ElementOutlineColor; - DPoint m_UserSize; + glm::vec2 m_UserSize; + glm::mat4 m_Transform; + glm::mat4 m_LocalTransform; + bool m_bTransformChanged; }; } diff --git a/src/player/Arg.cpp b/src/player/Arg.cpp index 6bb7fbb..1518164 100644 --- a/src/player/Arg.cpp +++ b/src/player/Arg.cpp @@ -1,6 +1,6 @@ // // libavg - Media Playback Engine. -// Copyright (C) 2003-2011 Ulrich von Zadow +// Copyright (C) 2003-2014 Ulrich von Zadow // // This library is free software; you can redistribute it and/or // modify it under the terms of the GNU Lesser General Public @@ -22,6 +22,8 @@ // #include "Arg.h" +#include "FontStyle.h" + #include <string> using namespace std; @@ -31,14 +33,15 @@ namespace avg { #ifndef _WIN32 template class Arg<int>; template class Arg<bool>; -template class Arg<double>; template class Arg<float>; template class Arg<string>; -template class Arg<DPoint>; -template class Arg<IntTriple>; -template class Arg<DTriple>; -template class Arg<vector<double> >; -template class Arg<vector<DPoint> >; -template class Arg<vector<IntTriple> >; +template class Arg<glm::vec2>; +template class Arg<glm::vec3>; +template class Arg<glm::ivec3>; +template class Arg<std::vector<float> >; +template class Arg<std::vector<int> >; +template class Arg<vector<glm::vec2> >; +template class Arg<vector<glm::ivec3> >; +template class Arg<FontStyle>; #endif } diff --git a/src/player/Arg.h b/src/player/Arg.h index a48e86f..be441e3 100644 --- a/src/player/Arg.h +++ b/src/player/Arg.h @@ -1,6 +1,6 @@ // // libavg - Media Playback Engine. -// Copyright (C) 2003-2011 Ulrich von Zadow +// Copyright (C) 2003-2014 Ulrich von Zadow // // This library is free software; you can redistribute it and/or // modify it under the terms of the GNU Lesser General Public @@ -25,8 +25,7 @@ #define _Arg_H_ #include "../api.h" -#include "../base/Point.h" -#include "../base/Triple.h" +#include "../base/GLMHelper.h" #include "ArgBase.h" @@ -35,7 +34,7 @@ namespace avg { -class Node; +class ExportedObject; template<class T> class AVG_TEMPLATE_API Arg: public ArgBase @@ -47,7 +46,7 @@ public: void setValue(const T& Value); const T& getValue() const; - virtual void setMember(Node * pNode) const; + virtual void setMember(ExportedObject * pObj) const; virtual ArgBase* createCopy() const; private: @@ -81,10 +80,10 @@ void Arg<T>::setValue(const T& Value) } template<class T> -void Arg<T>::setMember(Node * pNode) const +void Arg<T>::setMember(ExportedObject * pObj) const { if (getMemberOffset() != -1) { - T* pMember = (T*)((char*)pNode+getMemberOffset()); + T* pMember = (T*)((char*)pObj+getMemberOffset()); *pMember = m_Value; } } @@ -103,14 +102,14 @@ ArgBase* Arg<T>::createCopy() const extern template class Arg<int>; extern template class Arg<bool>; extern template class Arg<float>; -extern template class Arg<double>; extern template class Arg<std::string>; -extern template class Arg<DPoint>; -extern template class Arg<IntTriple>; -extern template class Arg<DTriple>; -extern template class Arg<std::vector<double> >; -extern template class Arg<std::vector<DPoint> >; -extern template class Arg<std::vector<IntTriple> >; +extern template class Arg<glm::vec2>; +extern template class Arg<glm::vec3>; +extern template class Arg<glm::ivec3>; +extern template class Arg<std::vector<float> >; +extern template class Arg<std::vector<int> >; +extern template class Arg<std::vector<glm::vec2> >; +extern template class Arg<std::vector<glm::ivec2> >; #endif #endif diff --git a/src/player/ArgBase.cpp b/src/player/ArgBase.cpp index 1c4882d..9409f45 100644 --- a/src/player/ArgBase.cpp +++ b/src/player/ArgBase.cpp @@ -1,6 +1,6 @@ // // libavg - Media Playback Engine. -// Copyright (C) 2003-2011 Ulrich von Zadow +// Copyright (C) 2003-2014 Ulrich von Zadow // // This library is free software; you can redistribute it and/or // modify it under the terms of the GNU Lesser General Public diff --git a/src/player/ArgBase.h b/src/player/ArgBase.h index c6017f2..fff8969 100644 --- a/src/player/ArgBase.h +++ b/src/player/ArgBase.h @@ -1,6 +1,6 @@ // // libavg - Media Playback Engine. -// Copyright (C) 2003-2011 Ulrich von Zadow +// Copyright (C) 2003-2014 Ulrich von Zadow // // This library is free software; you can redistribute it and/or // modify it under the terms of the GNU Lesser General Public @@ -32,7 +32,7 @@ namespace avg { -class Node; +class ExportedObject; class AVG_API ArgBase { @@ -44,7 +44,7 @@ public: bool isDefault() const; bool isRequired() const; - virtual void setMember(Node * pNode) const = 0; + virtual void setMember(ExportedObject * pObj) const = 0; virtual ArgBase* createCopy() const = 0; diff --git a/src/player/ArgList.cpp b/src/player/ArgList.cpp index 15b5ce3..5abe78c 100644 --- a/src/player/ArgList.cpp +++ b/src/player/ArgList.cpp @@ -1,6 +1,6 @@ // // libavg - Media Playback Engine. -// Copyright (C) 2003-2011 Ulrich von Zadow +// Copyright (C) 2003-2014 Ulrich von Zadow // // This library is free software; you can redistribute it and/or // modify it under the terms of the GNU Lesser General Public @@ -23,7 +23,8 @@ #include "ArgList.h" -#include "Node.h" +#include "ExportedObject.h" +#include "FontStyle.h" #include "../base/Logger.h" #include "../base/Exception.h" @@ -36,6 +37,8 @@ using namespace std; namespace avg { +typedef std::vector<std::vector<glm::vec2> > CollVec2Vector; + ArgList::ArgList() { } @@ -52,18 +55,18 @@ ArgList::ArgList(const ArgList& argTemplates, const xmlNodePtr xmlNode) } } -ArgList::ArgList(const ArgList& argTemplates, const boost::python::dict& PyDict) +ArgList::ArgList(const ArgList& argTemplates, const py::dict& PyDict) { // TODO: Check if all required args are being set. copyArgsFrom(argTemplates); - boost::python::list keys = PyDict.keys(); - int nKeys = boost::python::len(keys); + py::list keys = PyDict.keys(); + int nKeys = py::len(keys); for (int i = 0; i < nKeys; i++) { - boost::python::object keyObj = keys[i]; - boost::python::object valObj = PyDict[keyObj]; + py::object keyObj = keys[i]; + py::object valObj = PyDict[keyObj]; - boost::python::extract<string> keyStrProxy(keyObj); + py::extract<string> keyStrProxy(keyObj); if (!keyStrProxy.check()) { throw Exception(AVG_ERR_INVALID_ARGS, "Argument name must be a string."); } @@ -93,7 +96,7 @@ const ArgBasePtr ArgList::getArg(const string& sName) const return valIt->second; } -void ArgList::getOverlayedArgVal(DPoint* pResult, const string& sName, +void ArgList::getOverlayedArgVal(glm::vec2* pResult, const string& sName, const string& sOverlay1, const string& sOverlay2, const string& sID) const { if (hasArg(sName)) { @@ -102,7 +105,7 @@ void ArgList::getOverlayedArgVal(DPoint* pResult, const string& sName, string("Duplicate node arguments (")+sName+" and "+ sOverlay1+","+sOverlay2+") for node '"+sID+"'")); } - *pResult = getArgVal<DPoint>(sName); + *pResult = getArgVal<glm::vec2>(sName); } } @@ -113,7 +116,7 @@ const ArgMap& ArgList::getArgMap() const void ArgList::setArg(const ArgBase& newArg) { - m_Args.insert(ArgMap::value_type(newArg.getName(), ArgBasePtr(newArg.createCopy()))); + m_Args[newArg.getName()] = ArgBasePtr(newArg.createCopy()); } void ArgList::setArgs(const ArgList& args) @@ -123,20 +126,19 @@ void ArgList::setArgs(const ArgList& args) } } -void ArgList::setMembers(Node * pNode) const +void ArgList::setMembers(ExportedObject * pObj) const { for (ArgMap::const_iterator it = m_Args.begin(); it != m_Args.end(); it++) { const ArgBasePtr pCurArg = it->second; - pCurArg->setMember(pNode); + pCurArg->setMember(pObj); } - pNode->setArgs(*this); + pObj->setArgs(*this); } template<class T> -void setArgValue(Arg<T>* pArg, const std::string & sName, - const boost::python::object& value) +void setArgValue(Arg<T>* pArg, const std::string & sName, const py::object& value) { - boost::python::extract<T> valProxy(value); + py::extract<T> valProxy(value); if (!valProxy.check()) { string sTypeName = getFriendlyTypeName(pArg->getValue()); throw Exception(AVG_ERR_INVALID_ARGS, "Type error in argument "+sName+": " @@ -145,47 +147,57 @@ void setArgValue(Arg<T>* pArg, const std::string & sName, pArg->setValue(valProxy()); } -void ArgList::setArgValue(const std::string & sName, const boost::python::object& value) +void ArgList::setArgValue(const std::string & sName, const py::object& value) { ArgBasePtr pArg = getArg(sName); Arg<string>* pStringArg = dynamic_cast<Arg<string>* >(&*pArg); Arg<UTF8String>* pUTF8StringArg = dynamic_cast<Arg<UTF8String>* >(&*pArg); Arg<int>* pIntArg = dynamic_cast<Arg<int>* >(&*pArg); - Arg<double>* pDoubleArg = dynamic_cast<Arg<double>* >(&*pArg); Arg<float>* pFloatArg = dynamic_cast<Arg<float>* >(&*pArg); Arg<bool>* pBoolArg = dynamic_cast<Arg<bool>* >(&*pArg); - Arg<DPoint>* pDPointArg = dynamic_cast<Arg<DPoint>* >(&*pArg); - Arg<IntTriple>* pIntTripleArg = dynamic_cast<Arg<IntTriple>* >(&*pArg); - Arg<DTriple>* pDTripleArg = dynamic_cast<Arg<DTriple>* >(&*pArg); - Arg<vector<double> >* pDVectorArg = dynamic_cast<Arg<vector<double> >* >(&*pArg); - Arg<vector<DPoint> >* pDPointVectorArg = - dynamic_cast<Arg<vector<DPoint> >* >(&*pArg); - Arg<vector<IntTriple> >* pIntTripleVectorArg = - dynamic_cast<Arg<vector<IntTriple> >* >(&*pArg); + Arg<glm::vec2>* pVec2Arg = dynamic_cast<Arg<glm::vec2>* >(&*pArg); + Arg<glm::vec3>* pVec3Arg = dynamic_cast<Arg<glm::vec3>* >(&*pArg); + Arg<glm::ivec3>* pIVec3Arg = dynamic_cast<Arg<glm::ivec3>* >(&*pArg); + Arg<vector<float> >* pFVectorArg = dynamic_cast<Arg<vector<float> >* >(&*pArg); + Arg<vector<int> >* pIVectorArg = dynamic_cast<Arg<vector<int> >* >(&*pArg); + Arg<vector<glm::vec2> >* pVec2VectorArg = + dynamic_cast<Arg<vector<glm::vec2> >* >(&*pArg); + Arg<vector<glm::ivec3> >* pIVec3VectorArg = + dynamic_cast<Arg<vector<glm::ivec3> >* >(&*pArg); + Arg<CollVec2Vector>* pCollVec2VectorArg = + dynamic_cast<Arg<CollVec2Vector>* >(&*pArg); + Arg<FontStyle>* pFontStyleArg = dynamic_cast<Arg<FontStyle>* >(&*pArg); + Arg<FontStylePtr>* pFontStylePtrArg = dynamic_cast<Arg<FontStylePtr>* >(&*pArg); if(pStringArg) { avg::setArgValue(pStringArg, sName, value); } else if (pUTF8StringArg) { avg::setArgValue(pUTF8StringArg, sName, value); } else if (pIntArg) { avg::setArgValue(pIntArg, sName, value); - } else if (pDoubleArg) { - avg::setArgValue(pDoubleArg, sName, value); } else if (pFloatArg) { avg::setArgValue(pFloatArg, sName, value); } else if (pBoolArg) { avg::setArgValue(pBoolArg, sName, value); - } else if (pDPointArg) { - avg::setArgValue(pDPointArg, sName, value); - } else if (pDVectorArg) { - avg::setArgValue(pDVectorArg, sName, value); - } else if (pDPointVectorArg) { - avg::setArgValue(pDPointVectorArg, sName, value); - } else if (pIntTripleArg) { - avg::setArgValue(pIntTripleArg, sName, value); - } else if (pDTripleArg) { - avg::setArgValue(pDTripleArg, sName, value); - } else if (pIntTripleVectorArg) { - avg::setArgValue(pIntTripleVectorArg, sName, value); + } else if (pVec2Arg) { + avg::setArgValue(pVec2Arg, sName, value); + } else if (pVec3Arg) { + avg::setArgValue(pVec3Arg, sName, value); + } else if (pIVec3Arg) { + avg::setArgValue(pIVec3Arg, sName, value); + } else if (pFVectorArg) { + avg::setArgValue(pFVectorArg, sName, value); + } else if (pIVectorArg) { + avg::setArgValue(pIVectorArg, sName, value); + } else if (pVec2VectorArg) { + avg::setArgValue(pVec2VectorArg, sName, value); + } else if (pIVec3VectorArg) { + avg::setArgValue(pIVec3VectorArg, sName, value); + } else if (pCollVec2VectorArg) { + avg::setArgValue(pCollVec2VectorArg, sName, value); + } else if (pFontStyleArg) { + avg::setArgValue(pFontStyleArg, sName, value); + } else if (pFontStylePtrArg) { + avg::setArgValue(pFontStylePtrArg, sName, value); } else { AVG_ASSERT(false); } @@ -197,45 +209,55 @@ void ArgList::setArgValue(const std::string & sName, const std::string & sValue) Arg<string>* pStringArg = dynamic_cast<Arg<string>* >(&*pArg); Arg<UTF8String>* pUTF8StringArg = dynamic_cast<Arg<UTF8String>* >(&*pArg); Arg<int>* pIntArg = dynamic_cast<Arg<int>* >(&*pArg); - Arg<double>* pDoubleArg = dynamic_cast<Arg<double>* >(&*pArg); Arg<float>* pFloatArg = dynamic_cast<Arg<float>* >(&*pArg); Arg<bool>* pBoolArg = dynamic_cast<Arg<bool>* >(&*pArg); - Arg<DPoint>* pDPointArg = dynamic_cast<Arg<DPoint>* >(&*pArg); - Arg<IntTriple>* pIntTripleArg = dynamic_cast<Arg<IntTriple>* >(&*pArg); - Arg<vector<double> >* pDVectorArg = dynamic_cast<Arg<vector<double> >* >(&*pArg); - Arg<vector<DPoint> >* pDPointVectorArg = - dynamic_cast<Arg<vector<DPoint> >* >(&*pArg); - Arg<vector<IntTriple> >* pIntTripleVectorArg = - dynamic_cast<Arg<vector<IntTriple> >* >(&*pArg); - + Arg<glm::vec2>* pVec2Arg = dynamic_cast<Arg<glm::vec2>* >(&*pArg); + Arg<glm::vec3>* pVec3Arg = dynamic_cast<Arg<glm::vec3>* >(&*pArg); + Arg<glm::ivec3>* pIVec3Arg = dynamic_cast<Arg<glm::ivec3>* >(&*pArg); + Arg<vector<float> >* pFVectorArg = dynamic_cast<Arg<vector<float> >* >(&*pArg); + Arg<vector<int> >* pIVectorArg = dynamic_cast<Arg<vector<int> >* >(&*pArg); + Arg<vector<glm::vec2> >* pVec2VectorArg = + dynamic_cast<Arg<vector<glm::vec2> >* >(&*pArg); + Arg<vector<glm::ivec3> >* pIVec3VectorArg = + dynamic_cast<Arg<vector<glm::ivec3> >* >(&*pArg); + Arg<CollVec2Vector>* pCollVec2VectorArg = + dynamic_cast<Arg<CollVec2Vector>* >(&*pArg); if (pStringArg) { pStringArg->setValue(sValue); } else if (pUTF8StringArg) { pUTF8StringArg->setValue(sValue); } else if (pIntArg) { pIntArg->setValue(stringToInt(sValue)); - } else if (pDoubleArg) { - pDoubleArg->setValue(stringToDouble(sValue)); } else if (pFloatArg) { - pFloatArg->setValue(float(stringToDouble(sValue))); + pFloatArg->setValue(stringToFloat(sValue)); } else if (pBoolArg) { pBoolArg->setValue(stringToBool(sValue)); - } else if (pDPointArg) { - pDPointArg->setValue(stringToDPoint(sValue)); - } else if (pIntTripleArg) { - pIntTripleArg->setValue(stringToIntTriple(sValue)); - } else if (pDVectorArg) { - vector<double> v; + } else if (pVec2Arg) { + pVec2Arg->setValue(stringToVec2(sValue)); + } else if (pVec3Arg) { + pVec3Arg->setValue(stringToVec3(sValue)); + } else if (pIVec3Arg) { + pIVec3Arg->setValue(stringToIVec3(sValue)); + } else if (pFVectorArg) { + vector<float> v; + fromString(sValue, v); + pFVectorArg->setValue(v); + } else if (pIVectorArg) { + vector<int> v; + fromString(sValue, v); + pIVectorArg->setValue(v); + } else if (pVec2VectorArg) { + vector<glm::vec2> v; fromString(sValue, v); - pDVectorArg->setValue(v); - } else if (pDPointVectorArg) { - vector<DPoint> v; + pVec2VectorArg->setValue(v); + } else if (pIVec3VectorArg) { + vector<glm::ivec3> v; fromString(sValue, v); - pDPointVectorArg->setValue(v); - } else if (pIntTripleVectorArg) { - vector<IntTriple> v; + pIVec3VectorArg->setValue(v); + } else if (pCollVec2VectorArg) { + CollVec2Vector v; fromString(sValue, v); - pIntTripleVectorArg->setValue(v); + pCollVec2VectorArg->setValue(v); } else { AVG_ASSERT(false); } diff --git a/src/player/ArgList.h b/src/player/ArgList.h index d04b1d4..5f78114 100644 --- a/src/player/ArgList.h +++ b/src/player/ArgList.h @@ -1,6 +1,6 @@ // // libavg - Media Playback Engine. -// Copyright (C) 2003-2011 Ulrich von Zadow +// Copyright (C) 2003-2014 Ulrich von Zadow // // This library is free software; you can redistribute it and/or // modify it under the terms of the GNU Lesser General Public @@ -38,14 +38,14 @@ namespace avg { typedef std::map<std::string, ArgBasePtr> ArgMap; -class Node; +class ExportedObject; class AVG_API ArgList { public: ArgList(); ArgList(const ArgList& argTemplates, const xmlNodePtr xmlNode); - ArgList(const ArgList& argTemplates, const boost::python::dict& PyDict); + ArgList(const ArgList& argTemplates, const py::dict& PyDict); virtual ~ArgList(); bool hasArg(const std::string& sName) const; @@ -54,7 +54,7 @@ public: template<class T> const T& getArgVal(const std::string& sName) const; - void getOverlayedArgVal(DPoint* pResult, const std::string& sName, + void getOverlayedArgVal(glm::vec2* pResult, const std::string& sName, const std::string& sOverlay1, const std::string& sOverlay2, const std::string& sID) const; @@ -62,12 +62,12 @@ public: void setArg(const ArgBase& newArg); void setArgs(const ArgList& args); - void setMembers(Node * pNode) const; + void setMembers(ExportedObject * pObj) const; void copyArgsFrom(const ArgList& argTemplates); private: - void setArgValue(const std::string & sName, const boost::python::object& value); + void setArgValue(const std::string & sName, const py::object& value); void setArgValue(const std::string & sName, const std::string & sValue); ArgMap m_Args; }; diff --git a/src/player/BitmapManager.cpp b/src/player/BitmapManager.cpp new file mode 100644 index 0000000..6151f1e --- /dev/null +++ b/src/player/BitmapManager.cpp @@ -0,0 +1,147 @@ +// +// libavg - Media Playback Engine. +// Copyright (C) 2003-2014 Ulrich von Zadow +// +// This library is free software; you can redistribute it and/or +// modify it under the terms of the GNU Lesser General Public +// License as published by the Free Software Foundation; either +// version 2 of the License, or (at your option) any later version. +// +// This library 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 +// Lesser General Public License for more details. +// +// You should have received a copy of the GNU Lesser General Public +// License along with this library; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +// +// Current versions can be found at www.libavg.de +// + +#include "BitmapManager.h" +#include "IBitmapLoadedListener.h" + +#ifdef WIN32 +#include <io.h> +#endif +#include <stdio.h> +#include <stdlib.h> + +#include "../base/OSHelper.h" + +using namespace std; + +namespace avg { + +BitmapManager * BitmapManager::s_pBitmapManager=0; + +BitmapManager::BitmapManager() +{ + if (s_pBitmapManager) { + throw Exception(AVG_ERR_UNKNOWN, "BitmapMananger has already been instantiated."); + } + + m_pCmdQueue = BitmapManagerThread::CQueuePtr(new BitmapManagerThread::CQueue); + m_pMsgQueue = BitmapManagerMsgQueuePtr(new BitmapManagerMsgQueue(8)); + + startThreads(1); + + s_pBitmapManager = this; +} + +BitmapManager::~BitmapManager() +{ + while (!m_pCmdQueue->empty()) { + m_pCmdQueue->pop(); + } + while (!m_pMsgQueue->empty()) { + m_pMsgQueue->pop(); + } + stopThreads(); + s_pBitmapManager = 0; +} + +BitmapManager* BitmapManager::get() +{ + if (!s_pBitmapManager) { + s_pBitmapManager = new BitmapManager(); + } + return s_pBitmapManager; +} + +void BitmapManager::loadBitmapPy(const UTF8String& sUtf8FileName, + const boost::python::object& pyFunc, PixelFormat pf) +{ + std::string sFileName = convertUTF8ToFilename(sUtf8FileName); + BitmapManagerMsgPtr pMsg = BitmapManagerMsgPtr( + new BitmapManagerMsg(sUtf8FileName, pyFunc, pf)); + internalLoadBitmap(pMsg); +} + +void BitmapManager::loadBitmap(const UTF8String& sUtf8FileName, + IBitmapLoadedListener* pLoadedListener, PixelFormat pf) +{ + std::string sFileName = convertUTF8ToFilename(sUtf8FileName); + BitmapManagerMsgPtr pMsg = BitmapManagerMsgPtr( + new BitmapManagerMsg(sUtf8FileName, pLoadedListener, pf)); + internalLoadBitmap(pMsg); +} + +void BitmapManager::setNumThreads(int numThreads) +{ + stopThreads(); + startThreads(numThreads); +} + +void BitmapManager::onFrameEnd() +{ + while (!m_pMsgQueue->empty()) { + BitmapManagerMsgPtr pMsg = m_pMsgQueue->pop(); + pMsg->executeCallback(); + } +} + +void BitmapManager::internalLoadBitmap(BitmapManagerMsgPtr pMsg) +{ +#ifdef WIN32 + int rc = _access(pMsg->getFilename().c_str(), 04); +#else + int rc = access(pMsg->getFilename().c_str(), R_OK); +#endif + + if (rc != 0) { + pMsg->setError(Exception(AVG_ERR_FILEIO, + std::string("BitmapManager can't open output file '") + + pMsg->getFilename() + "'. Reason: " + + strerror(errno))); + m_pMsgQueue->push(pMsg); + } else { + m_pCmdQueue->pushCmd(boost::bind(&BitmapManagerThread::loadBitmap, _1, pMsg)); + } +} + +void BitmapManager::startThreads(int numThreads) +{ + for (int i=0; i<numThreads; ++i) { + boost::thread* pThread = new boost::thread( + BitmapManagerThread(*m_pCmdQueue, *m_pMsgQueue)); + m_pBitmapManagerThreads.push_back(pThread); + } +} + +void BitmapManager::stopThreads() +{ + int numThreads = m_pBitmapManagerThreads.size(); + for (int i=0; i<numThreads; ++i) { + m_pCmdQueue->pushCmd(boost::bind(&BitmapManagerThread::stop, _1)); + } + for (int i=0; i<numThreads; ++i) { + boost::thread* pThread = m_pBitmapManagerThreads[i]; + pThread->join(); + delete pThread; + } + m_pBitmapManagerThreads.clear(); +} + +} diff --git a/src/player/BitmapManager.h b/src/player/BitmapManager.h new file mode 100644 index 0000000..64f8ba5 --- /dev/null +++ b/src/player/BitmapManager.h @@ -0,0 +1,66 @@ +// +// libavg - Media Playback Engine. +// Copyright (C) 2003-2014 Ulrich von Zadow +// +// This library is free software; you can redistribute it and/or +// modify it under the terms of the GNU Lesser General Public +// License as published by the Free Software Foundation; either +// version 2 of the License, or (at your option) any later version. +// +// This library 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 +// Lesser General Public License for more details. +// +// You should have received a copy of the GNU Lesser General Public +// License along with this library; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +// +// Current versions can be found at www.libavg.de +// + +#ifndef _BitmapManager_H_ +#define _BitmapManager_H_ + +#include "BitmapManagerThread.h" +#include "BitmapManagerMsg.h" + +#include "../api.h" +#include "../base/Queue.h" +#include "../base/IFrameEndListener.h" + +#include <boost/thread.hpp> + +#include <vector> + +namespace avg { + +class AVG_API BitmapManager : public IFrameEndListener +{ + public: + BitmapManager(); + ~BitmapManager(); + static BitmapManager* get(); + void loadBitmapPy(const UTF8String& sUtf8FileName, + const boost::python::object& pyFunc, PixelFormat pf=NO_PIXELFORMAT); + void loadBitmap(const UTF8String& sUtf8FileName, + IBitmapLoadedListener* pLoadedListener, PixelFormat pf=NO_PIXELFORMAT); + void setNumThreads(int numThreads); + + virtual void onFrameEnd(); + + private: + void internalLoadBitmap(BitmapManagerMsgPtr pMsg); + void startThreads(int numThreads); + void stopThreads(); + + static BitmapManager * s_pBitmapManager; + + std::vector<boost::thread*> m_pBitmapManagerThreads; + BitmapManagerThread::CQueuePtr m_pCmdQueue; + BitmapManagerMsgQueuePtr m_pMsgQueue; +}; + +} + +#endif diff --git a/src/player/BitmapManagerMsg.cpp b/src/player/BitmapManagerMsg.cpp new file mode 100644 index 0000000..f9dfc53 --- /dev/null +++ b/src/player/BitmapManagerMsg.cpp @@ -0,0 +1,121 @@ +// +// libavg - Media Playback Engine. +// Copyright (C) 2003-2014 Ulrich von Zadow +// +// This library is free software; you can redistribute it and/or +// modify it under the terms of the GNU Lesser General Public +// License as published by the Free Software Foundation; either +// version 2 of the License, or (at your option) any later version. +// +// This library 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 +// Lesser General Public License for more details. +// +// You should have received a copy of the GNU Lesser General Public +// License along with this library; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +// +// Current versions can be found at www.libavg.de +// + +#include "BitmapManagerMsg.h" +#include "IBitmapLoadedListener.h" + +#include "../base/ObjectCounter.h" +#include "../base/Exception.h" +#include "../base/TimeSource.h" + + +namespace avg { + +BitmapManagerMsg::BitmapManagerMsg(const UTF8String& sFilename, + const boost::python::object& onLoadedCb, PixelFormat pf) +{ + ObjectCounter::get()->incRef(&typeid(*this)); + init(sFilename, pf); + m_OnLoadedCb = onLoadedCb; + m_pLoadedListener = 0; +} + +BitmapManagerMsg::BitmapManagerMsg(const UTF8String& sFilename, + IBitmapLoadedListener* pLoadedListener, PixelFormat pf) +{ + ObjectCounter::get()->incRef(&typeid(*this)); + init(sFilename, pf); + m_OnLoadedCb = boost::python::object(); + m_pLoadedListener = pLoadedListener; +} + +BitmapManagerMsg::~BitmapManagerMsg() +{ + if (m_pEx) { + delete m_pEx; + } + ObjectCounter::get()->decRef(&typeid(*this)); +} + +void BitmapManagerMsg::init(const UTF8String& sFilename, PixelFormat pf) +{ + m_sFilename = sFilename; + m_StartTime = TimeSource::get()->getCurrentMicrosecs()/1000.0f; + m_PF = pf; + m_MsgType = REQUEST; + m_pEx = 0; +} + +void BitmapManagerMsg::executeCallback() +{ + switch (m_MsgType) { + case BITMAP: + if (m_pLoadedListener) { + m_pLoadedListener->onBitmapLoaded(m_pBmp); + } else { + boost::python::call<void>(m_OnLoadedCb.ptr(), m_pBmp); + } + break; + case ERROR: + if (m_pLoadedListener) { + m_pLoadedListener->onBitmapLoadError(m_pEx); + } else { + boost::python::call<void>(m_OnLoadedCb.ptr(), m_pEx); + } + break; + + default: + AVG_ASSERT(false); + } +} + +const UTF8String BitmapManagerMsg::getFilename() +{ + return m_sFilename; +} + +float BitmapManagerMsg::getStartTime() +{ + AVG_ASSERT(m_MsgType == REQUEST); + return m_StartTime; +} + +PixelFormat BitmapManagerMsg::getPixelFormat() +{ + AVG_ASSERT(m_MsgType == REQUEST); + return m_PF; +} + +void BitmapManagerMsg::setBitmap(BitmapPtr pBmp) +{ + AVG_ASSERT(m_MsgType == REQUEST); + m_pBmp = pBmp; + m_MsgType = BITMAP; +} + +void BitmapManagerMsg::setError(const Exception& ex) +{ + AVG_ASSERT(m_MsgType == REQUEST); + m_MsgType = ERROR; + m_pEx = new Exception(ex); +} + +} diff --git a/src/player/BitmapManagerMsg.h b/src/player/BitmapManagerMsg.h new file mode 100644 index 0000000..47ba785 --- /dev/null +++ b/src/player/BitmapManagerMsg.h @@ -0,0 +1,76 @@ +// +// libavg - Media Playback Engine. +// Copyright (C) 2003-2014 Ulrich von Zadow +// +// This library is free software; you can redistribute it and/or +// modify it under the terms of the GNU Lesser General Public +// License as published by the Free Software Foundation; either +// version 2 of the License, or (at your option) any later version. +// +// This library 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 +// Lesser General Public License for more details. +// +// You should have received a copy of the GNU Lesser General Public +// License along with this library; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +// +// Current versions can be found at www.libavg.de +// + +#ifndef _BitmapManagerMsg_H_ +#define _BitmapManagerMsg_H_ + +#include "WrapPython.h" + +#include "../api.h" +#include "../base/Queue.h" +#include "../graphics/Bitmap.h" + +#include <boost/shared_ptr.hpp> +#include <boost/python.hpp> + + +namespace avg { + +class IBitmapLoadedListener; + +class AVG_API BitmapManagerMsg +{ +public: + enum MsgType {REQUEST, BITMAP, ERROR}; + + BitmapManagerMsg(const UTF8String& sFilename, + const boost::python::object& onLoadedCb, PixelFormat pf); + BitmapManagerMsg(const UTF8String& sFilename, + IBitmapLoadedListener* pLoadedListener, PixelFormat pf); + virtual ~BitmapManagerMsg(); + void init(const UTF8String& sFilename, PixelFormat pf); + + void executeCallback(); + const UTF8String getFilename(); + float getStartTime(); + PixelFormat getPixelFormat(); + void setBitmap(BitmapPtr pBmp); + void setError(const Exception& ex); + + MsgType getType() { return m_MsgType; }; + +private: + UTF8String m_sFilename; + float m_StartTime; + BitmapPtr m_pBmp; + boost::python::object m_OnLoadedCb; + IBitmapLoadedListener* m_pLoadedListener; + PixelFormat m_PF; + MsgType m_MsgType; + Exception* m_pEx; +}; + +typedef boost::shared_ptr<BitmapManagerMsg> BitmapManagerMsgPtr; +typedef Queue<BitmapManagerMsg> BitmapManagerMsgQueue; +typedef boost::shared_ptr<BitmapManagerMsgQueue> BitmapManagerMsgQueuePtr; +} + +#endif diff --git a/src/player/BitmapManagerThread.cpp b/src/player/BitmapManagerThread.cpp new file mode 100644 index 0000000..42372a6 --- /dev/null +++ b/src/player/BitmapManagerThread.cpp @@ -0,0 +1,78 @@ +// +// libavg - Media Playback Engine. +// Copyright (C) 2003-2014 Ulrich von Zadow +// +// This library is free software; you can redistribute it and/or +// modify it under the terms of the GNU Lesser General Public +// License as published by the Free Software Foundation; either +// version 2 of the License, or (at your option) any later version. +// +// This library 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 +// Lesser General Public License for more details. +// +// You should have received a copy of the GNU Lesser General Public +// License along with this library; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +// +// Current versions can be found at www.libavg.de +// + +#include "BitmapManagerThread.h" + +#include "../base/Exception.h" +#include "../base/ScopeTimer.h" +#include "../base/TimeSource.h" + +#include "../graphics/BitmapLoader.h" + +#include <stdio.h> +#include <stdlib.h> + +namespace avg { + +BitmapManagerThread::BitmapManagerThread(CQueue& cmdQ, BitmapManagerMsgQueue& MsgQueue) + : WorkerThread<BitmapManagerThread>("BitmapManager", cmdQ), + m_MsgQueue(MsgQueue), + m_TotalLatency(0), + m_NumBmpsLoaded(0) +{ +} + +bool BitmapManagerThread::work() +{ + waitForCommand(); + return true; +} + +void BitmapManagerThread::deinit() +{ + if (m_NumBmpsLoaded > 0) { + AVG_TRACE(Logger::category::PROFILE, Logger::severity::INFO, + "Average latency for async bitmap loads: " << m_TotalLatency/m_NumBmpsLoaded + << " ms"); + } +} + +static ProfilingZoneID LoaderProfilingZone("loadBitmap", true); + +void BitmapManagerThread::loadBitmap(BitmapManagerMsgPtr pRequest) +{ + BitmapPtr pBmp; + ScopeTimer timer(LoaderProfilingZone); + float startTime = pRequest->getStartTime(); + try { + pBmp = avg::loadBitmap(pRequest->getFilename(), pRequest->getPixelFormat()); + pRequest->setBitmap(pBmp); + } catch (const Exception& ex) { + pRequest->setError(ex); + } + m_MsgQueue.push(pRequest); + m_NumBmpsLoaded++; + float curLatency = TimeSource::get()->getCurrentMicrosecs()/1000 - startTime; + m_TotalLatency += curLatency; + ThreadProfiler::get()->reset(); +} + +} diff --git a/src/player/BitmapManagerThread.h b/src/player/BitmapManagerThread.h new file mode 100644 index 0000000..fbc5c56 --- /dev/null +++ b/src/player/BitmapManagerThread.h @@ -0,0 +1,55 @@ +// +// libavg - Media Playback Engine. +// Copyright (C) 2003-2014 Ulrich von Zadow +// +// This library is free software; you can redistribute it and/or +// modify it under the terms of the GNU Lesser General Public +// License as published by the Free Software Foundation; either +// version 2 of the License, or (at your option) any later version. +// +// This library 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 +// Lesser General Public License for more details. +// +// You should have received a copy of the GNU Lesser General Public +// License along with this library; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +// +// Current versions can be found at www.libavg.de +// + +#ifndef _BitmapManagerThread_H_ +#define _BitmapManagerThread_H_ + +#include "../api.h" + +#include "BitmapManagerMsg.h" + +#include "../base/WorkerThread.h" +#include "../graphics/Bitmap.h" + +#include <boost/thread.hpp> + + +namespace avg { + +class AVG_API BitmapManagerThread : public WorkerThread<BitmapManagerThread> +{ + public: + BitmapManagerThread(CQueue& cmdQ, BitmapManagerMsgQueue& MsgQueue); + + void loadBitmap(BitmapManagerMsgPtr pRequest); + + private: + virtual bool work(); + virtual void deinit(); + BitmapManagerMsgQueue& m_MsgQueue; + + float m_TotalLatency; + int m_NumBmpsLoaded; +}; + +} + +#endif diff --git a/src/player/BlurFXNode.cpp b/src/player/BlurFXNode.cpp index 3a0ad19..16583a8 100644 --- a/src/player/BlurFXNode.cpp +++ b/src/player/BlurFXNode.cpp @@ -1,6 +1,6 @@ // // libavg - Media Playback Engine. -// Copyright (C) 2003-2011 Ulrich von Zadow +// Copyright (C) 2003-2014 Ulrich von Zadow // // This library is free software; you can redistribute it and/or // modify it under the terms of the GNU Lesser General Public @@ -23,7 +23,6 @@ #include "../base/ObjectCounter.h" #include "../base/Exception.h" -#include "../graphics/ShaderRegistry.h" #include <string> @@ -31,9 +30,9 @@ using namespace std; namespace avg { -BlurFXNode::BlurFXNode() - : FXNode(), - m_StdDev(1) +BlurFXNode::BlurFXNode(float radius) + : FXNode(false), + m_StdDev(radius) { ObjectCounter::get()->incRef(&typeid(*this)); } @@ -45,10 +44,6 @@ BlurFXNode::~BlurFXNode() void BlurFXNode::connect() { - if (!GLTexture::isFloatFormatSupported()) { - throw Exception(AVG_ERR_UNSUPPORTED, - "Cannot create BlurFX: OpenGL configuration doesn't support Blur (no float textures)."); - } setDirty(); FXNode::connect(); } @@ -59,12 +54,7 @@ void BlurFXNode::disconnect() FXNode::disconnect(); } -void BlurFXNode::setParam(double stdDev) -{ - setRadius(stdDev); -} - -void BlurFXNode::setRadius(double stdDev) +void BlurFXNode::setRadius(float stdDev) { m_StdDev = stdDev; if (m_pFilter) { @@ -73,7 +63,7 @@ void BlurFXNode::setRadius(double stdDev) setDirty(); } -double BlurFXNode::getRadius() const +float BlurFXNode::getRadius() const { return m_StdDev; } diff --git a/src/player/BlurFXNode.h b/src/player/BlurFXNode.h index 62eb535..24b5f8c 100644 --- a/src/player/BlurFXNode.h +++ b/src/player/BlurFXNode.h @@ -1,6 +1,6 @@ // // libavg - Media Playback Engine. -// Copyright (C) 2003-2011 Ulrich von Zadow +// Copyright (C) 2003-2014 Ulrich von Zadow // // This library is free software; you can redistribute it and/or // modify it under the terms of the GNU Lesser General Public @@ -33,22 +33,21 @@ namespace avg { class AVG_API BlurFXNode: public FXNode { public: - BlurFXNode(); + BlurFXNode(float radius=1.f); virtual ~BlurFXNode(); void connect(); virtual void disconnect(); - void setParam(double stdDev); - void setRadius(double stdDev); - double getRadius() const; + void setRadius(float stdDev); + float getRadius() const; private: virtual GPUFilterPtr createFilter(const IntPoint& size); GPUBlurFilterPtr m_pFilter; - double m_StdDev; + float m_StdDev; }; typedef boost::shared_ptr<BlurFXNode> BlurFXNodePtr; diff --git a/src/player/BoostPython.h b/src/player/BoostPython.h index db1c0c5..6fdc141 100644 --- a/src/player/BoostPython.h +++ b/src/player/BoostPython.h @@ -1,6 +1,6 @@ // // libavg - Media Playback Engine. -// Copyright (C) 2003-2011 Ulrich von Zadow +// Copyright (C) 2003-2014 Ulrich von Zadow // // This library is free software; you can redistribute it and/or // modify it under the terms of the GNU Lesser General Public @@ -28,6 +28,8 @@ #include "../api.h" #include <boost/python.hpp> +namespace py = boost::python; + #ifdef _WIN32 #pragma warning(pop) #endif diff --git a/src/player/CameraNode.cpp b/src/player/CameraNode.cpp index 8f08dfa..c091a4e 100644 --- a/src/player/CameraNode.cpp +++ b/src/player/CameraNode.cpp @@ -1,6 +1,6 @@ // // libavg - Media Playback Engine. -// Copyright (C) 2003-2011 Ulrich von Zadow +// Copyright (C) 2003-2014 Ulrich von Zadow // // This library is free software; you can redistribute it and/or // modify it under the terms of the GNU Lesser General Public @@ -21,7 +21,7 @@ #include "CameraNode.h" #include "OGLSurface.h" -#include "NodeDefinition.h" +#include "TypeDefinition.h" #include "../base/Logger.h" #include "../base/Exception.h" @@ -31,6 +31,7 @@ #include "../graphics/Filterfill.h" #include "../graphics/TextureMover.h" #include "../graphics/GLTexture.h" +#include "../graphics/BitmapLoader.h" #include "../imaging/Camera.h" #include "../imaging/FWCamera.h" @@ -46,15 +47,15 @@ using namespace std; namespace avg { -NodeDefinition CameraNode::createDefinition() +void CameraNode::registerType() { - return NodeDefinition("camera", Node::buildNode<CameraNode>) - .extendDefinition(RasterNode::createDefinition()) + TypeDefinition def = TypeDefinition("camera", "rasternode", + ExportedObject::buildObject<CameraNode>) .addArg(Arg<string>("driver", "firewire")) .addArg(Arg<string>("device", "")) .addArg(Arg<int>("unit", -1)) .addArg(Arg<bool>("fw800", false)) - .addArg(Arg<double>("framerate", 15)) + .addArg(Arg<float>("framerate", 15)) .addArg(Arg<int>("capturewidth", 640)) .addArg(Arg<int>("captureheight", 480)) .addArg(Arg<string>("pixelformat", "RGB")) @@ -66,6 +67,7 @@ NodeDefinition CameraNode::createDefinition() .addArg(Arg<int>("shutter", -1)) .addArg(Arg<int>("gain", -1)) .addArg(Arg<int>("strobeduration", -1)); + TypeRegistry::get()->registerType(def); } CameraNode::CameraNode(const ArgList& args) @@ -79,7 +81,7 @@ CameraNode::CameraNode(const ArgList& args) string sDevice = args.getArgVal<string>("device"); int unit = args.getArgVal<int>("unit"); bool bFW800 = args.getArgVal<bool>("fw800"); - double frameRate = args.getArgVal<double>("framerate"); + float frameRate = args.getArgVal<float>("framerate"); int width = args.getArgVal<int>("capturewidth"); int height = args.getArgVal<int>("captureheight"); string sPF = args.getArgVal<string>("pixelformat"); @@ -90,7 +92,11 @@ CameraNode::CameraNode(const ArgList& args) } PixelFormat destPF; if (pixelFormatIsColored(camPF)) { - destPF = B8G8R8X8; + if (BitmapLoader::get()->isBlueFirst()) { + destPF = B8G8R8X8; + } else { + destPF = R8G8B8X8; + } } else { destPF = I8; } @@ -98,8 +104,8 @@ CameraNode::CameraNode(const ArgList& args) m_pCamera = createCamera(sDriver, sDevice, unit, bFW800, IntPoint(width, height), camPF, destPF, frameRate); - AVG_TRACE(Logger::CONFIG, "Got Camera " << m_pCamera->getDevice() << " from driver: " - << m_pCamera->getDriverName()); + AVG_TRACE(Logger::category::CONFIG,Logger::severity::INFO, "Got Camera " << + m_pCamera->getDevice() << " from driver: " << m_pCamera->getDriverName()); m_pCamera->setFeature(CAM_FEATURE_BRIGHTNESS, args.getArgVal<int>("brightness")); m_pCamera->setFeature(CAM_FEATURE_EXPOSURE, args.getArgVal<int>("exposure")); @@ -273,9 +279,10 @@ BitmapPtr CameraNode::getBitmap() } } -void CameraNode::dumpCameras() +CamerasInfosVector CameraNode::getCamerasInfos() { - avg::dumpCameras(); + CamerasInfosVector camInfos = avg::getCamerasInfos(); + return camInfos; } void CameraNode::resetFirewireBus() @@ -283,7 +290,7 @@ void CameraNode::resetFirewireBus() FWCamera::resetBus(); } -double CameraNode::getFPS() const +float CameraNode::getFPS() const { return m_pCamera->getFrameRate(); } @@ -298,6 +305,7 @@ void CameraNode::open() m_pTex = GLTexturePtr(new GLTexture(size, pf, bMipmap)); m_pTex->enableStreaming(); getSurface()->create(pf, m_pTex); + newSurface(); BitmapPtr pBmp = m_pTex->lockStreamingBmp(); if (pf == B8G8R8X8 || pf == B8G8R8A8) { @@ -308,6 +316,7 @@ void CameraNode::open() Filter.applyInPlace(pBmp); } m_pTex->unlockStreamingBmp(true); + setupFX(true); } int CameraNode::getFeature(CameraFeature feature) const @@ -328,9 +337,10 @@ int CameraNode::getFrameNum() const static ProfilingZoneID CameraFetchImage("Camera fetch image"); static ProfilingZoneID CameraDownloadProfilingZone("Camera tex download"); -void CameraNode::preRender() +void CameraNode::preRender(const VertexArrayPtr& pVA, bool bIsParentActive, + float parentEffectiveOpacity) { - Node::preRender(); + Node::preRender(pVA, bIsParentActive, parentEffectiveOpacity); if (isAutoUpdateCameraImage()) { ScopeTimer Timer(CameraFetchImage); updateToLatestCameraImage(); @@ -346,19 +356,19 @@ void CameraNode::preRender() AVG_ASSERT(pBmp->getPixelFormat() == m_pCurBmp->getPixelFormat()); pBmp->copyPixels(*m_pCurBmp); m_pTex->unlockStreamingBmp(true); - bind(); renderFX(getSize(), Pixel32(255, 255, 255, 255), false); m_bNewBmp = false; } + calcVertexArray(pVA); } static ProfilingZoneID CameraProfilingZone("Camera::render"); -void CameraNode::render(const DRect& rect) +void CameraNode::render() { if (m_bIsPlaying) { ScopeTimer Timer(CameraProfilingZone); - blt32(getSize(), getEffectiveOpacity(), getBlendMode()); + blt32(getTransform(), getSize(), getEffectiveOpacity(), getBlendMode()); } } @@ -381,7 +391,7 @@ void CameraNode::updateCameraImage() { if (!isAutoUpdateCameraImage()) { m_pCurBmp = m_pCamera->getImage(false); - blt32(getSize(), getEffectiveOpacity(), getBlendMode()); + blt32(getTransform(), getSize(), getEffectiveOpacity(), getBlendMode()); } } diff --git a/src/player/CameraNode.h b/src/player/CameraNode.h index 874593b..1aef572 100644 --- a/src/player/CameraNode.h +++ b/src/player/CameraNode.h @@ -1,6 +1,6 @@ // // libavg - Media Playback Engine. -// Copyright (C) 2003-2011 Ulrich von Zadow +// Copyright (C) 2003-2014 Ulrich von Zadow // // This library is free software; you can redistribute it and/or // modify it under the terms of the GNU Lesser General Public @@ -28,6 +28,7 @@ #include "RasterNode.h" #include "../imaging/Camera.h" +#include "../imaging/CameraInfo.h" #include <boost/thread/thread.hpp> @@ -38,11 +39,12 @@ namespace avg { class TextureMover; typedef boost::shared_ptr<TextureMover> TextureMoverPtr; +typedef std::vector<CameraInfo> CamerasInfosVector; class AVG_API CameraNode : public RasterNode { public: - static NodeDefinition createDefinition(); + static void registerType(); CameraNode(const ArgList& args); virtual ~CameraNode(); @@ -65,7 +67,7 @@ class AVG_API CameraNode : public RasterNode return m_pCamera->getDriverName(); } - double getFrameRate() const + float getFrameRate() const { return m_pCamera->getFrameRate(); } @@ -94,21 +96,22 @@ class AVG_API CameraNode : public RasterNode void setAutoUpdateCameraImage(bool bVal); bool isImageAvailable() const; - virtual void preRender(); - virtual void render(const DRect& Rect); + virtual void preRender(const VertexArrayPtr& pVA, bool bIsParentActive, + float parentEffectiveOpacity); + virtual void render(); int getFrameNum() const; IntPoint getMediaSize(); virtual BitmapPtr getBitmap(); - static void dumpCameras(); + static CamerasInfosVector getCamerasInfos(); static void resetFirewireBus(); private: int getFeature (CameraFeature feature) const; void setFeature (CameraFeature feature, int value); - virtual double getFPS() const; + virtual float getFPS() const; virtual void open(); virtual PixelFormat getPixelFormat(); void setFeature(int FeatureID); diff --git a/src/player/Canvas.cpp b/src/player/Canvas.cpp index 0a21f8a..ae0723e 100644 --- a/src/player/Canvas.cpp +++ b/src/player/Canvas.cpp @@ -1,6 +1,6 @@ // // libavg - Media Playback Engine. -// Copyright (C) 2003-2011 Ulrich von Zadow +// Copyright (C) 2003-2014 Ulrich von Zadow // // This library is free software; you can redistribute it and/or // modify it under the terms of the GNU Lesser General Public @@ -30,6 +30,8 @@ #include "../base/Logger.h" #include "../base/ScopeTimer.h" +#include "../graphics/StandardShader.h" + #include <iostream> using namespace std; @@ -37,8 +39,6 @@ using namespace boost; namespace avg { -CanvasPtr Canvas::s_pActiveCanvas; - Canvas::Canvas(Player * pPlayer) : m_pPlayer(pPlayer), m_bIsPlaying(false), @@ -57,8 +57,8 @@ void Canvas::setRoot(NodePtr pRootNode) { assert(!m_pRootNode); m_pRootNode = dynamic_pointer_cast<CanvasNode>(pRootNode); - m_pRootNode->setParent(DivNodeWeakPtr(), Node::NS_CONNECTED, - shared_from_this()); + CanvasPtr pThis = dynamic_pointer_cast<Canvas>(shared_from_this()); + m_pRootNode->setParent(0, Node::NS_CONNECTED, pThis); registerNode(m_pRootNode); } @@ -67,16 +67,20 @@ void Canvas::initPlayback(int multiSampleSamples) m_bIsPlaying = true; m_pRootNode->connectDisplay(); m_MultiSampleSamples = multiSampleSamples; + m_pVertexArray = VertexArrayPtr(new VertexArray(2000, 3000)); } -void Canvas::stopPlayback() +void Canvas::stopPlayback(bool bIsAbort) { if (m_bIsPlaying) { - m_PlaybackEndSignal.emit(); + if (!bIsAbort) { + m_PlaybackEndSignal.emit(); + } m_pRootNode->disconnect(true); m_pRootNode = CanvasNodePtr(); m_IDMap.clear(); m_bIsPlaying = false; + m_pVertexArray = VertexArrayPtr(); } } @@ -85,7 +89,6 @@ NodePtr Canvas::getElementByID(const std::string& id) if (m_IDMap.find(id) != m_IDMap.end()) { return m_IDMap.find(id)->second; } else { - AVG_TRACE(Logger::WARNING, "getElementByID(\"" << id << "\") failed."); return NodePtr(); } } @@ -138,25 +141,26 @@ static ProfilingZoneID RenderProfilingZone("Render"); void Canvas::doFrame(bool bPythonAvailable) { - s_pActiveCanvas = shared_from_this(); emitPreRenderSignal(); if (!m_pPlayer->isStopping()) { ScopeTimer Timer(RenderProfilingZone); + Player::get()->startTraversingTree(); if (bPythonAvailable) { Py_BEGIN_ALLOW_THREADS; try { - render(); + renderTree(); } catch(...) { Py_BLOCK_THREADS; + Player::get()->endTraversingTree(); throw; } Py_END_ALLOW_THREADS; } else { - render(); + renderTree(); } + Player::get()->endTraversingTree(); } emitFrameEndSignal(); - s_pActiveCanvas = CanvasPtr(); } IntPoint Canvas::getSize() const @@ -165,20 +169,20 @@ IntPoint Canvas::getSize() const } static ProfilingZoneID PushClipRectProfilingZone("pushClipRect"); -void Canvas::pushClipRect(VertexArrayPtr pVA) +void Canvas::pushClipRect(const glm::mat4& transform, SubVertexArray& va) { ScopeTimer timer(PushClipRectProfilingZone); m_ClipLevel++; - clip(pVA, GL_INCR); + clip(transform, va, GL_INCR); } static ProfilingZoneID PopClipRectProfilingZone("popClipRect"); -void Canvas::popClipRect(VertexArrayPtr pVA) +void Canvas::popClipRect(const glm::mat4& transform, SubVertexArray& va) { ScopeTimer timer(PopClipRectProfilingZone); m_ClipLevel--; - clip(pVA, GL_DECR); + clip(transform, va, GL_DECR); } void Canvas::registerPlaybackEndListener(IPlaybackEndListener* pListener) @@ -211,102 +215,69 @@ void Canvas::unregisterPreRenderListener(IPreRenderListener* pListener) m_PreRenderSignal.disconnect(pListener); } -bool Canvas::operator ==(const Canvas& other) const -{ - return this == &other; -} - -bool Canvas::operator !=(const Canvas& other) const -{ - return this != &other; -} - -long Canvas::getHash() const -{ - return long(this); -} - -CanvasPtr Canvas::getActive() -{ - return s_pActiveCanvas; -} - Player* Canvas::getPlayer() const { return m_pPlayer; } -vector<NodeWeakPtr> Canvas::getElementsByPos(const DPoint& pos) const +vector<NodePtr> Canvas::getElementsByPos(const glm::vec2& pos) const { - vector<NodeWeakPtr> elements; + vector<NodePtr> elements; m_pRootNode->getElementsByPos(pos, elements); return elements; } static ProfilingZoneID PreRenderProfilingZone("PreRender"); +static ProfilingZoneID VATransferProfilingZone("VA Transfer"); -void Canvas::render(IntPoint windowSize, bool bUpsideDown, FBOPtr pFBO, - ProfilingZoneID& renderProfilingZone) +void Canvas::preRender() { + ScopeTimer Timer(PreRenderProfilingZone); + m_pVertexArray->reset(); + m_pRootNode->preRender(m_pVertexArray, true, 1.0f); { - ScopeTimer Timer(PreRenderProfilingZone); - m_pRootNode->preRender(); - } - if (pFBO) { - pFBO->activate(); - } else { - glproc::BindFramebuffer(GL_FRAMEBUFFER_EXT, 0); - OGLErrorCheck(AVG_ERR_VIDEO_GENERAL, "Canvas::render: BindFramebuffer()"); - } - if (m_MultiSampleSamples > 1) { - glEnable(GL_MULTISAMPLE); - OGLErrorCheck(AVG_ERR_VIDEO_GENERAL, - "Canvas::render: glEnable(GL_MULTISAMPLE)"); - } else { - glDisable(GL_MULTISAMPLE); - OGLErrorCheck(AVG_ERR_VIDEO_GENERAL, - "Canvas::render: glDisable(GL_MULTISAMPLE)"); + ScopeTimer Timer(VATransferProfilingZone); + m_pVertexArray->update(); } - clearGLBuffers(GL_COLOR_BUFFER_BIT | GL_STENCIL_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); +} + +void Canvas::render(IntPoint windowSize, bool bOffscreen) +{ + clearGLBuffers(GL_COLOR_BUFFER_BIT | GL_STENCIL_BUFFER_BIT | GL_DEPTH_BUFFER_BIT, + !bOffscreen); glViewport(0, 0, windowSize.x, windowSize.y); - OGLErrorCheck(AVG_ERR_VIDEO_GENERAL, "Canvas::render: glViewport()"); - glMatrixMode(GL_PROJECTION); - OGLErrorCheck(AVG_ERR_VIDEO_GENERAL, "Canvas::render: glMatrixMode()"); - glLoadIdentity(); - OGLErrorCheck(AVG_ERR_VIDEO_GENERAL, "Canvas::render: glLoadIdentity()"); - IntPoint size = IntPoint(m_pRootNode->getSize()); - if (bUpsideDown) { - gluOrtho2D(0, size.x, 0, size.y); + GLContext::checkError("Canvas::render: glViewport()"); + glm::vec2 size = m_pRootNode->getSize(); + glm::mat4 projMat; + if (bOffscreen) { + projMat = glm::ortho(0.f, size.x, 0.f, size.y); } else { - gluOrtho2D(0, size.x, size.y, 0); + projMat = glm::ortho(0.f, size.x, size.y, 0.f); } - OGLErrorCheck(AVG_ERR_VIDEO_GENERAL, "Canvas::render: gluOrtho2D()"); - - const DRect rc(0,0, size.x, size.y); - glMatrixMode(GL_MODELVIEW); - { - ScopeTimer Timer(renderProfilingZone); - m_pRootNode->maybeRender(rc); + m_pVertexArray->activate(); + m_pRootNode->maybeRender(projMat); - renderOutlines(); - } + renderOutlines(projMat); } -void Canvas::renderOutlines() +void Canvas::renderOutlines(const glm::mat4& transform) { - GLContext* pContext = GLContext::getCurrent(); + GLContext* pContext = GLContext::getMain(); VertexArrayPtr pVA(new VertexArray); pContext->setBlendMode(GLContext::BLEND_BLEND, false); m_pRootNode->renderOutlines(pVA, Pixel32(0,0,0,0)); - if (pVA->getCurVert() != 0) { + StandardShaderPtr pShader = pContext->getStandardShader(); + pShader->setTransform(transform); + pShader->setUntextured(); + pShader->setAlpha(0.5f); + pShader->activate(); + if (pVA->getNumVerts() != 0) { pVA->update(); - pContext->enableTexture(false); - pContext->enableGLColorArray(true); pVA->draw(); } } -void Canvas::clip(VertexArrayPtr pVA, GLenum stencilOp) +void Canvas::clip(const glm::mat4& transform, SubVertexArray& va, GLenum stencilOp) { // Disable drawing to color buffer glColorMask(0, 0, 0, 0); @@ -318,7 +289,11 @@ void Canvas::clip(VertexArrayPtr pVA, GLenum stencilOp) glStencilFunc(GL_ALWAYS, 0, 0); glStencilOp(stencilOp, stencilOp, stencilOp); - pVA->draw(); + StandardShaderPtr pShader = GLContext::getMain()->getStandardShader(); + pShader->setUntextured(); + pShader->setTransform(transform); + pShader->activate(); + va.draw(); // Set stencil test to only let glStencilFunc(GL_LEQUAL, m_ClipLevel, ~0); diff --git a/src/player/Canvas.h b/src/player/Canvas.h index a5e30ac..38259a5 100644 --- a/src/player/Canvas.h +++ b/src/player/Canvas.h @@ -1,6 +1,6 @@ // // libavg - Media Playback Engine. -// Copyright (C) 2003-2011 Ulrich von Zadow +// Copyright (C) 2003-2014 Ulrich von Zadow // // This library is free software; you can redistribute it and/or // modify it under the terms of the GNU Lesser General Public @@ -21,13 +21,16 @@ #ifndef _Canvas_H_ #define _Canvas_H_ - + #include "../api.h" +#include "FontStyle.h" + #include "../base/IPlaybackEndListener.h" #include "../base/IFrameEndListener.h" #include "../base/IPreRenderListener.h" #include "../base/Signal.h" +#include "../base/GLMHelper.h" #include "../graphics/OGLHelper.h" #include "../graphics/Bitmap.h" @@ -48,9 +51,9 @@ class ProfilingZoneID; class Canvas; class FBO; class VertexArray; +class SubVertexArray; typedef boost::shared_ptr<Node> NodePtr; -typedef boost::weak_ptr<Node> NodeWeakPtr; typedef boost::shared_ptr<CanvasNode> CanvasNodePtr; typedef boost::shared_ptr<FBO> FBOPtr; typedef boost::shared_ptr<VertexArray> VertexArrayPtr; @@ -59,14 +62,14 @@ class Canvas; typedef boost::shared_ptr<Canvas> CanvasPtr; typedef boost::weak_ptr<Canvas> CanvasWeakPtr; -class AVG_API Canvas: public boost::enable_shared_from_this<Canvas> +class AVG_API Canvas: public ExportedObject { public: Canvas(Player * pPlayer); virtual ~Canvas(); virtual void setRoot(NodePtr pRootNode); void initPlayback(int multiSampleSamples); - virtual void stopPlayback(); + virtual void stopPlayback(bool bIsAbort); CanvasNodePtr getRootNode() const; NodePtr getElementByID(const std::string& id); @@ -76,8 +79,8 @@ class AVG_API Canvas: public boost::enable_shared_from_this<Canvas> virtual void doFrame(bool bPythonAvailable); IntPoint getSize() const; virtual BitmapPtr screenshot() const = 0; - virtual void pushClipRect(VertexArrayPtr pVA); - virtual void popClipRect(VertexArrayPtr pVA); + virtual void pushClipRect(const glm::mat4& transform, SubVertexArray& va); + virtual void popClipRect(const glm::mat4& transform, SubVertexArray& va); void registerPlaybackEndListener(IPlaybackEndListener* pListener); void unregisterPlaybackEndListener(IPlaybackEndListener* pListener); @@ -86,30 +89,25 @@ class AVG_API Canvas: public boost::enable_shared_from_this<Canvas> void registerPreRenderListener(IPreRenderListener* pListener); void unregisterPreRenderListener(IPreRenderListener* pListener); - std::vector<NodeWeakPtr> getElementsByPos(const DPoint& Pos) const; - - bool operator ==(const Canvas& other) const; - bool operator !=(const Canvas& other) const; - long getHash() const; + std::vector<NodePtr> getElementsByPos(const glm::vec2& Pos) const; - static CanvasPtr getActive(); + virtual void render(IntPoint windowSize, bool bOffscreen); protected: Player * getPlayer() const; - void render(IntPoint windowSize, bool bUpsideDown, FBOPtr pFBO, - ProfilingZoneID& renderProfilingZone); + void preRender(); void emitPreRenderSignal(); void emitFrameEndSignal(); - private: - virtual void render()=0; - void renderOutlines(); + virtual void renderTree()=0; + void renderOutlines(const glm::mat4& transform); - void clip(VertexArrayPtr pVA, GLenum stencilOp); + void clip(const glm::mat4& transform, SubVertexArray& va, GLenum stencilOp); Player * m_pPlayer; CanvasNodePtr m_pRootNode; bool m_bIsPlaying; + VertexArrayPtr m_pVertexArray; typedef std::map<std::string, NodePtr> NodeIDMap; NodeIDMap m_IDMap; @@ -120,8 +118,6 @@ class AVG_API Canvas: public boost::enable_shared_from_this<Canvas> int m_MultiSampleSamples; int m_ClipLevel; - - static CanvasPtr s_pActiveCanvas; }; } diff --git a/src/player/CanvasNode.cpp b/src/player/CanvasNode.cpp index cfa836e..3c267d3 100644 --- a/src/player/CanvasNode.cpp +++ b/src/player/CanvasNode.cpp @@ -1,6 +1,6 @@ // // libavg - Media Playback Engine. -// Copyright (C) 2003-2011 Ulrich von Zadow +// Copyright (C) 2003-2014 Ulrich von Zadow // // This library is free software; you can redistribute it and/or // modify it under the terms of the GNU Lesser General Public @@ -22,7 +22,7 @@ #include "CanvasNode.h" #include "Player.h" -#include "NodeDefinition.h" +#include "TypeDefinition.h" #include "../base/FileHelper.h" #include "../base/Exception.h" @@ -31,17 +31,18 @@ using namespace std; namespace avg { -NodeDefinition CanvasNode::createDefinition() +void CanvasNode::registerType() { - return NodeDefinition("canvasbase", Node::buildNode<CanvasNode>) - .extendDefinition(DivNode::createDefinition()); + TypeDefinition def = TypeDefinition("canvasbase", "div", + ExportedObject::buildObject<CanvasNode>); + TypeRegistry::get()->registerType(def); } CanvasNode::CanvasNode(const ArgList& args) : DivNode(args) { args.setMembers(this); - if (getSize() == DPoint(0, 0)) { + if (getSize() == glm::vec2(0, 0)) { throw (Exception(AVG_ERR_OUT_OF_RANGE, "<avg> and <canvas> node width and height attributes are mandatory.")); } diff --git a/src/player/CanvasNode.h b/src/player/CanvasNode.h index eaf361d..b336a4a 100644 --- a/src/player/CanvasNode.h +++ b/src/player/CanvasNode.h @@ -1,6 +1,6 @@ // // libavg - Media Playback Engine. -// Copyright (C) 2003-2011 Ulrich von Zadow +// Copyright (C) 2003-2014 Ulrich von Zadow // // This library is free software; you can redistribute it and/or // modify it under the terms of the GNU Lesser General Public @@ -32,12 +32,13 @@ namespace avg { class AVG_API CanvasNode : public DivNode { public: - static NodeDefinition createDefinition(); + static void registerType(); CanvasNode(const ArgList& args); virtual ~CanvasNode(); virtual std::string getEffectiveMediaDir(); + }; typedef boost::shared_ptr<CanvasNode> CanvasNodePtr; diff --git a/src/player/ChromaKeyFXNode.cpp b/src/player/ChromaKeyFXNode.cpp index f243ba2..4e70454 100644 --- a/src/player/ChromaKeyFXNode.cpp +++ b/src/player/ChromaKeyFXNode.cpp @@ -1,6 +1,6 @@ // // libavg - Media Playback Engine. -// Copyright (C) 2003-2011 Ulrich von Zadow +// Copyright (C) 2003-2014 Ulrich von Zadow // // This library is free software; you can redistribute it and/or // modify it under the terms of the GNU Lesser General Public @@ -22,7 +22,6 @@ #include "ChromaKeyFXNode.h" #include "../base/ObjectCounter.h" -#include "../graphics/ShaderRegistry.h" #include <string> @@ -31,7 +30,7 @@ using namespace std; namespace avg { ChromaKeyFXNode::ChromaKeyFXNode() - : FXNode(), + : FXNode(false), m_sColorName("00FF00"), m_Color(0, 255, 0), m_HTolerance(0.0), @@ -68,46 +67,46 @@ const std::string& ChromaKeyFXNode::getColor() const return m_sColorName; } -void ChromaKeyFXNode::setHTolerance(double tolerance) +void ChromaKeyFXNode::setHTolerance(float tolerance) { m_HTolerance = tolerance; updateFilter(); } -double ChromaKeyFXNode::getHTolerance() const +float ChromaKeyFXNode::getHTolerance() const { return m_HTolerance; } -void ChromaKeyFXNode::setSTolerance(double tolerance) +void ChromaKeyFXNode::setSTolerance(float tolerance) { m_STolerance = tolerance; updateFilter(); } -double ChromaKeyFXNode::getSTolerance() const +float ChromaKeyFXNode::getSTolerance() const { return m_STolerance; } -void ChromaKeyFXNode::setLTolerance(double tolerance) +void ChromaKeyFXNode::setLTolerance(float tolerance) { m_LTolerance = tolerance; updateFilter(); } -double ChromaKeyFXNode::getLTolerance() const +float ChromaKeyFXNode::getLTolerance() const { return m_LTolerance; } -void ChromaKeyFXNode::setSoftness(double softness) +void ChromaKeyFXNode::setSoftness(float softness) { m_Softness = softness; updateFilter(); } -double ChromaKeyFXNode::getSoftness() const +float ChromaKeyFXNode::getSoftness() const { return m_Softness; } @@ -123,20 +122,20 @@ int ChromaKeyFXNode::getErosion() const return m_Erosion; } -void ChromaKeyFXNode::setSpillThreshold(double spillThreshold) +void ChromaKeyFXNode::setSpillThreshold(float spillThreshold) { m_SpillThreshold = spillThreshold; updateFilter(); } -double ChromaKeyFXNode::getSpillThreshold() const +float ChromaKeyFXNode::getSpillThreshold() const { return m_SpillThreshold; } GPUFilterPtr ChromaKeyFXNode::createFilter(const IntPoint& size) { - m_pFilter = GPUChromaKeyFilterPtr(new GPUChromaKeyFilter(size, B8G8R8A8, false)); + m_pFilter = GPUChromaKeyFilterPtr(new GPUChromaKeyFilter(size, false)); m_pFilter->setParams(m_Color, m_HTolerance, m_STolerance, m_LTolerance, m_Softness, m_Erosion, m_SpillThreshold); setDirty(); diff --git a/src/player/ChromaKeyFXNode.h b/src/player/ChromaKeyFXNode.h index c8cbe33..3653448 100644 --- a/src/player/ChromaKeyFXNode.h +++ b/src/player/ChromaKeyFXNode.h @@ -1,6 +1,6 @@ // // libavg - Media Playback Engine. -// Copyright (C) 2003-2011 Ulrich von Zadow +// Copyright (C) 2003-2014 Ulrich von Zadow // // This library is free software; you can redistribute it and/or // modify it under the terms of the GNU Lesser General Public @@ -40,18 +40,18 @@ public: void setColor(const std::string& sColorName); const std::string& getColor() const; - void setHTolerance(double tolerance); - double getHTolerance() const; - void setSTolerance(double tolerance); - double getSTolerance() const; - void setLTolerance(double tolerance); - double getLTolerance() const; - void setSoftness(double softness); - double getSoftness() const; + void setHTolerance(float tolerance); + float getHTolerance() const; + void setSTolerance(float tolerance); + float getSTolerance() const; + void setLTolerance(float tolerance); + float getLTolerance() const; + void setSoftness(float softness); + float getSoftness() const; void setErosion(int erosion); int getErosion() const; - void setSpillThreshold(double spillThreshold); - double getSpillThreshold() const; + void setSpillThreshold(float spillThreshold); + float getSpillThreshold() const; private: virtual GPUFilterPtr createFilter(const IntPoint& size); @@ -61,12 +61,12 @@ private: std::string m_sColorName; Pixel32 m_Color; - double m_HTolerance; - double m_STolerance; - double m_LTolerance; - double m_Softness; + float m_HTolerance; + float m_STolerance; + float m_LTolerance; + float m_Softness; int m_Erosion; - double m_SpillThreshold; + float m_SpillThreshold; }; typedef boost::shared_ptr<ChromaKeyFXNode> ChromaKeyFXNodePtr; diff --git a/src/player/CircleNode.cpp b/src/player/CircleNode.cpp index 1691d4d..8d00a8e 100644 --- a/src/player/CircleNode.cpp +++ b/src/player/CircleNode.cpp @@ -1,6 +1,6 @@ // // libavg - Media Playback Engine. -// Copyright (C) 2003-2011 Ulrich von Zadow +// Copyright (C) 2003-2014 Ulrich von Zadow // // This library is free software; you can redistribute it and/or // modify it under the terms of the GNU Lesser General Public @@ -21,9 +21,10 @@ #include "CircleNode.h" -#include "NodeDefinition.h" +#include "TypeDefinition.h" #include "../base/Exception.h" +#include "../base/MathHelper.h" #include <iostream> #include <sstream> @@ -32,15 +33,16 @@ using namespace std; namespace avg { -NodeDefinition CircleNode::createDefinition() +void CircleNode::registerType() { - return NodeDefinition("circle", Node::buildNode<CircleNode>) - .extendDefinition(FilledVectorNode::createDefinition()) - .addArg(Arg<DPoint>("pos", DPoint(0,0), false, offsetof(CircleNode, m_Pos))) - .addArg(Arg<double>("r", 1, false, offsetof(CircleNode, m_Radius))) - .addArg(Arg<double>("texcoord1", 0, false, offsetof(CircleNode, m_TC1))) - .addArg(Arg<double>("texcoord2", 1, false, offsetof(CircleNode, m_TC2))) + TypeDefinition def = TypeDefinition("circle", "filledvectornode", + ExportedObject::buildObject<CircleNode>) + .addArg(Arg<glm::vec2>("pos", glm::vec2(0,0), false, offsetof(CircleNode, m_Pos))) + .addArg(Arg<float>("r", 1, false, offsetof(CircleNode, m_Radius))) + .addArg(Arg<float>("texcoord1", 0, false, offsetof(CircleNode, m_TC1))) + .addArg(Arg<float>("texcoord2", 1, false, offsetof(CircleNode, m_TC2))) ; + TypeRegistry::get()->registerType(def); } CircleNode::CircleNode(const ArgList& args) @@ -53,23 +55,23 @@ CircleNode::~CircleNode() { } -const DPoint& CircleNode::getPos() const +const glm::vec2& CircleNode::getPos() const { return m_Pos; } -void CircleNode::setPos(const DPoint& pt) +void CircleNode::setPos(const glm::vec2& pt) { m_Pos = pt; setDrawNeeded(); } -double CircleNode::getR() const +float CircleNode::getR() const { return m_Radius; } -void CircleNode::setR(double r) +void CircleNode::setR(float r) { if (int(r) <= 0) { throw Exception(AVG_ERR_OUT_OF_RANGE, "Circle radius must be a positive number."); @@ -78,189 +80,191 @@ void CircleNode::setR(double r) setDrawNeeded(); } -double CircleNode::getTexCoord1() const +float CircleNode::getTexCoord1() const { return m_TC1; } -void CircleNode::setTexCoord1(double tc) +void CircleNode::setTexCoord1(float tc) { m_TC1 = tc; setDrawNeeded(); } -double CircleNode::getTexCoord2() const +float CircleNode::getTexCoord2() const { return m_TC2; } -void CircleNode::setTexCoord2(double tc) +void CircleNode::setTexCoord2(float tc) { m_TC2 = tc; setDrawNeeded(); } -void CircleNode::getElementsByPos(const DPoint& pos, vector<NodeWeakPtr>& pElements) +void CircleNode::getElementsByPos(const glm::vec2& pos, vector<NodePtr>& pElements) { - if (calcDist(pos, m_Pos) <= m_Radius && reactsToMouseEvents()) { - pElements.push_back(shared_from_this()); + if (glm::length(pos-m_Pos) <= m_Radius && reactsToMouseEvents()) { + pElements.push_back(getSharedThis()); } } -void CircleNode::calcVertexes(VertexArrayPtr& pVertexArray, Pixel32 color) +void CircleNode::calcVertexes(const VertexDataPtr& pVertexData, Pixel32 color) { // TODO: This gets called whenever the circle position changes and is quite // expensive. Should be optimized away. - DPoint firstPt1 = getCirclePt(0, m_Radius+getStrokeWidth()/2)+m_Pos; - DPoint firstPt2 = getCirclePt(0, m_Radius-getStrokeWidth()/2)+m_Pos; + glm::vec2 firstPt1 = getCirclePt(0, m_Radius+getStrokeWidth()/2)+m_Pos; + glm::vec2 firstPt2 = getCirclePt(0, m_Radius-getStrokeWidth()/2)+m_Pos; int curVertex = 0; - pVertexArray->appendPos(firstPt1, DPoint(m_TC1, 0), color); - pVertexArray->appendPos(firstPt2, DPoint(m_TC1, 1), color); - vector<DPoint> innerCircle; + pVertexData->appendPos(firstPt1, glm::vec2(m_TC1, 0), color); + pVertexData->appendPos(firstPt2, glm::vec2(m_TC1, 1), color); + vector<glm::vec2> innerCircle; getEigthCirclePoints(innerCircle, m_Radius-getStrokeWidth()/2); - vector<DPoint> outerCircle; + vector<glm::vec2> outerCircle; getEigthCirclePoints(outerCircle, m_Radius+getStrokeWidth()/2); - typedef vector<DPoint>::iterator DPointIt; - typedef vector<DPoint>::reverse_iterator DPointRIt; + typedef vector<glm::vec2>::iterator Vec2It; + typedef vector<glm::vec2>::reverse_iterator Vec2RIt; int i = 0; - for (DPointIt iit = innerCircle.begin()+1, oit = outerCircle.begin()+1; + for (Vec2It iit = innerCircle.begin()+1, oit = outerCircle.begin()+1; iit != innerCircle.end(); ++iit, ++oit) { - appendCirclePoint(pVertexArray, *iit, *oit, color, i, curVertex); + appendCirclePoint(pVertexData, *iit, *oit, color, i, curVertex); } - for (DPointRIt iit = innerCircle.rbegin()+1, oit = outerCircle.rbegin()+1; + for (Vec2RIt iit = innerCircle.rbegin()+1, oit = outerCircle.rbegin()+1; iit != innerCircle.rend(); ++iit, ++oit) { - DPoint iPt = DPoint(-iit->y, -iit->x); - DPoint oPt = DPoint(-oit->y, -oit->x); - appendCirclePoint(pVertexArray, iPt, oPt, color, i, curVertex); + glm::vec2 iPt = glm::vec2(-iit->y, -iit->x); + glm::vec2 oPt = glm::vec2(-oit->y, -oit->x); + appendCirclePoint(pVertexData, iPt, oPt, color, i, curVertex); } - for (DPointIt iit = innerCircle.begin()+1, oit = outerCircle.begin()+1; + for (Vec2It iit = innerCircle.begin()+1, oit = outerCircle.begin()+1; iit != innerCircle.end(); ++iit, ++oit) { - DPoint iPt = DPoint(-iit->y, iit->x); - DPoint oPt = DPoint(-oit->y, oit->x); - appendCirclePoint(pVertexArray, iPt, oPt, color, i, curVertex); + glm::vec2 iPt = glm::vec2(-iit->y, iit->x); + glm::vec2 oPt = glm::vec2(-oit->y, oit->x); + appendCirclePoint(pVertexData, iPt, oPt, color, i, curVertex); } - for (DPointRIt iit = innerCircle.rbegin()+1, oit = outerCircle.rbegin()+1; + for (Vec2RIt iit = innerCircle.rbegin()+1, oit = outerCircle.rbegin()+1; iit !=innerCircle.rend(); ++iit, ++oit) { - DPoint iPt = DPoint(iit->x, -iit->y); - DPoint oPt = DPoint(oit->x, -oit->y); - appendCirclePoint(pVertexArray, iPt, oPt, color, i, curVertex); + glm::vec2 iPt = glm::vec2(iit->x, -iit->y); + glm::vec2 oPt = glm::vec2(oit->x, -oit->y); + appendCirclePoint(pVertexData, iPt, oPt, color, i, curVertex); } - for (DPointIt iit = innerCircle.begin()+1, oit = outerCircle.begin()+1; + for (Vec2It iit = innerCircle.begin()+1, oit = outerCircle.begin()+1; iit != innerCircle.end(); ++iit, ++oit) { - DPoint iPt = DPoint(-iit->x, -iit->y); - DPoint oPt = DPoint(-oit->x, -oit->y); - appendCirclePoint(pVertexArray, iPt, oPt, color, i, curVertex); + glm::vec2 iPt = glm::vec2(-iit->x, -iit->y); + glm::vec2 oPt = glm::vec2(-oit->x, -oit->y); + appendCirclePoint(pVertexData, iPt, oPt, color, i, curVertex); } - for (DPointRIt iit = innerCircle.rbegin()+1, oit = outerCircle.rbegin()+1; + for (Vec2RIt iit = innerCircle.rbegin()+1, oit = outerCircle.rbegin()+1; iit != innerCircle.rend(); ++iit, ++oit) { - DPoint iPt = DPoint(iit->y, iit->x); - DPoint oPt = DPoint(oit->y, oit->x); - appendCirclePoint(pVertexArray, iPt, oPt, color, i, curVertex); + glm::vec2 iPt = glm::vec2(iit->y, iit->x); + glm::vec2 oPt = glm::vec2(oit->y, oit->x); + appendCirclePoint(pVertexData, iPt, oPt, color, i, curVertex); } - for (DPointIt iit = innerCircle.begin()+1, oit = outerCircle.begin()+1; + for (Vec2It iit = innerCircle.begin()+1, oit = outerCircle.begin()+1; iit != innerCircle.end(); ++iit, ++oit) { - DPoint iPt = DPoint(iit->y, -iit->x); - DPoint oPt = DPoint(oit->y, -oit->x); - appendCirclePoint(pVertexArray, iPt, oPt, color, i, curVertex); + glm::vec2 iPt = glm::vec2(iit->y, -iit->x); + glm::vec2 oPt = glm::vec2(oit->y, -oit->x); + appendCirclePoint(pVertexData, iPt, oPt, color, i, curVertex); } - for (DPointRIt iit = innerCircle.rbegin()+1, oit = outerCircle.rbegin()+1; + for (Vec2RIt iit = innerCircle.rbegin()+1, oit = outerCircle.rbegin()+1; iit != innerCircle.rend(); ++iit, ++oit) { - DPoint iPt = DPoint(-iit->x, iit->y); - DPoint oPt = DPoint(-oit->x, oit->y); - appendCirclePoint(pVertexArray, iPt, oPt, color, i, curVertex); + glm::vec2 iPt = glm::vec2(-iit->x, iit->y); + glm::vec2 oPt = glm::vec2(-oit->x, oit->y); + appendCirclePoint(pVertexData, iPt, oPt, color, i, curVertex); } } -void CircleNode::calcFillVertexes(VertexArrayPtr& pVertexArray, Pixel32 color) +void CircleNode::calcFillVertexes(const VertexDataPtr& pVertexData, Pixel32 color) { - DPoint minPt = m_Pos-DPoint(m_Radius, m_Radius); - DPoint maxPt = m_Pos+DPoint(m_Radius, m_Radius); - DPoint centerTexCoord = calcFillTexCoord(m_Pos, minPt, maxPt); - pVertexArray->appendPos(m_Pos, centerTexCoord, color); + glm::vec2 minPt = m_Pos-glm::vec2(m_Radius, m_Radius); + glm::vec2 maxPt = m_Pos+glm::vec2(m_Radius, m_Radius); + glm::vec2 centerTexCoord = calcFillTexCoord(m_Pos, minPt, maxPt); + pVertexData->appendPos(m_Pos, centerTexCoord, color); int curVertex = 1; - DPoint firstPt = getCirclePt(0, m_Radius)+m_Pos; - DPoint firstTexCoord = calcFillTexCoord(firstPt, minPt, maxPt); - pVertexArray->appendPos(firstPt, firstTexCoord, color); - vector<DPoint> circlePoints; + glm::vec2 firstPt = getCirclePt(0, m_Radius)+m_Pos; + glm::vec2 firstTexCoord = calcFillTexCoord(firstPt, minPt, maxPt); + pVertexData->appendPos(firstPt, firstTexCoord, color); + vector<glm::vec2> circlePoints; getEigthCirclePoints(circlePoints, m_Radius); - for (vector<DPoint>::iterator it = circlePoints.begin()+1; it != circlePoints.end(); - ++it) + for (vector<glm::vec2>::iterator it = circlePoints.begin()+1; + it != circlePoints.end(); ++it) { - DPoint curPt = *it+m_Pos; - appendFillCirclePoint(pVertexArray, curPt, minPt, maxPt, color, curVertex); + glm::vec2 curPt = *it+m_Pos; + appendFillCirclePoint(pVertexData, curPt, minPt, maxPt, color, curVertex); } - for (vector<DPoint>::reverse_iterator it = circlePoints.rbegin()+1; + for (vector<glm::vec2>::reverse_iterator it = circlePoints.rbegin()+1; it != circlePoints.rend(); ++it) { - DPoint curPt = DPoint(-it->y, -it->x)+m_Pos; - appendFillCirclePoint(pVertexArray, curPt, minPt, maxPt, color, curVertex); + glm::vec2 curPt = glm::vec2(-it->y, -it->x)+m_Pos; + appendFillCirclePoint(pVertexData, curPt, minPt, maxPt, color, curVertex); } - for (vector<DPoint>::iterator it = circlePoints.begin()+1; it != circlePoints.end(); - ++it) + for (vector<glm::vec2>::iterator it = circlePoints.begin()+1; + it != circlePoints.end(); ++it) { - DPoint curPt = DPoint(-it->y, it->x)+m_Pos; - appendFillCirclePoint(pVertexArray, curPt, minPt, maxPt, color, curVertex); + glm::vec2 curPt = glm::vec2(-it->y, it->x)+m_Pos; + appendFillCirclePoint(pVertexData, curPt, minPt, maxPt, color, curVertex); } - for (vector<DPoint>::reverse_iterator it = circlePoints.rbegin()+1; + for (vector<glm::vec2>::reverse_iterator it = circlePoints.rbegin()+1; it != circlePoints.rend(); ++it) { - DPoint curPt = DPoint(it->x, -it->y)+m_Pos; - appendFillCirclePoint(pVertexArray, curPt, minPt, maxPt, color, curVertex); + glm::vec2 curPt = glm::vec2(it->x, -it->y)+m_Pos; + appendFillCirclePoint(pVertexData, curPt, minPt, maxPt, color, curVertex); } - for (vector<DPoint>::iterator it = circlePoints.begin()+1; it != circlePoints.end(); - ++it) + for (vector<glm::vec2>::iterator it = circlePoints.begin()+1; + it != circlePoints.end(); ++it) { - DPoint curPt = DPoint(-it->x, -it->y)+m_Pos; - appendFillCirclePoint(pVertexArray, curPt, minPt, maxPt, color, curVertex); + glm::vec2 curPt = glm::vec2(-it->x, -it->y)+m_Pos; + appendFillCirclePoint(pVertexData, curPt, minPt, maxPt, color, curVertex); } - for (vector<DPoint>::reverse_iterator it = circlePoints.rbegin()+1; + for (vector<glm::vec2>::reverse_iterator it = circlePoints.rbegin()+1; it != circlePoints.rend(); ++it) { - DPoint curPt = DPoint(it->y, it->x)+m_Pos; - appendFillCirclePoint(pVertexArray, curPt, minPt, maxPt, color, curVertex); + glm::vec2 curPt = glm::vec2(it->y, it->x)+m_Pos; + appendFillCirclePoint(pVertexData, curPt, minPt, maxPt, color, curVertex); } - for (vector<DPoint>::iterator it = circlePoints.begin()+1; it != circlePoints.end(); - ++it) + for (vector<glm::vec2>::iterator it = circlePoints.begin()+1; + it != circlePoints.end(); ++it) { - DPoint curPt = DPoint(it->y, -it->x)+m_Pos; - appendFillCirclePoint(pVertexArray, curPt, minPt, maxPt, color, curVertex); + glm::vec2 curPt = glm::vec2(it->y, -it->x)+m_Pos; + appendFillCirclePoint(pVertexData, curPt, minPt, maxPt, color, curVertex); } - for (vector<DPoint>::reverse_iterator it = circlePoints.rbegin()+1; + for (vector<glm::vec2>::reverse_iterator it = circlePoints.rbegin()+1; it != circlePoints.rend(); ++it) { - DPoint curPt = DPoint(-it->x, it->y)+m_Pos; - appendFillCirclePoint(pVertexArray, curPt, minPt, maxPt, color, curVertex); + glm::vec2 curPt = glm::vec2(-it->x, it->y)+m_Pos; + appendFillCirclePoint(pVertexData, curPt, minPt, maxPt, color, curVertex); } } -void CircleNode::appendCirclePoint(VertexArrayPtr& pVertexArray, const DPoint& iPt, - const DPoint& oPt, Pixel32 color, int& i, int& curVertex) +void CircleNode::appendCirclePoint(const VertexDataPtr& pVertexData, + const glm::vec2& iPt, const glm::vec2& oPt, Pixel32 color, int& i, + int& curVertex) { i++; - double ratio = (double(i)/getNumCircumferencePoints()); - double curTC = (1-ratio)*m_TC1+ratio*m_TC2; - pVertexArray->appendPos(oPt+m_Pos, DPoint(curTC, 0), color); - pVertexArray->appendPos(iPt+m_Pos, DPoint(curTC, 1), color); - pVertexArray->appendQuadIndexes(curVertex+1, curVertex, curVertex+3, curVertex+2); + float ratio = (float(i)/getNumCircumferencePoints()); + float curTC = (1-ratio)*m_TC1+ratio*m_TC2; + pVertexData->appendPos(oPt+m_Pos, glm::vec2(curTC, 0), color); + pVertexData->appendPos(iPt+m_Pos, glm::vec2(curTC, 1), color); + pVertexData->appendQuadIndexes(curVertex+1, curVertex, curVertex+3, curVertex+2); curVertex += 2; } -void CircleNode::appendFillCirclePoint(VertexArrayPtr& pVertexArray, const DPoint& curPt, - const DPoint& minPt, const DPoint& maxPt, Pixel32 color, int& curVertex) +void CircleNode::appendFillCirclePoint(const VertexDataPtr& pVertexData, + const glm::vec2& curPt, const glm::vec2& minPt, const glm::vec2& maxPt, + Pixel32 color, int& curVertex) { - DPoint curTexCoord = calcFillTexCoord(curPt, minPt, maxPt); - pVertexArray->appendPos(curPt, curTexCoord, color); - pVertexArray->appendTriIndexes(0, curVertex, curVertex+1); + glm::vec2 curTexCoord = calcFillTexCoord(curPt, minPt, maxPt); + pVertexData->appendPos(curPt, curTexCoord, color); + pVertexData->appendTriIndexes(0, curVertex, curVertex+1); curVertex++; } @@ -269,19 +273,19 @@ int CircleNode::getNumCircumferencePoints() return int(ceil((m_Radius*3)/8)*8); } -void CircleNode::getEigthCirclePoints(vector<DPoint>& pts, double radius) +void CircleNode::getEigthCirclePoints(vector<glm::vec2>& pts, float radius) { int numPts = getNumCircumferencePoints(); for (int i = 0; i <= numPts/8; ++i) { - double ratio = (double(i)/numPts); - double angle = ratio*2*3.14159; + float ratio = (float(i)/numPts); + float angle = ratio*2*PI; pts.push_back(getCirclePt(angle, radius)); } } -DPoint CircleNode::getCirclePt(double angle, double radius) +glm::vec2 CircleNode::getCirclePt(float angle, float radius) { - return DPoint(sin(angle)*radius, -cos(angle)*radius); + return glm::vec2(sin(angle)*radius, -cos(angle)*radius); } } diff --git a/src/player/CircleNode.h b/src/player/CircleNode.h index 10ce112..afc4160 100644 --- a/src/player/CircleNode.h +++ b/src/player/CircleNode.h @@ -1,6 +1,6 @@ // // libavg - Media Playback Engine. -// Copyright (C) 2003-2011 Ulrich von Zadow +// Copyright (C) 2003-2014 Ulrich von Zadow // // This library is free software; you can redistribute it and/or // modify it under the terms of the GNU Lesser General Public @@ -32,41 +32,43 @@ namespace avg { class AVG_API CircleNode : public FilledVectorNode { public: - static NodeDefinition createDefinition(); + static void registerType(); CircleNode(const ArgList& args); virtual ~CircleNode(); - const DPoint& getPos() const; - void setPos(const DPoint& pt); + const glm::vec2& getPos() const; + void setPos(const glm::vec2& pt); - double getR() const; - void setR(double r); + float getR() const; + void setR(float r); - double getTexCoord1() const; - void setTexCoord1(double tc); + float getTexCoord1() const; + void setTexCoord1(float tc); - double getTexCoord2() const; - void setTexCoord2(double tc); + float getTexCoord2() const; + void setTexCoord2(float tc); - void getElementsByPos(const DPoint& pos, std::vector<NodeWeakPtr>& pElements); - virtual void calcVertexes(VertexArrayPtr& pVertexArray, Pixel32 color); - virtual void calcFillVertexes(VertexArrayPtr& pVertexArray, Pixel32 color); + void getElementsByPos(const glm::vec2& pos, std::vector<NodePtr>& pElements); + virtual void calcVertexes(const VertexDataPtr& pVertexData, Pixel32 color); + virtual void calcFillVertexes(const VertexDataPtr& pVertexData, Pixel32 color); private: - void appendCirclePoint(VertexArrayPtr& pVertexArray, const DPoint& iPt, - const DPoint& oPt, Pixel32 color, int& i, int& curVertex); - void appendFillCirclePoint(VertexArrayPtr& pVertexArray, const DPoint& curPt, - const DPoint& minPt, const DPoint& maxPt, Pixel32 color, int& curVertex); + void appendCirclePoint(const VertexDataPtr& pVertexData, const glm::vec2& iPt, + const glm::vec2& oPt, Pixel32 color, int& i, int& curVertex); + void appendFillCirclePoint(const VertexDataPtr& pVertexData, + const glm::vec2& curPt, const glm::vec2& minPt, const glm::vec2& maxPt, + Pixel32 color, int& curVertex); int getNumCircumferencePoints(); - void getEigthCirclePoints(std::vector<DPoint>& pts, double radius); - DPoint getCirclePt(double angle, double radius); - DPoint calcTexCoord(const DPoint& pt, const DPoint& minPt, const DPoint& maxPt); + void getEigthCirclePoints(std::vector<glm::vec2>& pts, float radius); + glm::vec2 getCirclePt(float angle, float radius); + glm::vec2 calcTexCoord(const glm::vec2& pt, const glm::vec2& minPt, + const glm::vec2& maxPt); - DPoint m_Pos; - double m_Radius; - double m_TC1; - double m_TC2; + glm::vec2 m_Pos; + float m_Radius; + float m_TC1; + float m_TC2; }; } diff --git a/src/player/Contact.cpp b/src/player/Contact.cpp index a19abcc..b80615a 100644 --- a/src/player/Contact.cpp +++ b/src/player/Contact.cpp @@ -1,6 +1,6 @@ // // libavg - Media Playback Engine. -// Copyright (C) 2003-2011 Ulrich von Zadow +// Copyright (C) 2003-2014 Ulrich von Zadow // // This library is free software; you can redistribute it and/or // modify it under the terms of the GNU Lesser General Public @@ -24,9 +24,11 @@ #include "CursorEvent.h" #include "BoostPython.h" #include "Player.h" +#include "PublisherDefinition.h" #include "../base/Exception.h" #include "../base/StringHelper.h" +#include "../base/Logger.h" #include <iostream> @@ -36,8 +38,16 @@ namespace avg { int Contact::s_LastListenerID = 0; +void Contact::registerType() +{ + PublisherDefinitionPtr pPubDef = PublisherDefinition::create("Contact"); + pPubDef->addMessage("CURSOR_MOTION"); + pPubDef->addMessage("CURSOR_UP"); +} + Contact::Contact(CursorEventPtr pEvent) - : m_bSendingEvents(false), + : Publisher("Contact"), + m_bSendingEvents(false), m_bCurListenerIsDead(false), m_CursorID(pEvent->getCursorID()), m_DistanceTravelled(0) @@ -51,6 +61,7 @@ Contact::~Contact() int Contact::connectListener(PyObject* pMotionCallback, PyObject* pUpCallback) { + avgDeprecationWarning("1.8", "Contact.connectListener()", "Contact.subscribe()"); s_LastListenerID++; pair<int, Listener> val = pair<int, Listener>(s_LastListenerID, Listener(pMotionCallback, pUpCallback)); @@ -60,6 +71,8 @@ int Contact::connectListener(PyObject* pMotionCallback, PyObject* pUpCallback) void Contact::disconnectListener(int id) { + avgDeprecationWarning("1.8", "Contact.disconnectListener()", + "Contact.unsubscribe()"); map<int, Listener>::iterator it = m_ListenerMap.find(id); if (it == m_ListenerMap.end() || (m_CurListenerID == id && m_bCurListenerIsDead)) { throw Exception(AVG_ERR_INVALID_ARGS, @@ -77,27 +90,27 @@ long long Contact::getAge() const return m_Events.back()->getWhen() - m_Events[0]->getWhen(); } -double Contact::getDistanceFromStart() const +float Contact::getDistanceFromStart() const { - return getMotionVec().getNorm(); + return glm::length(getMotionVec()); } -double Contact::getMotionAngle() const +float Contact::getMotionAngle() const { - DPoint motion = getMotionVec(); - if (motion == DPoint(0,0)) { + glm::vec2 motion = getMotionVec(); + if (motion == glm::vec2(0,0)) { return 0; } else { - return motion.getAngle(); + return getAngle(motion); } } -DPoint Contact::getMotionVec() const +glm::vec2 Contact::getMotionVec() const { return m_Events.back()->getPos() - m_Events[0]->getPos(); } -double Contact::getDistanceTravelled() const +float Contact::getDistanceTravelled() const { return m_DistanceTravelled; } @@ -110,24 +123,31 @@ vector<CursorEventPtr> Contact::getEvents() const void Contact::addEvent(CursorEventPtr pEvent) { pEvent->setCursorID(m_CursorID); - pEvent->setContact(shared_from_this()); + pEvent->setContact(boost::dynamic_pointer_cast<Contact>(shared_from_this())); calcSpeed(pEvent, m_Events.back()); updateDistanceTravelled(m_Events.back(), pEvent); m_Events.back()->removeBlob(); + m_Events.back()->setNode(NodePtr()); m_Events.push_back(pEvent); } -bool Contact::hasListeners() const -{ - return !(m_ListenerMap.empty() || - (m_ListenerMap.size() == 1 && m_bCurListenerIsDead)); -} - void Contact::sendEventToListeners(CursorEventPtr pCursorEvent) { + switch (pCursorEvent->getType()) { + case Event::CURSOR_DOWN: + break; + case Event::CURSOR_MOTION: + notifySubscribers("CURSOR_MOTION", pCursorEvent); + break; + case Event::CURSOR_UP: + notifySubscribers("CURSOR_UP", pCursorEvent); + removeSubscribers(); + break; + default: + AVG_ASSERT_MSG(false, pCursorEvent->typeStr().c_str()); + } m_bSendingEvents = true; AVG_ASSERT(pCursorEvent->getContact() == shared_from_this()); - EventPtr pEvent = boost::dynamic_pointer_cast<Event>(pCursorEvent); m_bCurListenerIsDead = false; for (map<int, Listener>::iterator it = m_ListenerMap.begin(); it != m_ListenerMap.end();) @@ -136,14 +156,14 @@ void Contact::sendEventToListeners(CursorEventPtr pCursorEvent) m_CurListenerID = it->first; m_bCurListenerIsDead = false; switch (pCursorEvent->getType()) { - case Event::CURSORMOTION: + case Event::CURSOR_MOTION: if (listener.m_pMotionCallback != Py_None) { - boost::python::call<void>(listener.m_pMotionCallback, pEvent); + py::call<void>(listener.m_pMotionCallback, pCursorEvent); } break; - case Event::CURSORUP: + case Event::CURSOR_UP: if (listener.m_pUpCallback != Py_None) { - boost::python::call<void>(listener.m_pUpCallback, pEvent); + py::call<void>(listener.m_pUpCallback, pCursorEvent); } break; default: @@ -164,36 +184,20 @@ int Contact::getID() const return m_CursorID; } -bool Contact::operator ==(const Contact& other) const -{ - return (shared_from_this() == other.shared_from_this()); -} - -bool Contact::operator !=(const Contact& other) const -{ - return (shared_from_this() != other.shared_from_this()); -} - -long Contact::getHash() const -{ - return long(&*shared_from_this()); - -} - void Contact::calcSpeed(CursorEventPtr pEvent, CursorEventPtr pOldEvent) { - if (pEvent->getSpeed() == DPoint(0,0)) { - DPoint posDiff = pEvent->getPos() - pOldEvent->getPos(); + if (pEvent->getSpeed() == glm::vec2(0,0)) { + glm::vec2 posDiff = pEvent->getPos() - pOldEvent->getPos(); long long timeDiff = pEvent->getWhen() - pOldEvent->getWhen(); if (timeDiff != 0) { - pEvent->setSpeed(posDiff/double(timeDiff)); + pEvent->setSpeed(posDiff/float(timeDiff)); } } } void Contact::updateDistanceTravelled(CursorEventPtr pEvent1, CursorEventPtr pEvent2) { - double dist = (pEvent2->getPos() - pEvent1->getPos()).getNorm(); + float dist = glm::length(pEvent2->getPos() - pEvent1->getPos()); m_DistanceTravelled += dist; } diff --git a/src/player/Contact.h b/src/player/Contact.h index 922dff8..846b422 100644 --- a/src/player/Contact.h +++ b/src/player/Contact.h @@ -1,6 +1,6 @@ // // libavg - Media Playback Engine. -// Copyright (C) 2003-2011 Ulrich von Zadow +// Copyright (C) 2003-2014 Ulrich von Zadow // // This library is free software; you can redistribute it and/or // modify it under the terms of the GNU Lesser General Public @@ -22,7 +22,9 @@ #ifndef _Contact_H_ #define _Contact_H_ -#include "../base/Point.h" +#include "Publisher.h" + +#include "../base/GLMHelper.h" #include <boost/shared_ptr.hpp> #include <boost/weak_ptr.hpp> @@ -41,10 +43,10 @@ class CursorEvent; typedef boost::shared_ptr<class CursorEvent> CursorEventPtr; class Contact; typedef boost::shared_ptr<class Contact> ContactPtr; -//typedef boost::weak_ptr<class Contact> ContactWeakPtr; -class AVG_API Contact: public boost::enable_shared_from_this<Contact> { +class AVG_API Contact: public Publisher { public: + static void registerType(); Contact(CursorEventPtr pEvent); virtual ~Contact(); @@ -52,22 +54,17 @@ public: void disconnectListener(int id); long long getAge() const; - double getDistanceFromStart() const; - double getMotionAngle() const; - DPoint getMotionVec() const; - double getDistanceTravelled() const; + float getDistanceFromStart() const; + float getMotionAngle() const; + glm::vec2 getMotionVec() const; + float getDistanceTravelled() const; std::vector<CursorEventPtr> getEvents() const; void addEvent(CursorEventPtr pEvent); - bool hasListeners() const; void sendEventToListeners(CursorEventPtr pCursorEvent); int getID() const; - bool operator ==(const Contact& other) const; - bool operator !=(const Contact& other) const; - long getHash() const; - private: void calcSpeed(CursorEventPtr pEvent, CursorEventPtr pOldEvent); void updateDistanceTravelled(CursorEventPtr pEvent1, CursorEventPtr pEvent2); @@ -91,7 +88,7 @@ private: int m_CurListenerID; bool m_bCurListenerIsDead; int m_CursorID; - double m_DistanceTravelled; + float m_DistanceTravelled; }; } diff --git a/src/player/CursorEvent.cpp b/src/player/CursorEvent.cpp index df71c5c..ee4ba92 100644 --- a/src/player/CursorEvent.cpp +++ b/src/player/CursorEvent.cpp @@ -1,6 +1,6 @@ // // libavg - Media Playback Engine. -// Copyright (C) 2003-2011 Ulrich von Zadow +// Copyright (C) 2003-2014 Ulrich von Zadow // // This library is free software; you can redistribute it and/or // modify it under the terms of the GNU Lesser General Public @@ -55,14 +55,14 @@ CursorEventPtr CursorEvent::cloneAs(Type eventType) const return pClone; } -void CursorEvent::setPos(const DPoint& pos) +void CursorEvent::setPos(const glm::vec2& pos) { m_Position = IntPoint(pos); } -DPoint CursorEvent::getPos() const +glm::vec2 CursorEvent::getPos() const { - return DPoint(m_Position); + return glm::vec2(m_Position); } int CursorEvent::getXPosition() const @@ -92,15 +92,15 @@ void CursorEvent::setNode(NodePtr pNode) NodePtr CursorEvent::getNode() const { - return m_pNode.lock(); + return m_pNode; } -void CursorEvent::setSpeed(DPoint speed) +void CursorEvent::setSpeed(glm::vec2 speed) { m_Speed = speed; } -const DPoint& CursorEvent::getSpeed() const +const glm::vec2& CursorEvent::getSpeed() const { return m_Speed; } @@ -124,10 +124,11 @@ bool operator ==(const CursorEvent& event1, const CursorEvent& event2) void CursorEvent::trace() { string sType = typeStr(); - if (m_pNode.expired()) { - AVG_TRACE(Logger::EVENTS, sType); + if (!m_pNode) { + AVG_TRACE(Logger::category::EVENTS, Logger::severity::DEBUG, sType); } else { - AVG_TRACE(Logger::EVENTS, m_pNode.lock()->getID()+", "+sType); + AVG_TRACE(Logger::category::EVENTS, Logger::severity::DEBUG, + m_pNode->getID()+", "+sType); } } diff --git a/src/player/CursorEvent.h b/src/player/CursorEvent.h index 5c6e699..e84272a 100644 --- a/src/player/CursorEvent.h +++ b/src/player/CursorEvent.h @@ -1,6 +1,6 @@ // // libavg - Media Playback Engine. -// Copyright (C) 2003-2011 Ulrich von Zadow +// Copyright (C) 2003-2014 Ulrich von Zadow // // This library is free software; you can redistribute it and/or // modify it under the terms of the GNU Lesser General Public @@ -27,7 +27,7 @@ #include "../api.h" #include "Event.h" -#include "../base/Point.h" +#include "../base/GLMHelper.h" #include <boost/shared_ptr.hpp> #include <boost/weak_ptr.hpp> @@ -54,16 +54,16 @@ class AVG_API CursorEvent: public Event int when=-1); virtual ~CursorEvent(); virtual CursorEventPtr cloneAs(Type eventType) const; - void setPos(const DPoint& pos); - DPoint getPos() const; + void setPos(const glm::vec2& pos); + glm::vec2 getPos() const; int getXPosition() const; int getYPosition() const; void setCursorID(int id); int getCursorID() const; void setNode(NodePtr pNode); NodePtr getNode() const; - void setSpeed(DPoint speed); - virtual const DPoint& getSpeed() const; + void setSpeed(glm::vec2 speed); + virtual const glm::vec2& getSpeed() const; void setContact(ContactPtr pContact); ContactPtr getContact() const; @@ -76,8 +76,8 @@ class AVG_API CursorEvent: public Event IntPoint m_Position; int m_ID; ContactWeakPtr m_pContact; - NodeWeakPtr m_pNode; - DPoint m_Speed; + NodePtr m_pNode; + glm::vec2 m_Speed; }; bool operator ==(const CursorEvent& event1, const CursorEvent& event2); diff --git a/src/player/CursorState.cpp b/src/player/CursorState.cpp index d1f52bb..4408946 100644 --- a/src/player/CursorState.cpp +++ b/src/player/CursorState.cpp @@ -1,6 +1,6 @@ // // libavg - Media Playback Engine. -// Copyright (C) 2003-2011 Ulrich von Zadow +// Copyright (C) 2003-2014 Ulrich von Zadow // // This library is free software; you can redistribute it and/or // modify it under the terms of the GNU Lesser General Public @@ -27,7 +27,7 @@ using namespace std; namespace avg { CursorState::CursorState(const CursorEventPtr pEvent, - const vector<NodeWeakPtr>& pNodes) + const vector<NodePtr>& pNodes) : m_pNodes(pNodes) { m_pLastEvent = pEvent; @@ -38,13 +38,13 @@ CursorState::~CursorState() } void CursorState::setInfo(const CursorEventPtr pEvent, - const vector<NodeWeakPtr>& pNodes) + const vector<NodePtr>& pNodes) { m_pLastEvent = pEvent; m_pNodes = pNodes; } -const vector<NodeWeakPtr>& CursorState::getNodes() const +const vector<NodePtr>& CursorState::getNodes() const { return m_pNodes; } diff --git a/src/player/CursorState.h b/src/player/CursorState.h index b9d7693..8cec4c7 100644 --- a/src/player/CursorState.h +++ b/src/player/CursorState.h @@ -1,6 +1,6 @@ // // libavg - Media Playback Engine. -// Copyright (C) 2003-2011 Ulrich von Zadow +// Copyright (C) 2003-2014 Ulrich von Zadow // // This library is free software; you can redistribute it and/or // modify it under the terms of the GNU Lesser General Public @@ -30,23 +30,23 @@ namespace avg { class Node; -typedef boost::weak_ptr<Node> NodeWeakPtr; +typedef boost::shared_ptr<Node> NodePtr; class CursorEvent; typedef boost::shared_ptr<CursorEvent> CursorEventPtr; class AVG_API CursorState { public: - CursorState(const CursorEventPtr pEvent, const std::vector<NodeWeakPtr>& pNodes); + CursorState(const CursorEventPtr pEvent, const std::vector<NodePtr>& pNodes); ~CursorState(); - void setInfo(const CursorEventPtr pEvent, const std::vector<NodeWeakPtr>& pNodes); - const std::vector<NodeWeakPtr>& getNodes() const; + void setInfo(const CursorEventPtr pEvent, const std::vector<NodePtr>& pNodes); + const std::vector<NodePtr>& getNodes() const; CursorEventPtr getLastEvent() const; private: CursorState(const CursorState&); - std::vector<NodeWeakPtr> m_pNodes; + std::vector<NodePtr> m_pNodes; CursorEventPtr m_pLastEvent; }; diff --git a/src/player/CurveNode.cpp b/src/player/CurveNode.cpp index adaabe5..7a685f5 100644 --- a/src/player/CurveNode.cpp +++ b/src/player/CurveNode.cpp @@ -1,6 +1,6 @@ // // libavg - Media Playback Engine. -// Copyright (C) 2003-2011 Ulrich von Zadow +// Copyright (C) 2003-2014 Ulrich von Zadow // // This library is free software; you can redistribute it and/or // modify it under the terms of the GNU Lesser General Public @@ -21,7 +21,7 @@ #include "CurveNode.h" -#include "NodeDefinition.h" +#include "TypeDefinition.h" #include "../graphics/VertexArray.h" #include "../base/Exception.h" @@ -37,16 +37,17 @@ using namespace std; namespace avg { -NodeDefinition CurveNode::createDefinition() +void CurveNode::registerType() { - return NodeDefinition("curve", Node::buildNode<CurveNode>) - .extendDefinition(VectorNode::createDefinition()) - .addArg(Arg<DPoint>("pos1", DPoint(0,0), false, offsetof(CurveNode, m_P1))) - .addArg(Arg<DPoint>("pos2", DPoint(0,0), false, offsetof(CurveNode, m_P2))) - .addArg(Arg<DPoint>("pos3", DPoint(0,0), false, offsetof(CurveNode, m_P3))) - .addArg(Arg<DPoint>("pos4", DPoint(0,0), false, offsetof(CurveNode, m_P4))) - .addArg(Arg<double>("texcoord1", 0, true, offsetof(CurveNode, m_TC1))) - .addArg(Arg<double>("texcoord2", 1, true, offsetof(CurveNode, m_TC2))); + TypeDefinition def = TypeDefinition("curve", "vectornode", + ExportedObject::buildObject<CurveNode>) + .addArg(Arg<glm::vec2>("pos1", glm::vec2(0,0), false, offsetof(CurveNode, m_P1))) + .addArg(Arg<glm::vec2>("pos2", glm::vec2(0,0), false, offsetof(CurveNode, m_P2))) + .addArg(Arg<glm::vec2>("pos3", glm::vec2(0,0), false, offsetof(CurveNode, m_P3))) + .addArg(Arg<glm::vec2>("pos4", glm::vec2(0,0), false, offsetof(CurveNode, m_P4))) + .addArg(Arg<float>("texcoord1", 0, true, offsetof(CurveNode, m_TC1))) + .addArg(Arg<float>("texcoord2", 1, true, offsetof(CurveNode, m_TC2))); + TypeRegistry::get()->registerType(def); } CurveNode::CurveNode(const ArgList& args) @@ -59,118 +60,122 @@ CurveNode::~CurveNode() { } -const DPoint& CurveNode::getPos1() const +const glm::vec2& CurveNode::getPos1() const { return m_P1; } -void CurveNode::setPos1(const DPoint& pt) +void CurveNode::setPos1(const glm::vec2& pt) { m_P1 = pt; setDrawNeeded(); } -const DPoint& CurveNode::getPos2() const +const glm::vec2& CurveNode::getPos2() const { return m_P2; } -void CurveNode::setPos2(const DPoint& pt) +void CurveNode::setPos2(const glm::vec2& pt) { m_P2 = pt; setDrawNeeded(); } -const DPoint& CurveNode::getPos3() const +const glm::vec2& CurveNode::getPos3() const { return m_P3; } -void CurveNode::setPos3(const DPoint& pt) +void CurveNode::setPos3(const glm::vec2& pt) { m_P3 = pt; setDrawNeeded(); } -const DPoint& CurveNode::getPos4() const +const glm::vec2& CurveNode::getPos4() const { return m_P4; } -void CurveNode::setPos4(const DPoint& pt) +void CurveNode::setPos4(const glm::vec2& pt) { m_P4 = pt; setDrawNeeded(); } -double CurveNode::getTexCoord1() const +float CurveNode::getTexCoord1() const { return m_TC1; } -void CurveNode::setTexCoord1(double tc) +void CurveNode::setTexCoord1(float tc) { m_TC1 = tc; setDrawNeeded(); } -double CurveNode::getTexCoord2() const +float CurveNode::getTexCoord2() const { return m_TC2; } -void CurveNode::setTexCoord2(double tc) +void CurveNode::setTexCoord2(float tc) { m_TC2 = tc; setDrawNeeded(); } + +int CurveNode::getCurveLen() const +{ + // Calc. upper bound for spline length. + float curveLen = glm::length(m_P2-m_P1) + glm::length(m_P3 - m_P2) + + glm::length(m_P4-m_P3); + return int(curveLen); +} -void CurveNode::calcVertexes(VertexArrayPtr& pVertexArray, Pixel32 color) +glm::vec2 CurveNode::getPtOnCurve(float t) const { - updateLines(); - - pVertexArray->appendPos(m_LeftCurve[0], DPoint(m_TC1,1), color); - pVertexArray->appendPos(m_RightCurve[0], DPoint(m_TC2,0), color); - for (unsigned i = 0; i < m_LeftCurve.size()-1; ++i) { - double ratio = i/double(m_LeftCurve.size()); - double tc = (1-ratio)*m_TC1+ratio*m_TC2; - pVertexArray->appendPos(m_LeftCurve[i+1], DPoint(tc,1), color); - pVertexArray->appendPos(m_RightCurve[i+1], DPoint(tc,0), color); - pVertexArray->appendQuadIndexes((i+1)*2, i*2, (i+1)*2+1, i*2+1); - } + BezierCurve curve(m_P1, m_P2, m_P3, m_P4); + return curve.interpolate(t); } -int CurveNode::getCurveLen() +void CurveNode::calcVertexes(const VertexDataPtr& pVertexData, Pixel32 color) { - // Calc. upper bound for spline length. - double curveLen = calcDist(m_P2,m_P1)+calcDist(m_P3,m_P2)+calcDist(m_P4,m_P3); - if (curveLen > 50000) { - throw Exception(AVG_ERR_OUT_OF_RANGE, "Illegal points in curve."); + updateLines(); + + pVertexData->appendPos(m_LeftCurve[0], glm::vec2(m_TC1,1), color); + pVertexData->appendPos(m_RightCurve[0], glm::vec2(m_TC2,0), color); + for (unsigned i = 0; i < m_LeftCurve.size()-1; ++i) { + float ratio = i/float(m_LeftCurve.size()); + float tc = (1-ratio)*m_TC1+ratio*m_TC2; + pVertexData->appendPos(m_LeftCurve[i+1], glm::vec2(tc,1), color); + pVertexData->appendPos(m_RightCurve[i+1], glm::vec2(tc,0), color); + pVertexData->appendQuadIndexes((i+1)*2, i*2, (i+1)*2+1, i*2+1); } - return int(curveLen); } void CurveNode::updateLines() { BezierCurve curve(m_P1, m_P2, m_P3, m_P4); - double len = getCurveLen(); + float len = float(getCurveLen()); m_LeftCurve.clear(); m_RightCurve.clear(); - m_LeftCurve.reserve(int(len+1.5)); - m_RightCurve.reserve(int(len+1.5)); + m_LeftCurve.reserve(int(len+1.5f)); + m_RightCurve.reserve(int(len+1.5f)); for (unsigned i = 0; i < len; ++i) { - double t = i/len; + float t = i/len; addLRCurvePoint(curve.interpolate(t), curve.getDeriv(t)); } addLRCurvePoint(curve.interpolate(1), curve.getDeriv(1)); } -void CurveNode::addLRCurvePoint(const DPoint& pos, const DPoint& deriv) +void CurveNode::addLRCurvePoint(const glm::vec2& pos, const glm::vec2& deriv) { - DPoint m = deriv.getNormalized(); - DPoint w = DPoint(m.y, -m.x)*getStrokeWidth()/2; + glm::vec2 m = glm::normalize(deriv); + glm::vec2 w = glm::vec2(m.y, -m.x)*float(getStrokeWidth()/2); m_LeftCurve.push_back(pos-w); m_RightCurve.push_back(pos+w); } diff --git a/src/player/CurveNode.h b/src/player/CurveNode.h index 0a93292..45efc05 100644 --- a/src/player/CurveNode.h +++ b/src/player/CurveNode.h @@ -1,6 +1,6 @@ // // libavg - Media Playback Engine. -// Copyright (C) 2003-2011 Ulrich von Zadow +// Copyright (C) 2003-2014 Ulrich von Zadow // // This library is free software; you can redistribute it and/or // modify it under the terms of the GNU Lesser General Public @@ -32,44 +32,46 @@ namespace avg { class AVG_API CurveNode : public VectorNode { public: - static NodeDefinition createDefinition(); + static void registerType(); CurveNode(const ArgList& args); virtual ~CurveNode(); - const DPoint& getPos1() const; - void setPos1(const DPoint& pt); + const glm::vec2& getPos1() const; + void setPos1(const glm::vec2& pt); - const DPoint& getPos2() const; - void setPos2(const DPoint& pt); + const glm::vec2& getPos2() const; + void setPos2(const glm::vec2& pt); - const DPoint& getPos3() const; - void setPos3(const DPoint& pt); + const glm::vec2& getPos3() const; + void setPos3(const glm::vec2& pt); - const DPoint& getPos4() const; - void setPos4(const DPoint& pt); + const glm::vec2& getPos4() const; + void setPos4(const glm::vec2& pt); - double getTexCoord1() const; - void setTexCoord1(double tc); + float getTexCoord1() const; + void setTexCoord1(float tc); - double getTexCoord2() const; - void setTexCoord2(double tc); + float getTexCoord2() const; + void setTexCoord2(float tc); - virtual void calcVertexes(VertexArrayPtr& pVertexArray, Pixel32 color); + int getCurveLen() const; + glm::vec2 getPtOnCurve(float t) const; + + virtual void calcVertexes(const VertexDataPtr& pVertexData, Pixel32 color); private: - int getCurveLen(); void updateLines(); - void addLRCurvePoint(const DPoint& pos, const DPoint& deriv); - DPoint m_P1; - DPoint m_P2; - DPoint m_P3; - DPoint m_P4; - double m_TC1; - double m_TC2; - - std::vector<DPoint> m_LeftCurve; - std::vector<DPoint> m_RightCurve; + void addLRCurvePoint(const glm::vec2& pos, const glm::vec2& deriv); + glm::vec2 m_P1; + glm::vec2 m_P2; + glm::vec2 m_P3; + glm::vec2 m_P4; + float m_TC1; + float m_TC2; + + std::vector<glm::vec2> m_LeftCurve; + std::vector<glm::vec2> m_RightCurve; }; } diff --git a/src/player/DisplayEngine.cpp b/src/player/DisplayEngine.cpp index 1f46847..7144e36 100644 --- a/src/player/DisplayEngine.cpp +++ b/src/player/DisplayEngine.cpp @@ -1,6 +1,6 @@ // // libavg - Media Playback Engine. -// Copyright (C) 2003-2011 Ulrich von Zadow +// Copyright (C) 2003-2014 Ulrich von Zadow // // This library is free software; you can redistribute it and/or // modify it under the terms of the GNU Lesser General Public @@ -25,7 +25,9 @@ #include "../base/ScopeTimer.h" #include "../base/TimeSource.h" #include "../base/Exception.h" -#include "../base/ObjectCounter.h" + +#include "../graphics/GLContext.h" +#include "../graphics/Display.h" using namespace std; @@ -38,12 +40,10 @@ DisplayEngine::DisplayEngine() m_bInitialized(false), m_EffFramerate(0) { - ObjectCounter::get()->incRef(&typeid(*this)); } DisplayEngine::~DisplayEngine() { - ObjectCounter::get()->decRef(&typeid(*this)); } @@ -64,42 +64,48 @@ void DisplayEngine::initRender() void DisplayEngine::deinitRender() { - AVG_TRACE(Logger::PROFILE, "Framerate statistics: "); - AVG_TRACE(Logger::PROFILE, " Total frames: " << m_NumFrames); - double TotalTime = double(TimeSource::get()->getCurrentMicrosecs() + AVG_TRACE(Logger::category::PROFILE, Logger::severity::INFO, + "Framerate statistics: "); + AVG_TRACE(Logger::category::PROFILE, Logger::severity::INFO, + " Total frames: " <<m_NumFrames); + float TotalTime = float(TimeSource::get()->getCurrentMicrosecs() -m_StartTime)/1000000; - AVG_TRACE(Logger::PROFILE, " Total time: " << TotalTime << " seconds"); - double actualFramerate = (m_NumFrames+1)/TotalTime; - AVG_TRACE(Logger::PROFILE, " Framerate achieved: " - << actualFramerate); - AVG_TRACE(Logger::PROFILE, " Frames too late: " << m_FramesTooLate); - AVG_TRACE(Logger::PROFILE, " Percent of time spent waiting: " - << double (m_TimeSpentWaiting)/(10000*TotalTime)); + AVG_TRACE(Logger::category::PROFILE, Logger::severity::INFO, + " Total time: " << TotalTime << " seconds"); + float actualFramerate = (m_NumFrames+1)/TotalTime; + AVG_TRACE(Logger::category::PROFILE, Logger::severity::INFO, + " Framerate achieved: " << actualFramerate); + AVG_TRACE(Logger::category::PROFILE, Logger::severity::INFO, + " Frames too late: " << m_FramesTooLate); + AVG_TRACE(Logger::category::PROFILE, Logger::severity::INFO, + " Percent of time spent waiting: " + << float (m_TimeSpentWaiting)/(10000*TotalTime)); if (m_Framerate != 0) { - AVG_TRACE(Logger::PROFILE, " Framerate goal was: " << m_Framerate); + AVG_TRACE(Logger::category::PROFILE, Logger::severity::INFO, + " Framerate goal was: " << m_Framerate); if (m_Framerate*2 < actualFramerate && m_NumFrames > 10) { - AVG_TRACE(Logger::WARNING, - "Actual framerate was a lot higher than framerate goal. Is vblank sync forced off?"); + AVG_LOG_WARNING("Actual framerate was a lot higher than framerate goal.\ + Is vblank sync forced off?"); } } m_bInitialized = false; } -void DisplayEngine::setFramerate(double rate) +void DisplayEngine::setFramerate(float rate) { if (rate != 0 && m_bInitialized) { - initVBlank(0); + GLContext::getMain()->initVBlank(0); } m_Framerate = rate; m_VBRate = 0; } -double DisplayEngine::getFramerate() +float DisplayEngine::getFramerate() { return m_Framerate; } -double DisplayEngine::getEffectiveFramerate() +float DisplayEngine::getEffectiveFramerate() { return m_EffFramerate; } @@ -108,10 +114,10 @@ void DisplayEngine::setVBlankRate(int rate) { m_VBRate = rate; if (m_bInitialized) { - bool bOK = initVBlank(rate); - m_Framerate = getRefreshRate()/m_VBRate; + bool bOK = GLContext::getMain()->initVBlank(rate); + m_Framerate = Display::get()->getRefreshRate()/m_VBRate; if (!bOK || rate == 0) { - AVG_TRACE(Logger::WARNING, "Using framerate of " << m_Framerate << + AVG_LOG_WARNING("Using framerate of " << m_Framerate << " instead of VBRate of " << m_VBRate); m_VBRate = 0; } @@ -133,15 +139,12 @@ void DisplayEngine::frameWait() m_FrameWaitStartTime = TimeSource::get()->getCurrentMicrosecs(); m_TargetTime = m_LastFrameTime+(long long)(1000000/m_Framerate); - if (m_VBRate != 0) { - m_bFrameLate = !vbWait(m_VBRate); - } else { - m_bFrameLate = false; + m_bFrameLate = false; + if (m_VBRate == 0) { if (m_FrameWaitStartTime <= m_TargetTime) { long long WaitTime = (m_TargetTime-m_FrameWaitStartTime)/1000; if (WaitTime > 5000) { - AVG_TRACE (Logger::WARNING, - "DisplayEngine: waiting " << WaitTime << " ms."); + AVG_LOG_WARNING("DisplayEngine: waiting " << WaitTime << " ms."); } TimeSource::get()->sleepUntil(m_TargetTime/1000); } @@ -160,7 +163,7 @@ void DisplayEngine::checkJitter() } else { long long CurIntervalTime = TimeSource::get()->getCurrentMicrosecs() -m_LastFrameTime; - m_EffFramerate = 1000000.0/CurIntervalTime; + m_EffFramerate = 1000000.0f/CurIntervalTime; } long long frameTime = TimeSource::get()->getCurrentMicrosecs(); @@ -171,9 +174,6 @@ void DisplayEngine::checkJitter() maxDelay = 6; } if ((frameTime - m_TargetTime)/1000 > maxDelay || m_bFrameLate) { - AVG_TRACE (Logger::PROFILE_LATEFRAMES, - "DisplayEngine: frame too late by " - << (frameTime - m_TargetTime)/1000 << " ms."); m_bFrameLate = true; m_FramesTooLate++; } diff --git a/src/player/DisplayEngine.h b/src/player/DisplayEngine.h index 1025f6a..9b53e45 100644 --- a/src/player/DisplayEngine.h +++ b/src/player/DisplayEngine.h @@ -1,6 +1,6 @@ // libavg - Media Playback Engine. -// Copyright (C) 2003-2011 Ulrich von Zadow +// Copyright (C) 2003-2014 Ulrich von Zadow // // This library is free software; you can redistribute it and/or // modify it under the terms of the GNU Lesser General Public @@ -46,13 +46,12 @@ class AVG_API DisplayEngine virtual void teardown() = 0; void initRender(); void deinitRender(); - void setFramerate(double rate); - double getFramerate(); - double getEffectiveFramerate(); + void setFramerate(float rate); + float getFramerate(); + float getEffectiveFramerate(); void setVBlankRate(int rate); bool wasFrameLate(); - virtual double getRefreshRate() = 0; - virtual void setGamma(double Red, double Green, double Blue) = 0; + virtual void setGamma(float Red, float Green, float Blue) = 0; virtual void setMousePos(const IntPoint& pos) = 0; virtual int getKeyModifierState() const = 0; @@ -70,9 +69,6 @@ class AVG_API DisplayEngine protected: private: - virtual bool initVBlank(int rate) = 0; - virtual bool vbWait(int rate) = 0; - int m_NumFrames; int m_FramesTooLate; long long m_StartTime; @@ -83,11 +79,11 @@ class AVG_API DisplayEngine long long m_FrameWaitStartTime; long long m_TargetTime; int m_VBRate; - double m_Framerate; + float m_Framerate; bool m_bInitialized; bool m_bFrameLate; - double m_EffFramerate; + float m_EffFramerate; }; typedef boost::shared_ptr<DisplayEngine> DisplayEnginePtr; diff --git a/src/player/DisplayParams.cpp b/src/player/DisplayParams.cpp index eb376c5..096da33 100644 --- a/src/player/DisplayParams.cpp +++ b/src/player/DisplayParams.cpp @@ -1,5 +1,5 @@ // libavg - Media Playback Engine. -// Copyright (C) 2003-2011 Ulrich von Zadow +// Copyright (C) 2003-2014 Ulrich von Zadow // // This library is free software; you can redistribute it and/or // modify it under the terms of the GNU Lesser General Public @@ -20,8 +20,6 @@ #include "DisplayParams.h" -#include "../base/ObjectCounter.h" - #include <iostream> using namespace std; @@ -37,18 +35,15 @@ DisplayParams::DisplayParams() m_bShowCursor(true), m_VBRate(1), m_Framerate(0), - m_bHasWindowFrame(true), - m_DotsPerMM(0) + m_bHasWindowFrame(true) { - ObjectCounter::get()->incRef(&typeid(*this)); - m_Gamma[0] = -1.0; - m_Gamma[1] = -1.0; - m_Gamma[2] = -1.0; + m_Gamma[0] = -1.0f; + m_Gamma[1] = -1.0f; + m_Gamma[2] = -1.0f; } DisplayParams::~DisplayParams() { - ObjectCounter::get()->decRef(&typeid(*this)); } void DisplayParams::dump() const @@ -63,7 +58,6 @@ void DisplayParams::dump() const cerr << " vbrate: " << m_VBRate << endl; cerr << " framerate: " << m_Framerate << endl; cerr << " has window frame: " << m_bHasWindowFrame << endl; - cerr << " dots per mm: " << m_DotsPerMM << endl; } } diff --git a/src/player/DisplayParams.h b/src/player/DisplayParams.h index 1a2114d..178abbf 100644 --- a/src/player/DisplayParams.h +++ b/src/player/DisplayParams.h @@ -1,6 +1,6 @@ // libavg - Media Playback Engine. -// Copyright (C) 2003-2011 Ulrich von Zadow +// Copyright (C) 2003-2014 Ulrich von Zadow // // This library is free software; you can redistribute it and/or // modify it under the terms of the GNU Lesser General Public @@ -24,7 +24,7 @@ #include "../api.h" -#include "../base/Point.h" +#include "../base/GLMHelper.h" namespace avg { @@ -41,11 +41,10 @@ struct AVG_API DisplayParams { IntPoint m_WindowSize; bool m_bShowCursor; int m_VBRate; - double m_Framerate; + float m_Framerate; bool m_bHasWindowFrame; - double m_DotsPerMM; - double m_Gamma[3]; + float m_Gamma[3]; }; } diff --git a/src/player/DivNode.cpp b/src/player/DivNode.cpp index 7d3dc7c..7397c10 100644 --- a/src/player/DivNode.cpp +++ b/src/player/DivNode.cpp @@ -1,6 +1,6 @@ // // libavg - Media Playback Engine. -// Copyright (C) 2003-2011 Ulrich von Zadow +// Copyright (C) 2003-2014 Ulrich von Zadow // // This library is free software; you can redistribute it and/or // modify it under the terms of the GNU Lesser General Public @@ -21,10 +21,9 @@ #include "DivNode.h" #include "Player.h" -#include "NodeDefinition.h" +#include "TypeDefinition.h" #include "Canvas.h" -#include "../base/Point.h" #include "../base/Exception.h" #include "../base/Logger.h" #include "../base/StringHelper.h" @@ -39,36 +38,35 @@ using namespace std; using namespace boost; -#define DEFAULT_SIZE 100000 - namespace avg { -NodeDefinition DivNode::createDefinition() +void DivNode::registerType() { string sChildArray[] = {"image", "div", "canvas", "words", "video", "camera", "panoimage", "sound", "line", "rect", "curve", "polyline", "polygon", "circle", "mesh"}; vector<string> sChildren = vectorFromCArray( sizeof(sChildArray) / sizeof(*sChildArray), sChildArray); - return NodeDefinition("div", Node::buildNode<DivNode>) - .extendDefinition(AreaNode::createDefinition()) + TypeDefinition def = TypeDefinition("div", "areanode", + ExportedObject::buildObject<DivNode>) .addChildren(sChildren) .addArg(Arg<bool>("crop", false, false, offsetof(DivNode, m_bCrop))) - .addArg(Arg<string>("elementoutlinecolor", "", false, - offsetof(DivNode, m_sElementOutlineColor))) .addArg(Arg<UTF8String>("mediadir", "", false, offsetof(DivNode, m_sMediaDir))); + TypeRegistry::get()->registerType(def); } DivNode::DivNode(const ArgList& args) { args.setMembers(this); - setElementOutlineColor(m_sElementOutlineColor); ObjectCounter::get()->incRef(&typeid(*this)); } DivNode::~DivNode() { + for (unsigned i = 0; i < getNumChildren(); ++i) { + getChild(i)->removeParent(); + } ObjectCounter::get()->decRef(&typeid(*this)); } @@ -78,7 +76,6 @@ void DivNode::connectDisplay() for (unsigned i = 0; i < getNumChildren(); ++i) { getChild(i)->connectDisplay(); } - m_pClipVertexes = VertexArrayPtr(new VertexArray()); } void DivNode::connect(CanvasPtr pCanvas) @@ -94,18 +91,12 @@ void DivNode::disconnect(bool bKill) for (unsigned i = 0; i < getNumChildren(); ++i) { getChild(i)->disconnect(bKill); } - if (m_pClipVertexes) { - m_pClipVertexes = VertexArrayPtr(); - } AreaNode::disconnect(bKill); } -DPoint DivNode::getPivot() const +glm::vec2 DivNode::getPivot() const { - DPoint pivot = AreaNode::getPivot(); - if (pivot == DPoint(DEFAULT_SIZE / 2, DEFAULT_SIZE / 2)) { - return DPoint(0, 0); - } + glm::vec2 pivot = AreaNode::getPivot(); return pivot; } @@ -163,8 +154,7 @@ void DivNode::insertChild(NodePtr pChild, unsigned i) if (getState() == NS_CONNECTED || getState() == NS_CANRENDER) { getCanvas()->registerNode(pChild); } - DivNodePtr ptr = dynamic_pointer_cast<DivNode>(shared_from_this()); - pChild->checkSetParentError(ptr); + pChild->checkSetParentError(this); if (!isChildTypeAllowed(pChild->getTypeStr())) { throw(Exception(AVG_ERR_ALREADY_CONNECTED, "Can't insert a node of type "+pChild->getTypeStr()+ @@ -177,7 +167,7 @@ void DivNode::insertChild(NodePtr pChild, unsigned i) std::vector<NodePtr>::iterator pos = m_Children.begin()+i; m_Children.insert(pos, pChild); try { - pChild->setParent(ptr, getState(), getCanvas()); + pChild->setParent(this, getState(), getCanvas()); } catch (Exception&) { m_Children.erase(m_Children.begin()+i); throw; @@ -267,21 +257,6 @@ void DivNode::setCrop(bool bCrop) m_bCrop = bCrop; } -const std::string& DivNode::getElementOutlineColor() const -{ - return m_sElementOutlineColor; -} - -void DivNode::setElementOutlineColor(const std::string& sColor) -{ - m_sElementOutlineColor = sColor; - if (sColor == "") { - m_ElementOutlineColor = Pixel32(0,0,0,0); - } else { - m_ElementOutlineColor = colorStringToColor(m_sElementOutlineColor); - } -} - const UTF8String& DivNode::getMediaDir() const { return m_sMediaDir; @@ -289,88 +264,80 @@ const UTF8String& DivNode::getMediaDir() const void DivNode::setMediaDir(const UTF8String& sMediaDir) { +// avgDeprecationWarning("1.7", "DivNode.mediadir", ""); m_sMediaDir = sMediaDir; checkReload(); } -void DivNode::getElementsByPos(const DPoint& pos, vector<NodeWeakPtr>& pElements) +void DivNode::getElementsByPos(const glm::vec2& pos, vector<NodePtr>& pElements) { if (reactsToMouseEvents() && - ((getSize() == DPoint(DEFAULT_SIZE, DEFAULT_SIZE) || + ((getSize() == glm::vec2(0,0) || (pos.x >= 0 && pos.y >= 0 && pos.x < getSize().x && pos.y < getSize().y)))) { for (int i = getNumChildren()-1; i >= 0; i--) { NodePtr pCurChild = getChild(i); - DPoint relPos = pCurChild->toLocal(pos); + glm::vec2 relPos = pCurChild->toLocal(pos); pCurChild->getElementsByPos(relPos, pElements); if (!pElements.empty()) { - pElements.push_back(shared_from_this()); + pElements.push_back(getSharedThis()); return; } } // pos isn't in any of the children. - if (getSize() != DPoint(DEFAULT_SIZE, DEFAULT_SIZE)) { + if (getSize() != glm::vec2(0,0)) { // Explicit width/height given for div - div reacts on its own. - pElements.push_back(shared_from_this()); + pElements.push_back(getSharedThis()); } } } -void DivNode::preRender() +void DivNode::preRender(const VertexArrayPtr& pVA, bool bIsParentActive, + float parentEffectiveOpacity) { - Node::preRender(); + Node::preRender(pVA, bIsParentActive, parentEffectiveOpacity); + if (getCrop() && getSize() != glm::vec2(0,0)) { + pVA->startSubVA(m_ClipVA); + glm::vec2 viewport = getSize(); + m_ClipVA.appendPos(glm::vec2(0,0), glm::vec2(0,0), Pixel32(0,0,0,0)); + m_ClipVA.appendPos(glm::vec2(0,viewport.y), glm::vec2(0,0), Pixel32(0,0,0,0)); + m_ClipVA.appendPos(glm::vec2(viewport.x,0), glm::vec2(0,0), Pixel32(0,0,0,0)); + m_ClipVA.appendPos(viewport, glm::vec2(0,0), Pixel32(0,0,0,0)); + m_ClipVA.appendQuadIndexes(0, 1, 2, 3); + } for (unsigned i = 0; i < getNumChildren(); i++) { - getChild(i)->preRender(); + getChild(i)->preRender(pVA, bIsParentActive, getEffectiveOpacity()); } } -void DivNode::render(const DRect& rect) +void DivNode::render() { - DPoint viewport = getSize(); - - m_pClipVertexes->reset(); - m_pClipVertexes->appendPos(DPoint(0,0), DPoint(0,0), Pixel32(0,0,0,0)); - m_pClipVertexes->appendPos(DPoint(0,viewport.y), DPoint(0,0), Pixel32(0,0,0,0)); - m_pClipVertexes->appendPos(DPoint(viewport.x,0), DPoint(0,0), Pixel32(0,0,0,0)); - m_pClipVertexes->appendPos(viewport, DPoint(0,0), Pixel32(0,0,0,0)); - m_pClipVertexes->appendQuadIndexes(0, 1, 2, 3); - - if (getCrop()) { - getCanvas()->pushClipRect(m_pClipVertexes); + const glm::mat4& transform = getTransform(); + if (getCrop() && getSize() != glm::vec2(0,0)) { + getCanvas()->pushClipRect(transform, m_ClipVA); } for (unsigned i = 0; i < getNumChildren(); i++) { - getChild(i)->maybeRender(rect); + getChild(i)->maybeRender(transform); } - if (getCrop()) { - getCanvas()->popClipRect(m_pClipVertexes); + if (getCrop() && getSize() != glm::vec2(0,0)) { + getCanvas()->popClipRect(transform, m_ClipVA); } } -void DivNode::renderOutlines(const VertexArrayPtr& pVA, Pixel32 color) +void DivNode::renderOutlines(const VertexArrayPtr& pVA, Pixel32 parentColor) { - Pixel32 effColor = color; - if (m_ElementOutlineColor != Pixel32(0,0,0,0)) { - effColor = m_ElementOutlineColor; - effColor.setA(128); - } + Pixel32 effColor = getEffectiveOutlineColor(parentColor); if (effColor != Pixel32(0,0,0,0)) { - DPoint size = getSize(); - if (size == DPoint(DEFAULT_SIZE, DEFAULT_SIZE)) { - DPoint p0 = getAbsPos(DPoint(-4, 0.5)); - DPoint p1 = getAbsPos(DPoint(5, 0.5)); - DPoint p2 = getAbsPos(DPoint(0.5, -4)); - DPoint p3 = getAbsPos(DPoint(0.5, 5)); + glm::vec2 size = getSize(); + if (size == glm::vec2(0,0)) { + glm::vec2 p0 = getAbsPos(glm::vec2(-4, 0.5)); + glm::vec2 p1 = getAbsPos(glm::vec2(5, 0.5)); + glm::vec2 p2 = getAbsPos(glm::vec2(0.5, -4)); + glm::vec2 p3 = getAbsPos(glm::vec2(0.5, 5)); pVA->addLineData(effColor, p0, p1, 1); pVA->addLineData(effColor, p2, p3, 1); } else { - DPoint p0 = getAbsPos(DPoint(0.5, 0.5)); - DPoint p1 = getAbsPos(DPoint(size.x+0.5,0.5)); - DPoint p2 = getAbsPos(DPoint(size.x+0.5,size.y+0.5)); - DPoint p3 = getAbsPos(DPoint(0.5,size.y+0.5)); - pVA->addLineData(effColor, p0, p1, 1); - pVA->addLineData(effColor, p1, p2, 1); - pVA->addLineData(effColor, p2, p3, 1); - pVA->addLineData(effColor, p3, p0, 1); + AreaNode::renderOutlines(pVA, parentColor); } } for (unsigned i = 0; i < getNumChildren(); i++) { @@ -414,7 +381,7 @@ string DivNode::dump(int indent) IntPoint DivNode::getMediaSize() { - return IntPoint(DEFAULT_SIZE, DEFAULT_SIZE); + return IntPoint(0, 0); } bool DivNode::isChildTypeAllowed(const string& sType) diff --git a/src/player/DivNode.h b/src/player/DivNode.h index 573f2e5..080bf56 100644 --- a/src/player/DivNode.h +++ b/src/player/DivNode.h @@ -1,6 +1,6 @@ // // libavg - Media Playback Engine. -// Copyright (C) 2003-2011 Ulrich von Zadow +// Copyright (C) 2003-2014 Ulrich von Zadow // // This library is free software; you can redistribute it and/or // modify it under the terms of the GNU Lesser General Public @@ -25,19 +25,18 @@ #include "../api.h" #include "AreaNode.h" +#include "../graphics/SubVertexArray.h" + #include "../base/UTF8String.h" -#include "../graphics/VertexArray.h" #include <string> namespace avg { -class VertexArray; - class AVG_API DivNode : public AreaNode { public: - static NodeDefinition createDefinition(); + static void registerType(); DivNode(const ArgList& args); virtual ~DivNode(); @@ -59,20 +58,18 @@ class AVG_API DivNode : public AreaNode void removeChild(NodePtr pNode, bool bKill); void removeChild(unsigned i, bool bKill); - virtual DPoint getPivot() const; + virtual glm::vec2 getPivot() const; bool getCrop() const; void setCrop(bool bCrop); - const std::string& getElementOutlineColor() const; - void setElementOutlineColor(const std::string& sColor); - const UTF8String& getMediaDir() const; void setMediaDir(const UTF8String& mediaDir); - void getElementsByPos(const DPoint& pos, std::vector<NodeWeakPtr>& pElements); - virtual void preRender(); - virtual void render(const DRect& rect); + void getElementsByPos(const glm::vec2& pos, std::vector<NodePtr>& pElements); + virtual void preRender(const VertexArrayPtr& pVA, bool bIsParentActive, + float parentEffectiveOpacity); + virtual void render(); virtual void renderOutlines(const VertexArrayPtr& pVA, Pixel32 color); virtual std::string getEffectiveMediaDir(); @@ -86,10 +83,8 @@ class AVG_API DivNode : public AreaNode UTF8String m_sMediaDir; bool m_bCrop; - std::string m_sElementOutlineColor; - Pixel32 m_ElementOutlineColor; - VertexArrayPtr m_pClipVertexes; + SubVertexArray m_ClipVA; std::vector<NodePtr> m_Children; }; diff --git a/src/player/Event.cpp b/src/player/Event.cpp index a12d31c..07d274b 100644 --- a/src/player/Event.cpp +++ b/src/player/Event.cpp @@ -1,6 +1,6 @@ // // libavg - Media Playback Engine. -// Copyright (C) 2003-2011 Ulrich von Zadow +// Copyright (C) 2003-2014 Ulrich von Zadow // // This library is free software; you can redistribute it and/or // modify it under the terms of the GNU Lesser General Public @@ -106,24 +106,22 @@ string Event::typeStr() const string Event::typeStr(Event::Type type) { switch(type) { - case KEYUP: - return "KEYUP"; - case KEYDOWN: - return "KEYDOWN"; - case CURSORMOTION: - return "CURSORMOTION"; - case CURSORUP: - return "CURSORUP"; - case CURSORDOWN: - return "CURSORDOWN"; - case CURSOROVER: - return "CURSOROVER"; - case CURSOROUT: - return "CURSOROUT"; - case CUSTOMEVENT: - return "CUSTOMEVENT"; - case RESIZE: - return "RESIZE"; + case KEY_UP: + return "KEY_UP"; + case KEY_DOWN: + return "KEY_DOWN"; + case CURSOR_MOTION: + return "CURSOR_MOTION"; + case CURSOR_UP: + return "CURSOR_UP"; + case CURSOR_DOWN: + return "CURSOR_DOWN"; + case CURSOR_OVER: + return "CURSOR_OVER"; + case CURSOR_OUT: + return "CURSOR_OUT"; + case CUSTOM_EVENT: + return "CUSTOM_EVENT"; case QUIT: return "QUIT"; default: @@ -135,7 +133,7 @@ string Event::typeStr(Event::Type type) void Event::trace() { string sType = typeStr(); - AVG_TRACE(Logger::EVENTS, sType); + AVG_TRACE(Logger::category::EVENTS,Logger::severity::INFO, sType); } } diff --git a/src/player/Event.h b/src/player/Event.h index 9ac5a89..d1b6d9f 100644 --- a/src/player/Event.h +++ b/src/player/Event.h @@ -1,6 +1,6 @@ // // libavg - Media Playback Engine. -// Copyright (C) 2003-2011 Ulrich von Zadow +// Copyright (C) 2003-2014 Ulrich von Zadow // // This library is free software; you can redistribute it and/or // modify it under the terms of the GNU Lesser General Public @@ -39,15 +39,15 @@ typedef boost::weak_ptr<class IInputDevice> IInputDeviceWeakPtr; class AVG_API Event { public: enum Type { - KEYUP, - KEYDOWN, - CURSORMOTION, - CURSORUP, - CURSORDOWN, - CURSOROVER, - CURSOROUT, - CUSTOMEVENT, - RESIZE, + // XXX: Hack to make sure this enum can't be passed to Node.subscribe. + KEY_UP = 10000, + KEY_DOWN, + CURSOR_MOTION, + CURSOR_UP, + CURSOR_DOWN, + CURSOR_OVER, + CURSOR_OUT, + CUSTOM_EVENT, QUIT }; enum Source {MOUSE=1, TOUCH=2, TRACK=4, CUSTOM=8, NONE=16}; diff --git a/src/player/EventDispatcher.cpp b/src/player/EventDispatcher.cpp index f63c42a..23caff2 100644 --- a/src/player/EventDispatcher.cpp +++ b/src/player/EventDispatcher.cpp @@ -1,6 +1,6 @@ // // libavg - Media Playback Engine. -// Copyright (C) 2003-2011 Ulrich von Zadow +// Copyright (C) 2003-2014 Ulrich von Zadow // // This library is free software; you can redistribute it and/or // modify it under the terms of the GNU Lesser General Public @@ -26,6 +26,7 @@ #include "CursorEvent.h" #include "../base/Exception.h" +#include "../base/OSHelper.h" #include <string> @@ -34,9 +35,10 @@ using namespace boost; namespace avg { -EventDispatcher::EventDispatcher(Player* pPlayer) +EventDispatcher::EventDispatcher(Player* pPlayer, bool bMouseEnabled) : m_pPlayer(pPlayer), - m_NumMouseButtonsDown(0) + m_NumMouseButtonsDown(0), + m_bMouseEnabled(bMouseEnabled) { } @@ -63,10 +65,13 @@ void EventDispatcher::dispatch() vector<EventPtr>::iterator it; for (it = events.begin(); it != events.end(); ++it) { EventPtr pEvent = *it; -// cerr << " " << pEvent->typeStr() << ", " << pEvent->getSource() << endl; - testAddContact(pEvent); - handleEvent(*it); - testRemoveContact(pEvent); + bool bHookEatsEvent = processEventHook(pEvent); + if (!(!m_bMouseEnabled && pEvent->getSource() == Event::MOUSE) && + !bHookEatsEvent) { + testAddContact(pEvent); + handleEvent(*it); + testRemoveContact(pEvent); + } } } @@ -80,6 +85,11 @@ void EventDispatcher::sendEvent(EventPtr pEvent) handleEvent(pEvent); } +void EventDispatcher::enableMouse(bool bEnabled) +{ + m_bMouseEnabled = bEnabled; +} + ContactPtr EventDispatcher::getContact(int id) { std::map<int, ContactPtr>::iterator it = m_ContactMap.find(id); @@ -95,13 +105,25 @@ void EventDispatcher::handleEvent(EventPtr pEvent) m_pPlayer->handleEvent(pEvent); } +bool EventDispatcher::processEventHook(EventPtr pEvent) +{ + PyObject * pEventHook = m_pPlayer->getEventHook(); + if (pEventHook != Py_None) { + // If the hook returns true, stop processing the event + if (py::call<bool>(pEventHook, pEvent)) { + return true; + } + } + return false; +} + void EventDispatcher::testAddContact(EventPtr pEvent) { ContactPtr pContact; CursorEventPtr pCursorEvent = dynamic_pointer_cast<CursorEvent>(pEvent); if (pCursorEvent) { switch (pCursorEvent->getType()) { - case Event::CURSORDOWN: + case Event::CURSOR_DOWN: if (pCursorEvent->getSource() == Event::MOUSE) { m_NumMouseButtonsDown++; if (m_NumMouseButtonsDown == 1) { @@ -114,8 +136,8 @@ void EventDispatcher::testAddContact(EventPtr pEvent) m_ContactMap[pCursorEvent->getCursorID()] = pContact; } break; - case Event::CURSORMOTION: - case Event::CURSORUP: { + case Event::CURSOR_MOTION: + case Event::CURSOR_UP: { pContact = getContact(pCursorEvent->getCursorID()); AVG_ASSERT(pContact || ( pCursorEvent->getSource() == Event::MOUSE && @@ -125,7 +147,7 @@ void EventDispatcher::testAddContact(EventPtr pEvent) } } break; - case Event::CUSTOMEVENT: + case Event::CUSTOM_EVENT: break; default: cerr << pCursorEvent->typeStr() << endl; @@ -140,13 +162,16 @@ void EventDispatcher::testAddContact(EventPtr pEvent) void EventDispatcher::testRemoveContact(EventPtr pEvent) { - if (pEvent->getType() == Event::CURSORUP) { + if (pEvent->getType() == Event::CURSOR_UP) { if (pEvent->getSource() == Event::MOUSE) { - AVG_ASSERT(m_NumMouseButtonsDown > 0); - m_NumMouseButtonsDown--; - if (m_NumMouseButtonsDown == 0) { - int rc = m_ContactMap.erase(MOUSECURSORID); - AVG_ASSERT(rc == 1); + // The following if is only false if the CURSOR_DOWN wasn't registered because + // it was outside the application window (or on the window border). + if (m_NumMouseButtonsDown > 0) { + m_NumMouseButtonsDown--; + if (m_NumMouseButtonsDown == 0) { + int rc = m_ContactMap.erase(MOUSECURSORID); + AVG_ASSERT(rc == 1); + } } } else { int rc = m_ContactMap.erase( diff --git a/src/player/EventDispatcher.h b/src/player/EventDispatcher.h index 51da86e..19c3f78 100644 --- a/src/player/EventDispatcher.h +++ b/src/player/EventDispatcher.h @@ -1,6 +1,6 @@ // // libavg - Media Playback Engine. -// Copyright (C) 2003-2011 Ulrich von Zadow +// Copyright (C) 2003-2014 Ulrich von Zadow // // This library is free software; you can redistribute it and/or // modify it under the terms of the GNU Lesser General Public @@ -38,17 +38,19 @@ class Player; class AVG_API EventDispatcher { public: - EventDispatcher(Player* pPlayer); + EventDispatcher(Player* pPlayer, bool bMouseEnabled); virtual ~EventDispatcher(); void dispatch(); void addInputDevice(IInputDevicePtr pInputDevice); void sendEvent(EventPtr pEvent); + void enableMouse(bool bEnabled); ContactPtr getContact(int id); private: void handleEvent(EventPtr pEvent); + bool processEventHook(EventPtr pEvent); void testAddContact(EventPtr pEvent); void testRemoveContact(EventPtr pEvent); @@ -56,6 +58,7 @@ class AVG_API EventDispatcher { Player* m_pPlayer; std::map<int, ContactPtr> m_ContactMap; int m_NumMouseButtonsDown; + bool m_bMouseEnabled; }; typedef boost::shared_ptr<EventDispatcher> EventDispatcherPtr; diff --git a/src/player/ExportedObject.cpp b/src/player/ExportedObject.cpp new file mode 100644 index 0000000..b50a72a --- /dev/null +++ b/src/player/ExportedObject.cpp @@ -0,0 +1,105 @@ +// +// libavg - Media Playback Engine. +// Copyright (C) 2003-2014 Ulrich von Zadow +// +// This library is free software; you can redistribute it and/or +// modify it under the terms of the GNU Lesser General Public +// License as published by the Free Software Foundation; either +// version 2 of the License, or (at your option) any later version. +// +// This library 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 +// Lesser General Public License for more details. +// +// You should have received a copy of the GNU Lesser General Public +// License along with this library; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +// +// Current versions can be found at www.libavg.de +// + +#include "ExportedObject.h" +#include "TypeDefinition.h" +#include "Arg.h" + +#include "../base/Exception.h" +#include "../base/Logger.h" +#include "../base/ObjectCounter.h" + +#include <string> + +using namespace std; + +namespace avg { + +ExportedObject::ExportedObject() + : m_pSelf(0) +{ + ObjectCounter::get()->incRef(&typeid(*this)); +} + +ExportedObject::ExportedObject(const ExportedObject& other) + : m_pSelf(0) +{ + AVG_ASSERT(!other.m_pSelf); + m_pDefinition = other.m_pDefinition; + ObjectCounter::get()->incRef(&typeid(*this)); +} + +ExportedObject::~ExportedObject() +{ + ObjectCounter::get()->decRef(&typeid(*this)); +} + +void ExportedObject::registerInstance(PyObject* pSelf) +{ + m_pSelf = pSelf; +} + +ExportedObjectPtr ExportedObject::getSharedThis() +{ + // Just using shared_from_this causes strange behaviour when derived classes + // are written in python: The pointer returned by shared_from_this doesn't know + // about the python part of the object and cuts it off. Because of this, we remember + // a pointer to the python object in m_pSelf and use that to create a functioning + // and complete ExportedObjectPtr if there is a python derived class. + if (m_pSelf) { + return py::extract<ExportedObjectPtr>(m_pSelf); + } else { + return shared_from_this(); + } +} + +void ExportedObject::setTypeInfo(const TypeDefinition * pDefinition) +{ + m_pDefinition = pDefinition; +} + +const TypeDefinition* ExportedObject::getDefinition() const +{ + return m_pDefinition; +} + +string ExportedObject::getTypeStr() const +{ + return m_pDefinition->getName(); +} + +bool ExportedObject::operator ==(const ExportedObject& other) const +{ + return this == &other; +} + +bool ExportedObject::operator !=(const ExportedObject& other) const +{ + return this != &other; +} + +long ExportedObject::getHash() const +{ + return long(this); +} + + +} diff --git a/src/player/ExportedObject.h b/src/player/ExportedObject.h new file mode 100644 index 0000000..810e787 --- /dev/null +++ b/src/player/ExportedObject.h @@ -0,0 +1,73 @@ +// +// libavg - Media Playback Engine. +// Copyright (C) 2003-2014 Ulrich von Zadow +// +// This library is free software; you can redistribute it and/or +// modify it under the terms of the GNU Lesser General Public +// License as published by the Free Software Foundation; either +// version 2 of the License, or (at your option) any later version. +// +// This library 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 +// Lesser General Public License for more details. +// +// You should have received a copy of the GNU Lesser General Public +// License along with this library; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +// +// Current versions can be found at www.libavg.de +// + +#ifndef _ExportedObject_H_ +#define _ExportedObject_H_ + +#include "../api.h" + +#include <boost/shared_ptr.hpp> +#include <boost/enable_shared_from_this.hpp> + +// Python docs say python.h should be included before any standard headers (!) +#include "WrapPython.h" + +namespace avg { + +class TypeDefinition; +class ArgList; + +class ExportedObject; +typedef boost::shared_ptr<ExportedObject> ExportedObjectPtr; + +class AVG_API ExportedObject: public boost::enable_shared_from_this<ExportedObject> +{ + public: + ExportedObject(); + ExportedObject(const ExportedObject& other); + virtual ~ExportedObject()=0; + + void registerInstance(PyObject* pSelf); + ExportedObjectPtr getSharedThis(); + + template<class Type> + static ExportedObjectPtr buildObject(const ArgList& Args) + { + return ExportedObjectPtr(new Type(Args)); + } + virtual void setTypeInfo(const TypeDefinition * pDefinition); + + virtual void setArgs(const ArgList& args) {}; + std::string getTypeStr() const; + virtual const TypeDefinition* getDefinition() const; + + bool operator ==(const ExportedObject& other) const; + bool operator !=(const ExportedObject& other) const; + long getHash() const; + + private: + const TypeDefinition* m_pDefinition; + PyObject* m_pSelf; +}; + +} + +#endif diff --git a/src/player/FXNode.cpp b/src/player/FXNode.cpp index c0483e5..9aa2fde 100644 --- a/src/player/FXNode.cpp +++ b/src/player/FXNode.cpp @@ -1,6 +1,6 @@ // // libavg - Media Playback Engine. -// Copyright (C) 2003-2011 Ulrich von Zadow +// Copyright (C) 2003-2014 Ulrich von Zadow // // This library is free software; you can redistribute it and/or // modify it under the terms of the GNU Lesser General Public @@ -29,8 +29,9 @@ namespace avg { using namespace std; -FXNode::FXNode() +FXNode::FXNode(bool bSupportsGLES) : m_Size(0, 0), + m_bSupportsGLES(bSupportsGLES), m_bDirty(true) { ObjectCounter::get()->incRef(&typeid(*this)); @@ -43,6 +44,7 @@ FXNode::~FXNode() void FXNode::connect() { + checkGLES(); if (m_Size != IntPoint(0,0)) { m_pFilter = createFilter(m_Size); } @@ -66,7 +68,7 @@ void FXNode::setSize(const IntPoint& newSize) void FXNode::apply(GLTexturePtr pSrcTex) { // blt overwrites everything, so no glClear necessary before. - GLContext::getCurrent()->setBlendMode(GLContext::BLEND_COPY); + GLContext::getMain()->setBlendMode(GLContext::BLEND_COPY); m_pFilter->apply(pSrcTex); } @@ -80,7 +82,7 @@ BitmapPtr FXNode::getImage() return m_pFilter->getImage(); } -DRect FXNode::getRelDestRect() const +FRect FXNode::getRelDestRect() const { return m_pFilter->getRelDestRect(); } @@ -105,4 +107,11 @@ void FXNode::setDirty() m_bDirty = true; } +void FXNode::checkGLES() const +{ + if (!m_bSupportsGLES && GLContext::getCurrent()->isGLES()) { + throw Exception(AVG_ERR_UNSUPPORTED, "This effect is unsupported under OpenGL ES."); + } +} + } diff --git a/src/player/FXNode.h b/src/player/FXNode.h index e602a9a..05a902e 100644 --- a/src/player/FXNode.h +++ b/src/player/FXNode.h @@ -1,6 +1,6 @@ // // libavg - Media Playback Engine. -// Copyright (C) 2003-2011 Ulrich von Zadow +// Copyright (C) 2003-2014 Ulrich von Zadow // // This library is free software; you can redistribute it and/or // modify it under the terms of the GNU Lesser General Public @@ -32,7 +32,7 @@ namespace avg { class AVG_API FXNode { public: - FXNode(); + FXNode(bool bSupportsGLES=true); virtual ~FXNode(); virtual void connect(); @@ -43,7 +43,7 @@ public: GLTexturePtr getTex(); BitmapPtr getImage(); - DRect getRelDestRect() const; + FRect getRelDestRect() const; bool isDirty() const; void resetDirty(); @@ -54,10 +54,12 @@ protected: private: virtual GPUFilterPtr createFilter(const IntPoint& size) = 0; + void checkGLES() const; IntPoint m_Size; GPUFilterPtr m_pFilter; + bool m_bSupportsGLES; bool m_bDirty; }; diff --git a/src/player/FilledVectorNode.cpp b/src/player/FilledVectorNode.cpp index 69d833b..a804958 100644 --- a/src/player/FilledVectorNode.cpp +++ b/src/player/FilledVectorNode.cpp @@ -1,6 +1,6 @@ // // libavg - Media Playback Engine. -// Copyright (C) 2003-2011 Ulrich von Zadow +// Copyright (C) 2003-2014 Ulrich von Zadow // // This library is free software; you can redistribute it and/or // modify it under the terms of the GNU Lesser General Public @@ -21,7 +21,7 @@ #include "FilledVectorNode.h" -#include "NodeDefinition.h" +#include "TypeDefinition.h" #include "Image.h" #include "DivNode.h" @@ -34,21 +34,21 @@ using namespace boost; namespace avg { -NodeDefinition FilledVectorNode::createDefinition() +void FilledVectorNode::registerType() { - return NodeDefinition("filledvector") - .extendDefinition(VectorNode::createDefinition()) + TypeDefinition def = TypeDefinition("filledvectornode", "vectornode") .addArg(Arg<UTF8String>("filltexhref", "", false, offsetof(FilledVectorNode, m_FillTexHRef))) - .addArg(Arg<double>("fillopacity", 0, false, + .addArg(Arg<float>("fillopacity", 0, false, offsetof(FilledVectorNode, m_FillOpacity))) - .addArg(Arg<string>("fillcolor", "FFFFFF", false, + .addArg(Arg<UTF8String>("fillcolor", "FFFFFF", false, offsetof(FilledVectorNode, m_sFillColorName))) - .addArg(Arg<DPoint>("filltexcoord1", DPoint(0,0), false, + .addArg(Arg<glm::vec2>("filltexcoord1", glm::vec2(0,0), false, offsetof(FilledVectorNode, m_FillTexCoord1))) - .addArg(Arg<DPoint>("filltexcoord2", DPoint(1,1), false, + .addArg(Arg<glm::vec2>("filltexcoord2", glm::vec2(1,1), false, offsetof(FilledVectorNode, m_FillTexCoord2))) ; + TypeRegistry::get()->registerType(def); } FilledVectorNode::FilledVectorNode(const ArgList& args) @@ -57,7 +57,7 @@ FilledVectorNode::FilledVectorNode(const ArgList& args) { m_FillTexHRef = args.getArgVal<UTF8String>("filltexhref"); setFillTexHRef(m_FillTexHRef); - m_sFillColorName = args.getArgVal<string>("fillcolor"); + m_sFillColorName = args.getArgVal<UTF8String>("fillcolor"); m_FillColor = colorStringToColor(m_sFillColorName); } @@ -112,70 +112,71 @@ void FilledVectorNode::setFillBitmap(BitmapPtr pBmp) setDrawNeeded(); } -const DPoint& FilledVectorNode::getFillTexCoord1() const +const glm::vec2& FilledVectorNode::getFillTexCoord1() const { return m_FillTexCoord1; } -void FilledVectorNode::setFillTexCoord1(const DPoint& pt) +void FilledVectorNode::setFillTexCoord1(const glm::vec2& pt) { m_FillTexCoord1 = pt; setDrawNeeded(); } -const DPoint& FilledVectorNode::getFillTexCoord2() const +const glm::vec2& FilledVectorNode::getFillTexCoord2() const { return m_FillTexCoord2; } -void FilledVectorNode::setFillTexCoord2(const DPoint& pt) +void FilledVectorNode::setFillTexCoord2(const glm::vec2& pt) { m_FillTexCoord2 = pt; setDrawNeeded(); } -double FilledVectorNode::getFillOpacity() const +float FilledVectorNode::getFillOpacity() const { return m_FillOpacity; } -void FilledVectorNode::setFillOpacity(double opacity) +void FilledVectorNode::setFillOpacity(float opacity) { m_FillOpacity = opacity; setDrawNeeded(); } -void FilledVectorNode::preRender() +void FilledVectorNode::preRender(const VertexArrayPtr& pVA, bool bIsParentActive, + float parentEffectiveOpacity) { - Node::preRender(); - double curOpacity = getParent()->getEffectiveOpacity()*m_FillOpacity; - VertexArrayPtr pFillVA; - pFillVA = m_pFillShape->getVertexArray(); + Node::preRender(pVA, bIsParentActive, parentEffectiveOpacity); + float curOpacity = parentEffectiveOpacity*m_FillOpacity; + + VertexDataPtr pShapeVD = m_pFillShape->getVertexData(); if (isDrawNeeded() || curOpacity != m_OldOpacity) { - pFillVA->reset(); + pShapeVD->reset(); Pixel32 color = getFillColorVal(); - color.setA((unsigned char)(curOpacity*255)); - calcFillVertexes(pFillVA, color); - pFillVA->update(); + calcFillVertexes(pShapeVD, color); m_OldOpacity = curOpacity; } - VectorNode::preRender(); + if (isVisible()) { + m_pFillShape->setVertexArray(pVA); + } + VectorNode::preRender(pVA, bIsParentActive, parentEffectiveOpacity); } static ProfilingZoneID RenderProfilingZone("FilledVectorNode::render"); -void FilledVectorNode::render(const DRect& rect) +void FilledVectorNode::render() { ScopeTimer Timer(RenderProfilingZone); - double curOpacity = getParent()->getEffectiveOpacity()*m_FillOpacity; + float curOpacity = getParent()->getEffectiveOpacity()*m_FillOpacity; if (curOpacity > 0.01) { - glColor4d(1.0, 1.0, 1.0, curOpacity); - m_pFillShape->draw(); + m_pFillShape->draw(getTransform(), curOpacity); } - VectorNode::render(rect); + VectorNode::render(); } -void FilledVectorNode::setFillColor(const string& sColor) +void FilledVectorNode::setFillColor(const UTF8String& sColor) { if (m_sFillColorName != sColor) { m_sFillColorName = sColor; @@ -184,7 +185,7 @@ void FilledVectorNode::setFillColor(const string& sColor) } } -const string& FilledVectorNode::getFillColor() const +const UTF8String& FilledVectorNode::getFillColor() const { return m_sFillColorName; } @@ -194,10 +195,10 @@ Pixel32 FilledVectorNode::getFillColorVal() const return m_FillColor; } -DPoint FilledVectorNode::calcFillTexCoord(const DPoint& pt, const DPoint& minPt, - const DPoint& maxPt) +glm::vec2 FilledVectorNode::calcFillTexCoord(const glm::vec2& pt, const glm::vec2& minPt, + const glm::vec2& maxPt) { - DPoint texPt; + glm::vec2 texPt; texPt.x = (m_FillTexCoord2.x-m_FillTexCoord1.x)*(pt.x-minPt.x)/(maxPt.x-minPt.x) +m_FillTexCoord1.x; texPt.y = (m_FillTexCoord2.y-m_FillTexCoord1.y)*(pt.y-minPt.y)/(maxPt.y-minPt.y) @@ -207,7 +208,7 @@ DPoint FilledVectorNode::calcFillTexCoord(const DPoint& pt, const DPoint& minPt, bool FilledVectorNode::isVisible() const { - return getActive() && (getEffectiveOpacity() > 0.01 || + return getEffectiveActive() && (getEffectiveOpacity() > 0.01 || getParent()->getEffectiveOpacity()*m_FillOpacity > 0.01); } diff --git a/src/player/FilledVectorNode.h b/src/player/FilledVectorNode.h index ff8451d..ae98595 100644 --- a/src/player/FilledVectorNode.h +++ b/src/player/FilledVectorNode.h @@ -1,6 +1,6 @@ // // libavg - Media Playback Engine. -// Copyright (C) 2003-2011 Ulrich von Zadow +// Copyright (C) 2003-2014 Ulrich von Zadow // // This library is free software; you can redistribute it and/or // modify it under the terms of the GNU Lesser General Public @@ -32,7 +32,7 @@ namespace avg { class AVG_API FilledVectorNode : public VectorNode { public: - static NodeDefinition createDefinition(); + static void registerType(); FilledVectorNode(const ArgList& args); virtual ~FilledVectorNode(); @@ -44,37 +44,39 @@ class AVG_API FilledVectorNode : public VectorNode void setFillTexHRef(const UTF8String& href); void setFillBitmap(BitmapPtr pBmp); - const DPoint& getFillTexCoord1() const; - void setFillTexCoord1(const DPoint& pt); - const DPoint& getFillTexCoord2() const; - void setFillTexCoord2(const DPoint& pt); + const glm::vec2& getFillTexCoord1() const; + void setFillTexCoord1(const glm::vec2& pt); + const glm::vec2& getFillTexCoord2() const; + void setFillTexCoord2(const glm::vec2& pt); - void setFillColor(const std::string& sColor); - const std::string& getFillColor() const; + void setFillColor(const UTF8String& sColor); + const UTF8String& getFillColor() const; - double getFillOpacity() const; - void setFillOpacity(double opacity); + float getFillOpacity() const; + void setFillOpacity(float opacity); - virtual void preRender(); - virtual void render(const DRect& rect); + virtual void preRender(const VertexArrayPtr& pVA, bool bIsParentActive, + float parentEffectiveOpacity); + virtual void render(); - virtual void calcFillVertexes(VertexArrayPtr& pVertexArray, Pixel32 color) = 0; + virtual void calcFillVertexes( + const VertexDataPtr& pVertexData, Pixel32 color) = 0; protected: Pixel32 getFillColorVal() const; - DPoint calcFillTexCoord(const DPoint& pt, const DPoint& minPt, - const DPoint& maxPt); + glm::vec2 calcFillTexCoord(const glm::vec2& pt, const glm::vec2& minPt, + const glm::vec2& maxPt); virtual bool isVisible() const; private: - double m_OldOpacity; + float m_OldOpacity; UTF8String m_FillTexHRef; - DPoint m_FillTexCoord1; - DPoint m_FillTexCoord2; + glm::vec2 m_FillTexCoord1; + glm::vec2 m_FillTexCoord2; ShapePtr m_pFillShape; - double m_FillOpacity; - std::string m_sFillColorName; + float m_FillOpacity; + UTF8String m_sFillColorName; Pixel32 m_FillColor; }; diff --git a/src/player/FontStyle.cpp b/src/player/FontStyle.cpp new file mode 100644 index 0000000..2980aa3 --- /dev/null +++ b/src/player/FontStyle.cpp @@ -0,0 +1,315 @@ +// +// libavg - Media Playback Engine. +// Copyright (C) 2003-2014 Ulrich von Zadow +// +// This library is free software; you can redistribute it and/or +// modify it under the terms of the GNU Lesser General Public +// License as published by the Free Software Foundation; either +// version 2 of the License, or (at your option) any later version. +// +// This library 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 +// Lesser General Public License for more details. +// +// You should have received a copy of the GNU Lesser General Public +// License along with this library; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +// +// Current versions can be found at www.libavg.de +// + +#include "FontStyle.h" + +#include "../base/ObjectCounter.h" +#include "../base/Exception.h" + +#include "TypeDefinition.h" +#include "Arg.h" + +using namespace std; + +namespace avg { + +void FontStyle::registerType() +{ + TypeDefinition def = TypeDefinition("fontstyle", "", + ExportedObject::buildObject<FontStyle>) + .addArg(Arg<string>("font", "sans", false, offsetof(FontStyle, m_sName))) + .addArg(Arg<string>("variant", "", false, offsetof(FontStyle, m_sVariant))) + .addArg(Arg<string>("color", "FFFFFF", false, offsetof(FontStyle, m_sColorName))) + .addArg(Arg<float>("aagamma", 1.0f, false, offsetof(FontStyle, m_AAGamma))) + .addArg(Arg<float>("fontsize", 15, false, offsetof(FontStyle, m_Size))) + .addArg(Arg<int>("indent", 0, false, offsetof(FontStyle, m_Indent))) + .addArg(Arg<float>("linespacing", 0, false, offsetof(FontStyle, m_LineSpacing))) + .addArg(Arg<string>("alignment", "left")) + .addArg(Arg<string>("wrapmode", "word")) + .addArg(Arg<bool>("justify", false, false, offsetof(FontStyle, m_bJustify))) + .addArg(Arg<float>("letterspacing", 0, false, + offsetof(FontStyle, m_LetterSpacing))) + .addArg(Arg<bool>("hint", true, false, offsetof(FontStyle, m_bHint))) + .addArg(Arg<FontStylePtr>("basestyle", FontStylePtr())) + ; + TypeRegistry::get()->registerType(def); +} + +FontStyle::FontStyle(const ArgList& args) +{ + args.setMembers(this); + setAlignment(args.getArgVal<string>("alignment")); + setWrapMode(args.getArgVal<string>("wrapmode")); + m_Color = colorStringToColor(m_sColorName); + if (args.getArgVal<FontStylePtr>("basestyle") != 0) { + applyBaseStyle(*(args.getArgVal<FontStylePtr>("basestyle")), args); + } +} + +FontStyle::FontStyle() +{ + const ArgList& args = TypeRegistry::get()->getTypeDef("fontstyle").getDefaultArgs(); + args.setMembers(this); + setAlignment(args.getArgVal<string>("alignment")); + setWrapMode(args.getArgVal<string>("wrapmode")); + m_Color = colorStringToColor(m_sColorName); +} + +FontStyle::~FontStyle() +{ +} + +template<class ATTR> +void setDefaultedAttr(ATTR& member, const string& sName, const ArgList& args, + const ATTR& attr) +{ + if (args.getArg(sName)->isDefault()) { + member = attr; + } +} + +void FontStyle::applyBaseStyle(const FontStyle& baseStyle, const ArgList& args) +{ + setDefaultedAttr(m_sName, "font", args, baseStyle.getFont()); + setDefaultedAttr(m_sVariant, "variant", args, baseStyle.getFontVariant()); + setDefaultedAttr(m_sColorName, "color", args, baseStyle.getColor()); + m_Color = colorStringToColor(m_sColorName); + setDefaultedAttr(m_AAGamma, "aagamma", args, baseStyle.getAAGamma()); + setDefaultedAttr(m_Size, "fontsize", args, baseStyle.getFontSize()); + setDefaultedAttr(m_Indent, "indent", args, baseStyle.getIndent()); + setDefaultedAttr(m_LineSpacing, "linespacing", args, baseStyle.getLineSpacing()); + setDefaultedAttr(m_Alignment, "alignment", args, baseStyle.getAlignmentVal()); + setDefaultedAttr(m_WrapMode, "wrapmode", args, baseStyle.getWrapModeVal()); + setDefaultedAttr(m_bJustify, "justify", args, baseStyle.getJustify()); + setDefaultedAttr(m_LetterSpacing, "letterspacing", args, + baseStyle.getLetterSpacing()); + setDefaultedAttr(m_bHint, "hint", args, baseStyle.getHint()); +} + +template<class ARG> +void setDefaultedArg(ARG& member, const string& sName, const ArgList& args) +{ + if (!args.getArg(sName)->isDefault()) { + member = args.getArgVal<ARG>(sName); + } +} + +void FontStyle::setDefaultedArgs(const ArgList& args) +{ + // Warning: The ArgList here contains args that are for a different class originally, + // so the member offsets are wrong. + setDefaultedArg(m_sName, "font", args); + setDefaultedArg(m_sVariant, "variant", args); + setDefaultedArg(m_sColorName, "color", args); + setColor(m_sColorName); + setDefaultedArg(m_AAGamma, "aagamma", args); + setDefaultedArg(m_Size, "fontsize", args); + setDefaultedArg(m_Indent, "indent", args); + setDefaultedArg(m_LineSpacing, "linespacing", args); + string s = getAlignment(); + setDefaultedArg(s, "alignment", args); + setAlignment(s); + s = getWrapMode(); + setDefaultedArg(s, "wrapmode", args); + setWrapMode(s); + setDefaultedArg(m_bJustify, "justify", args); + setDefaultedArg(m_LetterSpacing, "letterspacing", args); + setDefaultedArg(m_bHint, "hint", args); +} + +const std::string& FontStyle::getFont() const +{ + return m_sName; +} + +void FontStyle::setFont(const string& sName) +{ + m_sName = sName; +} + +const std::string& FontStyle::getFontVariant() const +{ + return m_sVariant; +} + +void FontStyle::setFontVariant(const std::string& sVariant) +{ + m_sVariant = sVariant; +} + +const std::string& FontStyle::getColor() const +{ + return m_sColorName; +} + +void FontStyle::setColor(const string& sColor) +{ + m_sColorName = sColor; + m_Color = colorStringToColor(m_sColorName); +} + +float FontStyle::getAAGamma() const +{ + return m_AAGamma; +} + +void FontStyle::setAAGamma(float gamma) +{ + m_AAGamma = gamma; +} + +float FontStyle::getFontSize() const +{ + return m_Size; +} + +void FontStyle::setFontSize(float size) +{ + if (size <= 1) { + throw Exception(AVG_ERR_INVALID_ARGS, "Font size < 1 is illegal."); + } + m_Size = size; +} + +int FontStyle::getIndent() const +{ + return m_Indent; +} + +void FontStyle::setIndent(int indent) +{ + m_Indent = indent; +} + +float FontStyle::getLineSpacing() const +{ + return m_LineSpacing; +} + +void FontStyle::setLineSpacing(float lineSpacing) +{ + m_LineSpacing = lineSpacing; +} + +string FontStyle::getAlignment() const +{ + switch(m_Alignment) { + case PANGO_ALIGN_LEFT: + return "left"; + case PANGO_ALIGN_CENTER: + return "center"; + case PANGO_ALIGN_RIGHT: + return "right"; + default: + AVG_ASSERT(false); + return ""; + } +} + +void FontStyle::setAlignment(const string& sAlign) +{ + if (sAlign == "left") { + m_Alignment = PANGO_ALIGN_LEFT; + } else if (sAlign == "center") { + m_Alignment = PANGO_ALIGN_CENTER; + } else if (sAlign == "right") { + m_Alignment = PANGO_ALIGN_RIGHT; + } else { + throw(Exception(AVG_ERR_UNSUPPORTED, + "Alignment "+sAlign+" not supported.")); + } +} + +void FontStyle::setWrapMode(const string& sWrapMode) +{ + if (sWrapMode == "word") { + m_WrapMode = PANGO_WRAP_WORD; + } else if (sWrapMode == "char") { + m_WrapMode = PANGO_WRAP_CHAR; + } else if (sWrapMode == "wordchar") { + m_WrapMode = PANGO_WRAP_WORD_CHAR; + } else { + throw(Exception(AVG_ERR_UNSUPPORTED, + "FontStyle wrapping mode "+sWrapMode+" not supported.")); + } +} + +string FontStyle::getWrapMode() const +{ + switch(m_WrapMode) { + case PANGO_WRAP_WORD: + return "word"; + case PANGO_WRAP_CHAR: + return "char"; + case PANGO_WRAP_WORD_CHAR: + return "wordchar"; + default: + AVG_ASSERT(false); + return ""; + } +} + +bool FontStyle::getJustify() const +{ + return m_bJustify; +} + +void FontStyle::setJustify(bool bJustify) +{ + m_bJustify = bJustify; +} + +float FontStyle::getLetterSpacing() const +{ + return m_LetterSpacing; +} + +void FontStyle::setLetterSpacing(float letterSpacing) +{ + m_LetterSpacing = letterSpacing; +} + +bool FontStyle::getHint() const +{ + return m_bHint; +} + +void FontStyle::setHint(bool bHint) +{ + m_bHint = bHint; +} + +PangoAlignment FontStyle::getAlignmentVal() const +{ + return m_Alignment; +} + +PangoWrapMode FontStyle::getWrapModeVal() const +{ + return m_WrapMode; +} + +Pixel32 FontStyle::getColorVal() const +{ + return m_Color; +} + +} diff --git a/src/player/FontStyle.h b/src/player/FontStyle.h new file mode 100644 index 0000000..513aa14 --- /dev/null +++ b/src/player/FontStyle.h @@ -0,0 +1,114 @@ +// +// libavg - Media Playback Engine. +// Copyright (C) 2003-2014 Ulrich von Zadow +// +// This library is free software; you can redistribute it and/or +// modify it under the terms of the GNU Lesser General Public +// License as published by the Free Software Foundation; either +// version 2 of the License, or (at your option) any later version. +// +// This library 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 +// Lesser General Public License for more details. +// +// You should have received a copy of the GNU Lesser General Public +// License along with this library; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +// +// Current versions can be found at www.libavg.de +// + +#ifndef _FontStyle_H_ +#define _FontStyle_H_ + +#include "../api.h" + +#include "ExportedObject.h" + +#include "../graphics/Pixel32.h" + +#include <pango/pango.h> +#include <boost/shared_ptr.hpp> + +#include <string> + +namespace avg { + +class FontStyle; +typedef boost::shared_ptr<class FontStyle> FontStylePtr; + +class AVG_API FontStyle: public ExportedObject +{ + public: + static void registerType(); + + FontStyle(const ArgList& args); + FontStyle(); + virtual ~FontStyle(); + + void setDefaultedArgs(const ArgList& args); + + const std::string& getFont() const; + void setFont(const std::string& sName); + + const std::string& getFontVariant() const; + void setFontVariant(const std::string& sVariant); + + const std::string& getColor() const; + void setColor(const std::string& sColor); + + virtual float getAAGamma() const; + virtual void setAAGamma(float gamma); + + float getFontSize() const; + void setFontSize(float size); + + int getIndent() const; + void setIndent(int indent); + + float getLineSpacing() const; + void setLineSpacing(float lineSpacing); + + std::string getAlignment() const; + void setAlignment(const std::string& sAlignment); + + std::string getWrapMode() const; + void setWrapMode(const std::string& sWrapMode); + + bool getJustify() const; + void setJustify(bool bJustify); + + float getLetterSpacing() const; + void setLetterSpacing(float letterSpacing); + + bool getHint() const; + void setHint(bool bHint); + + PangoAlignment getAlignmentVal() const; + PangoWrapMode getWrapModeVal() const; + Pixel32 getColorVal() const; + + private: + void applyBaseStyle(const FontStyle& baseStyle, const ArgList& args); + + std::string m_sName; + std::string m_sVariant; + std::string m_sColorName; + Pixel32 m_Color; + float m_AAGamma; + float m_Size; + int m_Indent; + float m_LineSpacing; + PangoAlignment m_Alignment; + PangoWrapMode m_WrapMode; + bool m_bJustify; + float m_LetterSpacing; + bool m_bHint; + +}; + +typedef boost::shared_ptr<class FontStyle> FontStylePtr; + +} +#endif diff --git a/src/player/HueSatFXNode.cpp b/src/player/HueSatFXNode.cpp index c65e9fa..b15f333 100644 --- a/src/player/HueSatFXNode.cpp +++ b/src/player/HueSatFXNode.cpp @@ -1,6 +1,6 @@ // // libavg - Media Playback Engine. -// Copyright (C) 2003-2011 Ulrich von Zadow +// Copyright (C) 2003-2014 Ulrich von Zadow // // This library is free software; you can redistribute it and/or // modify it under the terms of the GNU Lesser General Public @@ -24,7 +24,8 @@ #include "../base/ObjectCounter.h" #include "../base/Logger.h" -#include "../graphics/ShaderRegistry.h" + +#include "../graphics/BitmapLoader.h" #include<sstream> @@ -32,13 +33,12 @@ using namespace std; namespace avg { -HueSatFXNode::HueSatFXNode(int hue, int saturation, int lightness, - bool tint): - FXNode(), - m_fHue(hue), - m_fLightnessOffset(lightness), - m_fSaturation(saturation), - m_bColorize(tint) +HueSatFXNode::HueSatFXNode(int hue, int saturation, int lightness, bool bColorize) + : FXNode(), + m_fHue(hue), + m_fLightnessOffset(lightness), + m_fSaturation(saturation), + m_bColorize(bColorize) { ObjectCounter::get()->incRef(&typeid(*this)); } @@ -94,9 +94,9 @@ void HueSatFXNode::setHue(int hue) void HueSatFXNode::setSaturation(int saturation) { - if(m_bColorize){ + if (m_bColorize) { m_fSaturation = clamp(saturation, 0, 100); - }else{ + } else { m_fSaturation = clamp(saturation, -100, 100); } setFilterParams(); @@ -104,23 +104,19 @@ void HueSatFXNode::setSaturation(int saturation) void HueSatFXNode::setLightnessOffset(int lightnessOffset) { - m_fLightnessOffset= clamp(lightnessOffset, -100, 100); + m_fLightnessOffset = clamp(lightnessOffset, -100, 100); setFilterParams(); } void HueSatFXNode::setColorizing(bool colorize) { m_bColorize = colorize; - m_fHue = 0; - m_fLightnessOffset = 0; - m_fSaturation = m_bColorize ? 50 : 0; setFilterParams(); } GPUFilterPtr HueSatFXNode::createFilter(const IntPoint& size) { - filterPtr = GPUHueSatFilterPtr(new GPUHueSatFilter(size, B8G8R8A8, - false)); + filterPtr = GPUHueSatFilterPtr(new GPUHueSatFilter(size, true, false)); setFilterParams(); return filterPtr; } @@ -145,9 +141,9 @@ std::string HueSatFXNode::toString() int HueSatFXNode::clamp(int val, int min, int max) { int result = val; - if(val < min){ + if (val < min) { result = min; - }else if(val > max){ + } else if (val > max) { result = max; } return result; diff --git a/src/player/HueSatFXNode.h b/src/player/HueSatFXNode.h index 780c271..410a7ec 100644 --- a/src/player/HueSatFXNode.h +++ b/src/player/HueSatFXNode.h @@ -1,6 +1,6 @@ // // libavg - Media Playback Engine. -// Copyright (C) 2003-2011 Ulrich von Zadow +// Copyright (C) 2003-2014 Ulrich von Zadow // // This library is free software; you can redistribute it and/or // modify it under the terms of the GNU Lesser General Public @@ -37,8 +37,7 @@ namespace avg { class AVG_API HueSatFXNode : public FXNode { public: - HueSatFXNode(int hue=0, int saturation=0, int lightness=0, - bool tint=false); + HueSatFXNode(int hue=0, int saturation=0, int lightness=0, bool bColorize=false); virtual ~HueSatFXNode(); virtual void disconnect(); @@ -67,7 +66,7 @@ private: }; typedef boost::shared_ptr<HueSatFXNode> HueSatFXNodePtr; -} //end namespace avg +} #endif diff --git a/src/player/IBitmapLoadedListener.h b/src/player/IBitmapLoadedListener.h new file mode 100644 index 0000000..da32f8b --- /dev/null +++ b/src/player/IBitmapLoadedListener.h @@ -0,0 +1,44 @@ +// +// libavg - Media Playback Engine. +// Copyright (C) 2003-2014 Ulrich von Zadow +// +// This library is free software; you can redistribute it and/or +// modify it under the terms of the GNU Lesser General Public +// License as published by the Free Software Foundation; either +// version 2 of the License, or (at your option) any later version. +// +// This library 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 +// Lesser General Public License for more details. +// +// You should have received a copy of the GNU Lesser General Public +// License along with this library; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +// +// Current versions can be found at www.libavg.de +// + +#ifndef _IBitmapLoadedListener_H_ +#define _IBitmapLoadedListener_H_ + +#include "../api.h" + +#include <boost/shared_ptr.hpp> + +namespace avg { + +class Bitmap; +typedef boost::shared_ptr<Bitmap> BitmapPtr; +class Exception; + +class AVG_API IBitmapLoadedListener { +public: + virtual ~IBitmapLoadedListener() {}; + virtual void onBitmapLoaded(BitmapPtr pBmp) = 0; + virtual void onBitmapLoadError(const Exception* e) = 0; +}; + +} + +#endif diff --git a/src/player/IInputDevice.h b/src/player/IInputDevice.h index 709809d..b155efe 100644 --- a/src/player/IInputDevice.h +++ b/src/player/IInputDevice.h @@ -1,6 +1,6 @@ // // libavg - Media Playback Engine. -// Copyright (C) 2003-2011 Ulrich von Zadow +// Copyright (C) 2003-2014 Ulrich von Zadow // // This library is free software; you can redistribute it and/or // modify it under the terms of the GNU Lesser General Public diff --git a/src/player/Image.cpp b/src/player/Image.cpp index 35e6801..5ac5fb9 100644 --- a/src/player/Image.cpp +++ b/src/player/Image.cpp @@ -1,6 +1,6 @@ // // libavg - Media Playback Engine. -// Copyright (C) 2003-2011 Ulrich von Zadow +// Copyright (C) 2003-2014 Ulrich von Zadow // // This library is free software; you can redistribute it and/or // modify it under the terms of the GNU Lesser General Public @@ -26,6 +26,8 @@ #include "../base/ObjectCounter.h" #include "../graphics/Filterfliprgb.h" +#include "../graphics/TextureMover.h" +#include "../graphics/BitmapLoader.h" #include "OGLSurface.h" #include "OffscreenCanvas.h" @@ -122,8 +124,8 @@ void Image::setEmpty() void Image::setFilename(const std::string& sFilename, TextureCompression comp) { assertValid(); - AVG_TRACE(Logger::MEMORY, "Loading " << sFilename); - BitmapPtr pBmp(new Bitmap(sFilename)); + AVG_TRACE(Logger::category::MEMORY, Logger::severity::INFO, "Loading " << sFilename); + BitmapPtr pBmp = loadBitmap(sFilename); if (comp == TEXTURECOMPRESSION_B5G6R5 && pBmp->hasAlpha()) { throw Exception(AVG_ERR_UNSUPPORTED, "B5G6R5-compressed textures with an alpha channel are not supported."); @@ -136,6 +138,9 @@ void Image::setFilename(const std::string& sFilename, TextureCompression comp) switch (comp) { case TEXTURECOMPRESSION_B5G6R5: m_pBmp = BitmapPtr(new Bitmap(pBmp->getSize(), B5G6R5, sFilename)); + if (!BitmapLoader::get()->isBlueFirst()) { + FilterFlipRGB().applyInPlace(pBmp); + } m_pBmp->copyPixels(*pBmp); break; case TEXTURECOMPRESSION_NONE: @@ -165,10 +170,13 @@ void Image::setBitmap(BitmapPtr pBmp, TextureCompression comp) PixelFormat pf; switch (comp) { case TEXTURECOMPRESSION_NONE: - pf = calcSurfacePF(*pBmp); + pf = pBmp->getPixelFormat(); break; case TEXTURECOMPRESSION_B5G6R5: pf = B5G6R5; + if (!BitmapLoader::get()->isBlueFirst()) { + FilterFlipRGB().applyInPlace(pBmp); + } break; default: assert(false); @@ -179,7 +187,7 @@ void Image::setBitmap(BitmapPtr pBmp, TextureCompression comp) m_pSurface->getPixelFormat() != pf) { pTex = GLTexturePtr(new GLTexture(pBmp->getSize(), pf, - m_Material.getUseMipmaps(), m_Material.getWrapSMode(), + m_Material.getUseMipmaps(), 0, m_Material.getWrapSMode(), m_Material.getWrapTMode())); m_pSurface->create(pf, pTex); } @@ -265,23 +273,25 @@ IntPoint Image::getSize() PixelFormat Image::getPixelFormat() { - if (m_Source == NONE) { - return B8G8R8X8; + PixelFormat pf; + if (BitmapLoader::get()->isBlueFirst()) { + pf = B8G8R8X8; } else { + pf = R8G8B8X8; + } + if (m_Source != NONE) { switch (m_State) { case CPU: - if (m_Source == SCENE) { - return B8G8R8X8; - } else { - return m_pBmp->getPixelFormat(); + if (m_Source != SCENE) { + pf = m_pBmp->getPixelFormat(); } case GPU: - return m_pSurface->getPixelFormat(); + pf = m_pSurface->getPixelFormat(); default: AVG_ASSERT(false); - return B8G8R8X8; } } + return pf; } OGLSurface* Image::getSurface() @@ -327,34 +337,16 @@ string Image::compression2String(TextureCompression compression) void Image::setupSurface() { - PixelFormat pf = calcSurfacePF(*m_pBmp); + PixelFormat pf = m_pBmp->getPixelFormat(); +// cerr << "setupSurface: " << pf << endl; GLTexturePtr pTex(new GLTexture(m_pBmp->getSize(), pf, m_Material.getUseMipmaps(), - m_Material.getWrapSMode(), m_Material.getWrapTMode())); + 0, m_Material.getWrapSMode(), m_Material.getWrapTMode())); m_pSurface->create(pf, pTex); TextureMoverPtr pMover = TextureMover::create(m_pBmp->getSize(), pf, GL_STATIC_DRAW); - BitmapPtr pMoverBmp = pMover->lock(); - pMoverBmp->copyPixels(*m_pBmp); - pMover->unlock(); - pMover->moveToTexture(*pTex); + pMover->moveBmpToTexture(m_pBmp, *pTex); m_pBmp = BitmapPtr(); } -PixelFormat Image::calcSurfacePF(const Bitmap& bmp) -{ - PixelFormat pf; - pf = B8G8R8X8; - if (bmp.hasAlpha()) { - pf = B8G8R8A8; - } - if (bmp.getPixelFormat() == I8) { - pf = I8; - } - if (bmp.getPixelFormat() == B5G6R5) { - pf = B5G6R5; - } - return pf; -} - bool Image::changeSource(Source newSource) { if (newSource != m_Source) { @@ -388,8 +380,7 @@ void Image::assertValid() const AVG_ASSERT((m_Source == SCENE) == bool(m_pCanvas)); switch (m_State) { case CPU: - AVG_ASSERT((m_Source == FILE || m_Source == BITMAP) == - bool(m_pBmp)); + AVG_ASSERT((m_Source == FILE || m_Source == BITMAP) == bool(m_pBmp)); AVG_ASSERT(!(m_pSurface->isCreated())); break; case GPU: diff --git a/src/player/Image.h b/src/player/Image.h index f7be873..6b6ad83 100644 --- a/src/player/Image.h +++ b/src/player/Image.h @@ -1,6 +1,6 @@ // // libavg - Media Playback Engine. -// Copyright (C) 2003-2011 Ulrich von Zadow +// Copyright (C) 2003-2014 Ulrich von Zadow // // This library is free software; you can redistribute it and/or // modify it under the terms of the GNU Lesser General Public @@ -26,7 +26,7 @@ #include "MaterialInfo.h" -#include "../base/Point.h" +#include "../base/GLMHelper.h" #include "../graphics/Bitmap.h" #include <boost/shared_ptr.hpp> @@ -76,7 +76,6 @@ class AVG_API Image private: void setupSurface(); - PixelFormat calcSurfacePF(const Bitmap& Bmp); bool changeSource(Source newSource); void assertValid() const; diff --git a/src/player/ImageNode.cpp b/src/player/ImageNode.cpp index d584ef4..18543c2 100644 --- a/src/player/ImageNode.cpp +++ b/src/player/ImageNode.cpp @@ -1,6 +1,6 @@ // // libavg - Media Playback Engine. -// Copyright (C) 2003-2011 Ulrich von Zadow +// Copyright (C) 2003-2014 Ulrich von Zadow // // This library is free software; you can redistribute it and/or // modify it under the terms of the GNU Lesser General Public @@ -21,7 +21,7 @@ #include "ImageNode.h" -#include "NodeDefinition.h" +#include "TypeDefinition.h" #include "OGLSurface.h" #include "Player.h" #include "OffscreenCanvas.h" @@ -41,12 +41,13 @@ using namespace std; namespace avg { -NodeDefinition ImageNode::createDefinition() +void ImageNode::registerType() { - return NodeDefinition("image", Node::buildNode<ImageNode>) - .extendDefinition(RasterNode::createDefinition()) + TypeDefinition def = TypeDefinition("image", "rasternode", + ExportedObject::buildObject<ImageNode>) .addArg(Arg<UTF8String>("href", "", false, offsetof(ImageNode, m_href))) .addArg(Arg<string>("compression", "none")); + TypeRegistry::get()->registerType(def); } ImageNode::ImageNode(const ArgList& args) @@ -73,7 +74,6 @@ void ImageNode::connectDisplay() if (m_pImage->getSource() == Image::SCENE) { checkCanvasValid(m_pImage->getCanvas()); } - getSurface()->attach(); m_pImage->moveToGPU(); RasterNode::connectDisplay(); if (m_pImage->getSource() == Image::SCENE) { @@ -135,33 +135,40 @@ const string ImageNode::getCompression() const void ImageNode::setBitmap(BitmapPtr pBmp) { - if (m_pImage->getSource() == Image::SCENE && getState() == Node::NS_CANRENDER) - { + if (m_pImage->getSource() == Image::SCENE && getState() == Node::NS_CANRENDER) { m_pImage->getCanvas()->removeDependentCanvas(getCanvas()); } m_pImage->setBitmap(pBmp, m_Compression); if (getState() == Node::NS_CANRENDER) { - bind(); + newSurface(); } m_href = ""; setViewport(-32767, -32767, -32767, -32767); } -void ImageNode::preRender() +static ProfilingZoneID PrerenderProfilingZone("ImageNode::prerender"); + +void ImageNode::preRender(const VertexArrayPtr& pVA, bool bIsParentActive, + float parentEffectiveOpacity) { - Node::preRender(); + ScopeTimer timer(PrerenderProfilingZone); + Node::preRender(pVA, bIsParentActive, parentEffectiveOpacity); if (isVisible()) { - renderFX(getSize(), Pixel32(255, 255, 255, 255), bool(m_pImage->getCanvas())); + bool bHasCanvas = bool(m_pImage->getCanvas()); + if (m_pImage->getSource() != Image::NONE) { + renderFX(getSize(), Pixel32(255, 255, 255, 255), bHasCanvas, bHasCanvas); + } } + calcVertexArray(pVA); } static ProfilingZoneID RenderProfilingZone("ImageNode::render"); -void ImageNode::render(const DRect& Rect) +void ImageNode::render() { ScopeTimer Timer(RenderProfilingZone); if (m_pImage->getSource() != Image::NONE) { - blt32(getSize(), getEffectiveOpacity(), getBlendMode(), + blt32(getTransform(), getSize(), getEffectiveOpacity(), getBlendMode(), bool(m_pImage->getCanvas())); } } @@ -184,21 +191,25 @@ void ImageNode::checkReload() if (getState() == NS_CANRENDER) { pCanvas->addDependentCanvas(getCanvas()); } + newSurface(); } else { - Node::checkReload(m_href, m_pImage, m_Compression); + bool bNewImage = Node::checkReload(m_href, m_pImage, m_Compression); + if (bNewImage) { + newSurface(); + } } setViewport(-32767, -32767, -32767, -32767); RasterNode::checkReload(); } -void ImageNode::getElementsByPos(const DPoint& pos, vector<NodeWeakPtr>& pElements) +void ImageNode::getElementsByPos(const glm::vec2& pos, vector<NodePtr>& pElements) { if (reactsToMouseEvents()) { OffscreenCanvasPtr pCanvas = m_pImage->getCanvas(); if (pCanvas && pCanvas->getHandleEvents()) { - DPoint nodeSize(getSize()); - DPoint canvasSize(pCanvas->getSize()); - DPoint localPos(pos.x*(canvasSize.x/nodeSize.x), + glm::vec2 nodeSize(getSize()); + glm::vec2 canvasSize(pCanvas->getSize()); + glm::vec2 localPos(pos.x*(canvasSize.x/nodeSize.x), pos.y*(canvasSize.y/nodeSize.y)); pCanvas->getRootNode()->getElementsByPos(localPos, pElements); } else { diff --git a/src/player/ImageNode.h b/src/player/ImageNode.h index e460c98..fce7d71 100644 --- a/src/player/ImageNode.h +++ b/src/player/ImageNode.h @@ -1,6 +1,6 @@ // // libavg - Media Playback Engine. -// Copyright (C) 2003-2011 Ulrich von Zadow +// Copyright (C) 2003-2014 Ulrich von Zadow // // This library is free software; you can redistribute it and/or // modify it under the terms of the GNU Lesser General Public @@ -36,7 +36,7 @@ namespace avg { class AVG_API ImageNode : public RasterNode { public: - static NodeDefinition createDefinition(); + static void registerType(); ImageNode(const ArgList& args); virtual ~ImageNode(); @@ -50,10 +50,11 @@ class AVG_API ImageNode : public RasterNode const std::string getCompression() const; void setBitmap(BitmapPtr pBmp); - virtual void preRender(); - virtual void render(const DRect& Rect); + virtual void preRender(const VertexArrayPtr& pVA, bool bIsParentActive, + float parentEffectiveOpacity); + virtual void render(); - void getElementsByPos(const DPoint& pos, std::vector<NodeWeakPtr>& pElements); + void getElementsByPos(const glm::vec2& pos, std::vector<NodePtr>& pElements); virtual BitmapPtr getBitmap(); virtual IntPoint getMediaSize(); diff --git a/src/player/InvertFXNode.cpp b/src/player/InvertFXNode.cpp index 589675a..c99cfa0 100644 --- a/src/player/InvertFXNode.cpp +++ b/src/player/InvertFXNode.cpp @@ -1,6 +1,6 @@ // // libavg - Media Playback Engine. -// Copyright (C) 2003-2011 Ulrich von Zadow +// Copyright (C) 2003-2014 Ulrich von Zadow // // This library is free software; you can redistribute it and/or // modify it under the terms of the GNU Lesser General Public @@ -23,7 +23,8 @@ #include "../base/ObjectCounter.h" #include "../base/Logger.h" -#include "../graphics/ShaderRegistry.h" + +#include "../graphics/BitmapLoader.h" #include <sstream> @@ -31,13 +32,14 @@ using namespace std; namespace avg { -InvertFXNode::InvertFXNode(): - FXNode() +InvertFXNode::InvertFXNode() + : FXNode() { ObjectCounter::get()->incRef(&typeid(*this)); } -InvertFXNode::~InvertFXNode() { +InvertFXNode::~InvertFXNode() +{ ObjectCounter::get()->decRef(&typeid(*this)); } @@ -49,8 +51,7 @@ void InvertFXNode::disconnect() GPUFilterPtr InvertFXNode::createFilter(const IntPoint& size) { - filterPtr = GPUInvertFilterPtr(new GPUInvertFilter(size, B8G8R8A8, - false)); + filterPtr = GPUInvertFilterPtr(new GPUInvertFilter(size, true, false)); setDirty(); return filterPtr; } diff --git a/src/player/InvertFXNode.h b/src/player/InvertFXNode.h index 5b148b2..53a6973 100644 --- a/src/player/InvertFXNode.h +++ b/src/player/InvertFXNode.h @@ -1,6 +1,6 @@ // // libavg - Media Playback Engine. -// Copyright (C) 2003-2011 Ulrich von Zadow +// Copyright (C) 2003-2014 Ulrich von Zadow // // This library is free software; you can redistribute it and/or // modify it under the terms of the GNU Lesser General Public diff --git a/src/player/KeyEvent.cpp b/src/player/KeyEvent.cpp index b922280..5ff8ce3 100644 --- a/src/player/KeyEvent.cpp +++ b/src/player/KeyEvent.cpp @@ -1,6 +1,6 @@ // // libavg - Media Playback Engine. -// Copyright (C) 2003-2011 Ulrich von Zadow +// Copyright (C) 2003-2014 Ulrich von Zadow // // This library is free software; you can redistribute it and/or // modify it under the terms of the GNU Lesser General Public @@ -72,8 +72,8 @@ int KeyEvent::getModifiers() const void KeyEvent::trace() { Event::trace(); - AVG_TRACE(Logger::EVENTS2, "Scancode: " << m_ScanCode - << ", Keycode: " << m_KeyCode << ", KeyString: " + AVG_TRACE(Logger::category::EVENTS, Logger::severity::DEBUG, + "Scancode: " << m_ScanCode << ", Keycode: " << m_KeyCode << ", KeyString: " << m_KeyString << ", Modifiers: " << m_Modifiers); } diff --git a/src/player/KeyEvent.h b/src/player/KeyEvent.h index 7559b7c..84ef8cf 100644 --- a/src/player/KeyEvent.h +++ b/src/player/KeyEvent.h @@ -1,6 +1,6 @@ // // libavg - Media Playback Engine. -// Copyright (C) 2003-2011 Ulrich von Zadow +// Copyright (C) 2003-2014 Ulrich von Zadow // // This library is free software; you can redistribute it and/or // modify it under the terms of the GNU Lesser General Public diff --git a/src/player/LibMTDevInputDevice.cpp b/src/player/LibMTDevInputDevice.cpp index 30eb11c..edfd061 100644 --- a/src/player/LibMTDevInputDevice.cpp +++ b/src/player/LibMTDevInputDevice.cpp @@ -1,6 +1,6 @@ // // libavg - Media Playback Engine. -// Copyright (C) 2003-2011 Ulrich von Zadow +// Copyright (C) 2003-2014 Ulrich von Zadow // // This library is free software; you can redistribute it and/or // modify it under the terms of the GNU Lesser General Public @@ -27,7 +27,6 @@ #include "TouchStatus.h" #include "../base/Logger.h" -#include "../base/Point.h" #include "../base/ObjectCounter.h" #include "../base/Exception.h" #include "../base/OSHelper.h" @@ -86,7 +85,8 @@ void LibMTDevInputDevice::start() m_Dimensions.br.y = pAbsInfo->maximum; MultitouchInputDevice::start(); - AVG_TRACE(Logger::CONFIG, "Linux MTDev Multitouch event source created."); + AVG_TRACE(Logger::category::CONFIG, Logger::severity::INFO, + "Linux MTDev Multitouch event source created."); } std::vector<EventPtr> LibMTDevInputDevice::pollEvents() @@ -117,7 +117,7 @@ std::vector<EventPtr> LibMTDevInputDevice::pollEvents() TouchEventPtr pOldEvent = pTouchStatus->getLastEvent(); TouchEventPtr pUpEvent = boost::dynamic_pointer_cast<TouchEvent>( - pOldEvent->cloneAs(Event::CURSORUP)); + pOldEvent->cloneAs(Event::CURSOR_UP)); pTouchStatus->pushEvent(pUpEvent); removeTouchStatus(pTouch->id); } @@ -162,14 +162,15 @@ void LibMTDevInputDevice::processEvents(const set<int>& changedIDs) if (!pTouchStatus) { // Down m_LastID++; - TouchEventPtr pEvent = createEvent(m_LastID, Event::CURSORDOWN, + TouchEventPtr pEvent = createEvent(m_LastID, Event::CURSOR_DOWN, touch.pos); // cerr << "down <" << touch.id << "> --> [" << m_LastID << "]" << endl; addTouchStatus((long)touch.id, pEvent); } else { // cerr << "move <" << touch.id << "> --> " << touch.pos << endl; // Move - TouchEventPtr pEvent = createEvent(0, Event::CURSORMOTION, touch.pos); + TouchEventPtr pEvent = createEvent(0, Event::CURSOR_MOTION, + touch.pos); pTouchStatus->pushEvent(pEvent); } } @@ -179,9 +180,9 @@ void LibMTDevInputDevice::processEvents(const set<int>& changedIDs) TouchEventPtr LibMTDevInputDevice::createEvent(int id, Event::Type type, IntPoint pos) { - DPoint size = getWindowSize(); - DPoint normPos = DPoint(double(pos.x-m_Dimensions.tl.x)/m_Dimensions.width(), - double(pos.y-m_Dimensions.tl.y)/m_Dimensions.height()); + glm::vec2 size(Player::get()->getScreenResolution()); + glm::vec2 normPos(float(pos.x-m_Dimensions.tl.x)/m_Dimensions.width(), + float(pos.y-m_Dimensions.tl.y)/m_Dimensions.height()); IntPoint screenPos(int(normPos.x*size.x+0.5), int(normPos.y*size.y+0.5)); return TouchEventPtr(new TouchEvent(id, type, screenPos, Event::TOUCH)); } diff --git a/src/player/LibMTDevInputDevice.h b/src/player/LibMTDevInputDevice.h index cb07695..d8417c1 100644 --- a/src/player/LibMTDevInputDevice.h +++ b/src/player/LibMTDevInputDevice.h @@ -1,6 +1,6 @@ // // libavg - Media Playback Engine. -// Copyright (C) 2003-2011 Ulrich von Zadow +// Copyright (C) 2003-2014 Ulrich von Zadow // // This library is free software; you can redistribute it and/or // modify it under the terms of the GNU Lesser General Public diff --git a/src/player/LineNode.cpp b/src/player/LineNode.cpp index 1ee299f..39a1b57 100644 --- a/src/player/LineNode.cpp +++ b/src/player/LineNode.cpp @@ -1,6 +1,6 @@ // // libavg - Media Playback Engine. -// Copyright (C) 2003-2011 Ulrich von Zadow +// Copyright (C) 2003-2014 Ulrich von Zadow // // This library is free software; you can redistribute it and/or // modify it under the terms of the GNU Lesser General Public @@ -21,7 +21,7 @@ #include "LineNode.h" -#include "NodeDefinition.h" +#include "TypeDefinition.h" #include "../base/Exception.h" @@ -32,15 +32,16 @@ using namespace std; namespace avg { -NodeDefinition LineNode::createDefinition() +void LineNode::registerType() { - return NodeDefinition("line", Node::buildNode<LineNode>) - .extendDefinition(VectorNode::createDefinition()) - .addArg(Arg<DPoint>("pos1", DPoint(0,0), false, offsetof(LineNode, m_P1))) - .addArg(Arg<DPoint>("pos2", DPoint(0,0), false, offsetof(LineNode, m_P2))) - .addArg(Arg<double>("texcoord1", 0, false, offsetof(LineNode, m_TC1))) - .addArg(Arg<double>("texcoord2", 1, false, offsetof(LineNode, m_TC2))) + TypeDefinition def = TypeDefinition("line", "vectornode", + ExportedObject::buildObject<LineNode>) + .addArg(Arg<glm::vec2>("pos1", glm::vec2(0,0), false, offsetof(LineNode, m_P1))) + .addArg(Arg<glm::vec2>("pos2", glm::vec2(0,0), false, offsetof(LineNode, m_P2))) + .addArg(Arg<float>("texcoord1", 0, false, offsetof(LineNode, m_TC1))) + .addArg(Arg<float>("texcoord2", 1, false, offsetof(LineNode, m_TC2))) ; + TypeRegistry::get()->registerType(def); } LineNode::LineNode(const ArgList& args) @@ -53,53 +54,53 @@ LineNode::~LineNode() { } -const DPoint& LineNode::getPos1() const +const glm::vec2& LineNode::getPos1() const { return m_P1; } -void LineNode::setPos1(const DPoint& pt) +void LineNode::setPos1(const glm::vec2& pt) { m_P1 = pt; setDrawNeeded(); } -const DPoint& LineNode::getPos2() const +const glm::vec2& LineNode::getPos2() const { return m_P2; } -void LineNode::setPos2(const DPoint& pt) +void LineNode::setPos2(const glm::vec2& pt) { m_P2 = pt; setDrawNeeded(); } -double LineNode::getTexCoord1() const +float LineNode::getTexCoord1() const { return m_TC1; } -void LineNode::setTexCoord1(double tc) +void LineNode::setTexCoord1(float tc) { m_TC1 = tc; setDrawNeeded(); } -double LineNode::getTexCoord2() const +float LineNode::getTexCoord2() const { return m_TC2; } -void LineNode::setTexCoord2(double tc) +void LineNode::setTexCoord2(float tc) { m_TC2 = tc; setDrawNeeded(); } -void LineNode::calcVertexes(VertexArrayPtr& pVertexArray, Pixel32 color) +void LineNode::calcVertexes(const VertexDataPtr& pVertexData, Pixel32 color) { - pVertexArray->addLineData(color, m_P1, m_P2, getStrokeWidth(), m_TC1, m_TC2); + pVertexData->addLineData(color, m_P1, m_P2, getStrokeWidth(), m_TC1, m_TC2); } } diff --git a/src/player/LineNode.h b/src/player/LineNode.h index daa5fbd..2843b48 100644 --- a/src/player/LineNode.h +++ b/src/player/LineNode.h @@ -1,6 +1,6 @@ // // libavg - Media Playback Engine. -// Copyright (C) 2003-2011 Ulrich von Zadow +// Copyright (C) 2003-2014 Ulrich von Zadow // // This library is free software; you can redistribute it and/or // modify it under the terms of the GNU Lesser General Public @@ -32,30 +32,30 @@ namespace avg { class AVG_API LineNode : public VectorNode { public: - static NodeDefinition createDefinition(); + static void registerType(); LineNode(const ArgList& args); virtual ~LineNode(); - const DPoint& getPos1() const; - void setPos1(const DPoint& pt); + const glm::vec2& getPos1() const; + void setPos1(const glm::vec2& pt); - const DPoint& getPos2() const; - void setPos2(const DPoint& pt); + const glm::vec2& getPos2() const; + void setPos2(const glm::vec2& pt); - double getTexCoord1() const; - void setTexCoord1(double tc); + float getTexCoord1() const; + void setTexCoord1(float tc); - double getTexCoord2() const; - void setTexCoord2(double tc); + float getTexCoord2() const; + void setTexCoord2(float tc); - virtual void calcVertexes(VertexArrayPtr& pVertexArray, Pixel32 color); + virtual void calcVertexes(const VertexDataPtr& pVertexData, Pixel32 color); private: - DPoint m_P1; - DPoint m_P2; - double m_TC1; - double m_TC2; + glm::vec2 m_P1; + glm::vec2 m_P2; + float m_TC1; + float m_TC2; }; } diff --git a/src/player/MainCanvas.cpp b/src/player/MainCanvas.cpp index c85db63..2af29fc 100644 --- a/src/player/MainCanvas.cpp +++ b/src/player/MainCanvas.cpp @@ -1,6 +1,6 @@ // // libavg - Media Playback Engine. -// Copyright (C) 2003-2011 Ulrich von Zadow +// Copyright (C) 2003-2014 Ulrich von Zadow // // This library is free software; you can redistribute it and/or // modify it under the terms of the GNU Lesser General Public @@ -59,7 +59,7 @@ void MainCanvas::setRoot(NodePtr pRootNode) void MainCanvas::initPlayback(const SDLDisplayEnginePtr& pDisplayEngine) { m_pDisplayEngine = pDisplayEngine; - Canvas::initPlayback(GLContext::getCurrent()->getConfig().m_MultiSampleSamples); + Canvas::initPlayback(GLContext::getMain()->getConfig().m_MultiSampleSamples); } BitmapPtr MainCanvas::screenshot() const @@ -73,10 +73,15 @@ BitmapPtr MainCanvas::screenshot() const static ProfilingZoneID RootRenderProfilingZone("Render MainCanvas"); -void MainCanvas::render() +void MainCanvas::renderTree() { - Canvas::render(m_pDisplayEngine->getWindowSize(), false, FBOPtr(), - RootRenderProfilingZone); + preRender(); + glproc::BindFramebuffer(GL_FRAMEBUFFER, 0); + GLContext::checkError("Canvas::renderTree: BindFramebuffer()"); + { + ScopeTimer Timer(RootRenderProfilingZone); + Canvas::render(m_pDisplayEngine->getWindowSize(), false); + } } } diff --git a/src/player/MainCanvas.h b/src/player/MainCanvas.h index c6d2310..55f68d6 100644 --- a/src/player/MainCanvas.h +++ b/src/player/MainCanvas.h @@ -1,6 +1,6 @@ // // libavg - Media Playback Engine. -// Copyright (C) 2003-2011 Ulrich von Zadow +// Copyright (C) 2003-2014 Ulrich von Zadow // // This library is free software; you can redistribute it and/or // modify it under the terms of the GNU Lesser General Public @@ -41,7 +41,7 @@ class AVG_API MainCanvas: public Canvas virtual BitmapPtr screenshot() const; private: - virtual void render(); + virtual void renderTree(); SDLDisplayEnginePtr m_pDisplayEngine; }; diff --git a/src/player/Makefile.am b/src/player/Makefile.am index 6dfd5e2..40d95d4 100644 --- a/src/player/Makefile.am +++ b/src/player/Makefile.am @@ -1,17 +1,26 @@ -INCLUDES = -I.. @XML2_CFLAGS@ @FREETYPE_CFLAGS@ \ - @PANGOFT2_CFLAGS@ @PYTHON_INCLUDES@ @GL_CFLAGS@ @FFMPEG_CFLAGS@ \ +AM_CPPFLAGS = -I.. @XML2_CFLAGS@ @FREETYPE_CFLAGS@ \ + @PANGOFT2_CFLAGS@ @PYTHON_CPPFLAGS@ @GL_CFLAGS@ \ @DC1394_2_CFLAGS@ @LIBRSVG_CFLAGS@ @FONTCONFIG_CFLAGS@ \ $(MTDEV_CFLAGS) - + if APPLE APPLE_SOURCES = SDLMain.m AppleTrackpadInputDevice.cpp - APPLE_LINKFLAGS=-read_only_relocs suppress -F/System/Library/PrivateFrameworks -framework MultitouchSupport + APPLE_LINKFLAGS = -read_only_relocs suppress -F/System/Library/PrivateFrameworks \ + -framework MultitouchSupport XGL_LIBS = else APPLE_SOURCES = - APPLE_LINKFLAGS= + APPLE_LINKFLAGS = +if ENABLE_RPI + XGL_LIBS = -lXxf86vm -lX11 -lGLESv2 -lEGL +else +if ENABLE_EGL + XGL_LIBS = -lXxf86vm -lX11 -lGLESv2 -lEGL +else XGL_LIBS = -lXxf86vm -lX11 endif +endif +endif if ENABLE_MTDEV MTDEV_SOURCES = LibMTDevInputDevice.cpp @@ -37,66 +46,76 @@ endif GL_SOURCES = OGLSurface.cpp SDLDisplayEngine.cpp GL_INCLUDES = OGLSurface.h SDLDisplayEngine.h -ALL_GL_LIBS = @GL_LIBS@ @SDL_LIBS@ $(XGL_LIBS) +ALL_GL_LIBS = @GL_LIBS@ @SDL_LIBS@ $(XGL_LIBS) -ALL_H = Player.h PluginManager.h IInputDevice.h VideoNode.h \ - DisplayEngine.h NodeRegistry.h Arg.h ArgBase.h ArgList.h \ - Node.h AreaNode.h DisplayParams.h NodeDefinition.h TextEngine.h \ +ALL_H = Player.h PluginManager.h IInputDevice.h VideoNode.h ExportedObject.h \ + DisplayEngine.h TypeRegistry.h Arg.h ArgBase.h ArgList.h \ + Node.h AreaNode.h DisplayParams.h TypeDefinition.h TextEngine.h \ AVGNode.h DivNode.h CursorState.h MaterialInfo.h Canvas.h MainCanvas.h \ Image.h ImageNode.h Timeout.h WordsNode.h WrapPython.h OffscreenCanvas.h \ EventDispatcher.h CursorEvent.h MouseEvent.h \ - Event.h KeyEvent.h PanoImageNode.h TestHelper.h CanvasNode.h \ + Event.h KeyEvent.h TestHelper.h CanvasNode.h \ OffscreenCanvasNode.h MultitouchInputDevice.h \ RasterNode.h CameraNode.h TrackerInputDevice.h TrackerCalibrator.h \ TouchEvent.h Contact.h TouchStatus.h TrackerTouchStatus.h BoostPython.h \ - SoundNode.h \ + SoundNode.h FontStyle.h \ VectorNode.h FilledVectorNode.h LineNode.h PolyLineNode.h RectNode.h \ CurveNode.h PolygonNode.h CircleNode.h Shape.h MeshNode.h FXNode.h \ NullFXNode.h BlurFXNode.h ShadowFXNode.h ChromaKeyFXNode.h HueSatFXNode.h \ InvertFXNode.h TUIOInputDevice.h VideoWriter.h VideoWriterThread.h \ - SVG.h SVGElement.h \ + SVG.h SVGElement.h Publisher.h SubscriberInfo.h PublisherDefinition.h \ + PublisherDefinitionRegistry.h MessageID.h VersionInfo.h \ + PythonLogSink.h BitmapManager.h BitmapManagerThread.h IBitmapLoadedListener.h \ + BitmapManagerMsg.h \ $(MTDEV_INCLUDES) $(GL_INCLUDES) $(XINPUT2_INCLUDES) -TESTS=testcalibrator testplayer +TESTS = testcalibrator testplayer EXTRA_DIST = SDLMain.h noinst_LTLIBRARIES = libplayer.la noinst_PROGRAMS = testcalibrator testplayer -testplayer_SOURCES=testplayer.cpp +testplayer_SOURCES = testplayer.cpp testplayer_LDADD = libplayer.la ../video/libvideo.la ../audio/libaudio.la \ + ../base/triangulate/libtriangulate.la \ ../imaging/libimaging.la ../graphics/libgraphics.la ../base/libbase.la \ ../lmfit/liblmfit.la ../oscpack/liboscpack.la \ - @XML2_LIBS@ -l@BOOST_THREAD_LIB@ -lboost_system @PTHREAD_LIBS@ @PANGOFT2_LIBS@ @LIBRSVG_LIBS@\ + @XML2_LIBS@ @BOOST_THREAD_LIBS@ @PTHREAD_CFLAGS@ @PTHREAD_LIBS@ @PANGOFT2_LIBS@ \ + @LIBRSVG_LIBS@ \ @DC1394_2_LIBS@ @GLU_LIBS@ $(ALL_GL_LIBS) $(XI2_1_LIBS) $(XI2_2_LIBS) \ - @LIBFFMPEG@ $(BOOST_PYTHON_LIBS) $(PYTHON_LIBS) @GDK_PIXBUF_LIBS@ \ + @LIBFFMPEG@ $(BOOST_PYTHON_LIBS) $(PYTHON_LDFLAGS) @GDK_PIXBUF_LIBS@ \ @FONTCONFIG_LIBS@ - + testplayer_LDFLAGS = $(APPLE_LINKFLAGS) -module -XCClinker -testcalibrator_SOURCES=testcalibrator.cpp +testcalibrator_SOURCES = testcalibrator.cpp testcalibrator_LDADD = libplayer.la ../video/libvideo.la ../audio/libaudio.la \ + ../base/triangulate/libtriangulate.la \ ../imaging/libimaging.la ../graphics/libgraphics.la ../base/libbase.la \ ../lmfit/liblmfit.la ../oscpack/liboscpack.la \ - @XML2_LIBS@ -l@BOOST_THREAD_LIB@ -lboost_system @PTHREAD_LIBS@ @LIBRSVG_LIBS@ @GDK_PIXBUF_LIBS@ + @XML2_LIBS@ @BOOST_THREAD_LIBS@ @PTHREAD_CFLAGS@ @PTHREAD_LIBS@ @LIBRSVG_LIBS@ \ + @GDK_PIXBUF_LIBS@ -libplayer_la_LIBADD = $(BOOST_PYTHON_LIBS) $(PYTHON_LIBS) $(MTDEV_LIBS) +libplayer_la_LIBADD = $(BOOST_PYTHON_LIBS) $(PYTHON_LDFLAGS) $(MTDEV_LIBS) libplayer_la_SOURCES = $(GL_SOURCES) \ - Arg.cpp AreaNode.cpp RasterNode.cpp DivNode.cpp VideoNode.cpp \ - Player.cpp PluginManager.cpp NodeRegistry.cpp ArgBase.cpp ArgList.cpp \ + Arg.cpp AreaNode.cpp RasterNode.cpp DivNode.cpp VideoNode.cpp ExportedObject.cpp \ + Player.cpp PluginManager.cpp TypeRegistry.cpp ArgBase.cpp ArgList.cpp \ DisplayEngine.cpp Canvas.cpp CanvasNode.cpp OffscreenCanvasNode.cpp \ - MainCanvas.cpp Node.cpp MultitouchInputDevice.cpp \ - PanoImageNode.cpp WordsNode.cpp CameraNode.cpp NodeDefinition.cpp TextEngine.cpp \ + MainCanvas.cpp Node.cpp MultitouchInputDevice.cpp WrapPython.cpp \ + WordsNode.cpp CameraNode.cpp TypeDefinition.cpp TextEngine.cpp \ Timeout.cpp Event.cpp DisplayParams.cpp CursorState.cpp MaterialInfo.cpp \ Image.cpp ImageNode.cpp EventDispatcher.cpp KeyEvent.cpp CursorEvent.cpp \ MouseEvent.cpp TouchEvent.cpp AVGNode.cpp TestHelper.cpp \ TrackerInputDevice.cpp TrackerTouchStatus.cpp TrackerCalibrator.cpp \ - SoundNode.cpp \ + SoundNode.cpp FontStyle.cpp \ VectorNode.cpp FilledVectorNode.cpp LineNode.cpp PolyLineNode.cpp \ RectNode.cpp CurveNode.cpp PolygonNode.cpp CircleNode.cpp Shape.cpp MeshNode.cpp \ Contact.cpp TouchStatus.cpp OffscreenCanvas.cpp FXNode.cpp TUIOInputDevice.cpp \ NullFXNode.cpp BlurFXNode.cpp ShadowFXNode.cpp ChromaKeyFXNode.cpp \ InvertFXNode.cpp HueSatFXNode.cpp VideoWriter.cpp VideoWriterThread.cpp \ - SVG.cpp SVGElement.cpp \ + SVG.cpp SVGElement.cpp Publisher.cpp SubscriberInfo.cpp PublisherDefinition.cpp \ + PublisherDefinitionRegistry.cpp MessageID.cpp VersionInfo.cpp \ + PythonLogSink.cpp BitmapManager.cpp BitmapManagerThread.cpp \ + BitmapManagerMsg.cpp \ $(MTDEV_SOURCES) $(XINPUT2_SOURCES) $(APPLE_SOURCES) $(ALL_H) libplayer_a_CXXFLAGS = -DPREFIXDIR=\"$(prefix)\" diff --git a/src/player/Makefile.in b/src/player/Makefile.in index 047b46a..a87be83 100644 --- a/src/player/Makefile.in +++ b/src/player/Makefile.in @@ -1,9 +1,9 @@ -# Makefile.in generated by automake 1.11.1 from Makefile.am. +# Makefile.in generated by automake 1.11.3 from Makefile.am. # @configure_input@ # Copyright (C) 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, -# 2003, 2004, 2005, 2006, 2007, 2008, 2009 Free Software Foundation, -# Inc. +# 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010, 2011 Free Software +# Foundation, Inc. # This Makefile.in is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, # with or without modifications, as long as this notice is preserved. @@ -44,11 +44,12 @@ ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 am__aclocal_m4_deps = $(top_srcdir)/m4/ac_cxx_namespaces.m4 \ $(top_srcdir)/m4/ac_path_generic.m4 \ $(top_srcdir)/m4/ax_boost_thread.m4 \ - $(top_srcdir)/m4/ax_check_gl.m4 $(top_srcdir)/m4/libtool.m4 \ - $(top_srcdir)/m4/ltoptions.m4 $(top_srcdir)/m4/ltsugar.m4 \ - $(top_srcdir)/m4/ltversion.m4 $(top_srcdir)/m4/lt~obsolete.m4 \ - $(top_srcdir)/m4/pkg.m4 $(top_srcdir)/m4/python_dev.m4 \ - $(top_srcdir)/configure.in + $(top_srcdir)/m4/ax_check_gl.m4 \ + $(top_srcdir)/m4/ax_python_devel.m4 \ + $(top_srcdir)/m4/libtool.m4 $(top_srcdir)/m4/ltoptions.m4 \ + $(top_srcdir)/m4/ltsugar.m4 $(top_srcdir)/m4/ltversion.m4 \ + $(top_srcdir)/m4/lt~obsolete.m4 $(top_srcdir)/m4/pkg.m4 \ + $(top_srcdir)/m4/avg_version.m4 $(top_srcdir)/configure.ac am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \ $(ACLOCAL_M4) mkinstalldirs = $(SHELL) $(top_srcdir)/mkinstalldirs @@ -61,42 +62,52 @@ libplayer_la_DEPENDENCIES = $(am__DEPENDENCIES_1) \ $(am__DEPENDENCIES_1) $(am__DEPENDENCIES_1) am__libplayer_la_SOURCES_DIST = OGLSurface.cpp SDLDisplayEngine.cpp \ Arg.cpp AreaNode.cpp RasterNode.cpp DivNode.cpp VideoNode.cpp \ - Player.cpp PluginManager.cpp NodeRegistry.cpp ArgBase.cpp \ - ArgList.cpp DisplayEngine.cpp Canvas.cpp CanvasNode.cpp \ - OffscreenCanvasNode.cpp MainCanvas.cpp Node.cpp \ - MultitouchInputDevice.cpp PanoImageNode.cpp WordsNode.cpp \ - CameraNode.cpp NodeDefinition.cpp TextEngine.cpp Timeout.cpp \ - Event.cpp DisplayParams.cpp CursorState.cpp MaterialInfo.cpp \ - Image.cpp ImageNode.cpp EventDispatcher.cpp KeyEvent.cpp \ - CursorEvent.cpp MouseEvent.cpp TouchEvent.cpp AVGNode.cpp \ - TestHelper.cpp TrackerInputDevice.cpp TrackerTouchStatus.cpp \ - TrackerCalibrator.cpp SoundNode.cpp VectorNode.cpp \ - FilledVectorNode.cpp LineNode.cpp PolyLineNode.cpp \ - RectNode.cpp CurveNode.cpp PolygonNode.cpp CircleNode.cpp \ - Shape.cpp MeshNode.cpp Contact.cpp TouchStatus.cpp \ - OffscreenCanvas.cpp FXNode.cpp TUIOInputDevice.cpp \ - NullFXNode.cpp BlurFXNode.cpp ShadowFXNode.cpp \ - ChromaKeyFXNode.cpp InvertFXNode.cpp HueSatFXNode.cpp \ - VideoWriter.cpp VideoWriterThread.cpp SVG.cpp SVGElement.cpp \ + ExportedObject.cpp Player.cpp PluginManager.cpp \ + TypeRegistry.cpp ArgBase.cpp ArgList.cpp DisplayEngine.cpp \ + Canvas.cpp CanvasNode.cpp OffscreenCanvasNode.cpp \ + MainCanvas.cpp Node.cpp MultitouchInputDevice.cpp \ + WrapPython.cpp WordsNode.cpp CameraNode.cpp TypeDefinition.cpp \ + TextEngine.cpp Timeout.cpp Event.cpp DisplayParams.cpp \ + CursorState.cpp MaterialInfo.cpp Image.cpp ImageNode.cpp \ + EventDispatcher.cpp KeyEvent.cpp CursorEvent.cpp \ + MouseEvent.cpp TouchEvent.cpp AVGNode.cpp TestHelper.cpp \ + TrackerInputDevice.cpp TrackerTouchStatus.cpp \ + TrackerCalibrator.cpp SoundNode.cpp FontStyle.cpp \ + VectorNode.cpp FilledVectorNode.cpp LineNode.cpp \ + PolyLineNode.cpp RectNode.cpp CurveNode.cpp PolygonNode.cpp \ + CircleNode.cpp Shape.cpp MeshNode.cpp Contact.cpp \ + TouchStatus.cpp OffscreenCanvas.cpp FXNode.cpp \ + TUIOInputDevice.cpp NullFXNode.cpp BlurFXNode.cpp \ + ShadowFXNode.cpp ChromaKeyFXNode.cpp InvertFXNode.cpp \ + HueSatFXNode.cpp VideoWriter.cpp VideoWriterThread.cpp SVG.cpp \ + SVGElement.cpp Publisher.cpp SubscriberInfo.cpp \ + PublisherDefinition.cpp PublisherDefinitionRegistry.cpp \ + MessageID.cpp VersionInfo.cpp PythonLogSink.cpp \ + BitmapManager.cpp BitmapManagerThread.cpp BitmapManagerMsg.cpp \ LibMTDevInputDevice.cpp XInputMTInputDevice.cpp SDLMain.m \ AppleTrackpadInputDevice.cpp Player.h PluginManager.h \ - IInputDevice.h VideoNode.h DisplayEngine.h NodeRegistry.h \ - Arg.h ArgBase.h ArgList.h Node.h AreaNode.h DisplayParams.h \ - NodeDefinition.h TextEngine.h AVGNode.h DivNode.h \ - CursorState.h MaterialInfo.h Canvas.h MainCanvas.h Image.h \ - ImageNode.h Timeout.h WordsNode.h WrapPython.h \ + IInputDevice.h VideoNode.h ExportedObject.h DisplayEngine.h \ + TypeRegistry.h Arg.h ArgBase.h ArgList.h Node.h AreaNode.h \ + DisplayParams.h TypeDefinition.h TextEngine.h AVGNode.h \ + DivNode.h CursorState.h MaterialInfo.h Canvas.h MainCanvas.h \ + Image.h ImageNode.h Timeout.h WordsNode.h WrapPython.h \ OffscreenCanvas.h EventDispatcher.h CursorEvent.h MouseEvent.h \ - Event.h KeyEvent.h PanoImageNode.h TestHelper.h CanvasNode.h \ + Event.h KeyEvent.h TestHelper.h CanvasNode.h \ OffscreenCanvasNode.h MultitouchInputDevice.h RasterNode.h \ CameraNode.h TrackerInputDevice.h TrackerCalibrator.h \ TouchEvent.h Contact.h TouchStatus.h TrackerTouchStatus.h \ - BoostPython.h SoundNode.h VectorNode.h FilledVectorNode.h \ - LineNode.h PolyLineNode.h RectNode.h CurveNode.h PolygonNode.h \ - CircleNode.h Shape.h MeshNode.h FXNode.h NullFXNode.h \ - BlurFXNode.h ShadowFXNode.h ChromaKeyFXNode.h HueSatFXNode.h \ - InvertFXNode.h TUIOInputDevice.h VideoWriter.h \ - VideoWriterThread.h SVG.h SVGElement.h LibMTDevInputDevice.h \ - OGLSurface.h SDLDisplayEngine.h XInputMTInputDevice.h + BoostPython.h SoundNode.h FontStyle.h VectorNode.h \ + FilledVectorNode.h LineNode.h PolyLineNode.h RectNode.h \ + CurveNode.h PolygonNode.h CircleNode.h Shape.h MeshNode.h \ + FXNode.h NullFXNode.h BlurFXNode.h ShadowFXNode.h \ + ChromaKeyFXNode.h HueSatFXNode.h InvertFXNode.h \ + TUIOInputDevice.h VideoWriter.h VideoWriterThread.h SVG.h \ + SVGElement.h Publisher.h SubscriberInfo.h \ + PublisherDefinition.h PublisherDefinitionRegistry.h \ + MessageID.h VersionInfo.h PythonLogSink.h BitmapManager.h \ + BitmapManagerThread.h IBitmapLoadedListener.h \ + BitmapManagerMsg.h LibMTDevInputDevice.h OGLSurface.h \ + SDLDisplayEngine.h XInputMTInputDevice.h am__objects_1 = OGLSurface.lo SDLDisplayEngine.lo @ENABLE_MTDEV_TRUE@am__objects_2 = LibMTDevInputDevice.lo @HAVE_XI2_1_FALSE@@HAVE_XI2_2_TRUE@am__objects_3 = \ @@ -106,46 +117,50 @@ am__objects_1 = OGLSurface.lo SDLDisplayEngine.lo am__objects_5 = am__objects_6 = $(am__objects_5) $(am__objects_5) $(am__objects_5) am_libplayer_la_OBJECTS = $(am__objects_1) Arg.lo AreaNode.lo \ - RasterNode.lo DivNode.lo VideoNode.lo Player.lo \ - PluginManager.lo NodeRegistry.lo ArgBase.lo ArgList.lo \ - DisplayEngine.lo Canvas.lo CanvasNode.lo \ + RasterNode.lo DivNode.lo VideoNode.lo ExportedObject.lo \ + Player.lo PluginManager.lo TypeRegistry.lo ArgBase.lo \ + ArgList.lo DisplayEngine.lo Canvas.lo CanvasNode.lo \ OffscreenCanvasNode.lo MainCanvas.lo Node.lo \ - MultitouchInputDevice.lo PanoImageNode.lo WordsNode.lo \ - CameraNode.lo NodeDefinition.lo TextEngine.lo Timeout.lo \ + MultitouchInputDevice.lo WrapPython.lo WordsNode.lo \ + CameraNode.lo TypeDefinition.lo TextEngine.lo Timeout.lo \ Event.lo DisplayParams.lo CursorState.lo MaterialInfo.lo \ Image.lo ImageNode.lo EventDispatcher.lo KeyEvent.lo \ CursorEvent.lo MouseEvent.lo TouchEvent.lo AVGNode.lo \ TestHelper.lo TrackerInputDevice.lo TrackerTouchStatus.lo \ - TrackerCalibrator.lo SoundNode.lo VectorNode.lo \ + TrackerCalibrator.lo SoundNode.lo FontStyle.lo VectorNode.lo \ FilledVectorNode.lo LineNode.lo PolyLineNode.lo RectNode.lo \ CurveNode.lo PolygonNode.lo CircleNode.lo Shape.lo MeshNode.lo \ Contact.lo TouchStatus.lo OffscreenCanvas.lo FXNode.lo \ TUIOInputDevice.lo NullFXNode.lo BlurFXNode.lo ShadowFXNode.lo \ ChromaKeyFXNode.lo InvertFXNode.lo HueSatFXNode.lo \ VideoWriter.lo VideoWriterThread.lo SVG.lo SVGElement.lo \ - $(am__objects_2) $(am__objects_3) $(am__objects_4) \ - $(am__objects_6) + Publisher.lo SubscriberInfo.lo PublisherDefinition.lo \ + PublisherDefinitionRegistry.lo MessageID.lo VersionInfo.lo \ + PythonLogSink.lo BitmapManager.lo BitmapManagerThread.lo \ + BitmapManagerMsg.lo $(am__objects_2) $(am__objects_3) \ + $(am__objects_4) $(am__objects_6) libplayer_la_OBJECTS = $(am_libplayer_la_OBJECTS) -AM_V_lt = $(am__v_lt_$(V)) -am__v_lt_ = $(am__v_lt_$(AM_DEFAULT_VERBOSITY)) +AM_V_lt = $(am__v_lt_@AM_V@) +am__v_lt_ = $(am__v_lt_@AM_DEFAULT_V@) am__v_lt_0 = --silent PROGRAMS = $(noinst_PROGRAMS) am_testcalibrator_OBJECTS = testcalibrator.$(OBJEXT) testcalibrator_OBJECTS = $(am_testcalibrator_OBJECTS) testcalibrator_DEPENDENCIES = libplayer.la ../video/libvideo.la \ - ../audio/libaudio.la ../imaging/libimaging.la \ - ../graphics/libgraphics.la ../base/libbase.la \ - ../lmfit/liblmfit.la ../oscpack/liboscpack.la + ../audio/libaudio.la ../base/triangulate/libtriangulate.la \ + ../imaging/libimaging.la ../graphics/libgraphics.la \ + ../base/libbase.la ../lmfit/liblmfit.la \ + ../oscpack/liboscpack.la am_testplayer_OBJECTS = testplayer.$(OBJEXT) testplayer_OBJECTS = $(am_testplayer_OBJECTS) am__DEPENDENCIES_2 = $(am__DEPENDENCIES_1) testplayer_DEPENDENCIES = libplayer.la ../video/libvideo.la \ - ../audio/libaudio.la ../imaging/libimaging.la \ - ../graphics/libgraphics.la ../base/libbase.la \ - ../lmfit/liblmfit.la ../oscpack/liboscpack.la \ - $(am__DEPENDENCIES_2) $(am__DEPENDENCIES_1) \ + ../audio/libaudio.la ../base/triangulate/libtriangulate.la \ + ../imaging/libimaging.la ../graphics/libgraphics.la \ + ../base/libbase.la ../lmfit/liblmfit.la \ + ../oscpack/liboscpack.la $(am__DEPENDENCIES_2) \ $(am__DEPENDENCIES_1) $(am__DEPENDENCIES_1) \ - $(am__DEPENDENCIES_1) + $(am__DEPENDENCIES_1) $(am__DEPENDENCIES_1) testplayer_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) \ $(LIBTOOLFLAGS) --mode=link $(CXXLD) $(AM_CXXFLAGS) \ $(CXXFLAGS) $(testplayer_LDFLAGS) $(LDFLAGS) -o $@ @@ -159,18 +174,18 @@ LTCXXCOMPILE = $(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) \ $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) \ $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) \ $(AM_CXXFLAGS) $(CXXFLAGS) -AM_V_CXX = $(am__v_CXX_$(V)) -am__v_CXX_ = $(am__v_CXX_$(AM_DEFAULT_VERBOSITY)) +AM_V_CXX = $(am__v_CXX_@AM_V@) +am__v_CXX_ = $(am__v_CXX_@AM_DEFAULT_V@) am__v_CXX_0 = @echo " CXX " $@; -AM_V_at = $(am__v_at_$(V)) -am__v_at_ = $(am__v_at_$(AM_DEFAULT_VERBOSITY)) +AM_V_at = $(am__v_at_@AM_V@) +am__v_at_ = $(am__v_at_@AM_DEFAULT_V@) am__v_at_0 = @ CXXLD = $(CXX) CXXLINK = $(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) \ $(LIBTOOLFLAGS) --mode=link $(CXXLD) $(AM_CXXFLAGS) \ $(CXXFLAGS) $(AM_LDFLAGS) $(LDFLAGS) -o $@ -AM_V_CXXLD = $(am__v_CXXLD_$(V)) -am__v_CXXLD_ = $(am__v_CXXLD_$(AM_DEFAULT_VERBOSITY)) +AM_V_CXXLD = $(am__v_CXXLD_@AM_V@) +am__v_CXXLD_ = $(am__v_CXXLD_@AM_DEFAULT_V@) am__v_CXXLD_0 = @echo " CXXLD " $@; OBJCCOMPILE = $(OBJC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) \ $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_OBJCFLAGS) $(OBJCFLAGS) @@ -178,15 +193,15 @@ LTOBJCCOMPILE = $(LIBTOOL) $(AM_V_lt) $(AM_LIBTOOLFLAGS) \ $(LIBTOOLFLAGS) --mode=compile $(OBJC) $(DEFS) \ $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) \ $(AM_OBJCFLAGS) $(OBJCFLAGS) -AM_V_OBJC = $(am__v_OBJC_$(V)) -am__v_OBJC_ = $(am__v_OBJC_$(AM_DEFAULT_VERBOSITY)) +AM_V_OBJC = $(am__v_OBJC_@AM_V@) +am__v_OBJC_ = $(am__v_OBJC_@AM_DEFAULT_V@) am__v_OBJC_0 = @echo " OBJC " $@; OBJCLD = $(OBJC) OBJCLINK = $(LIBTOOL) $(AM_V_lt) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) \ --mode=link $(OBJCLD) $(AM_OBJCFLAGS) $(OBJCFLAGS) \ $(AM_LDFLAGS) $(LDFLAGS) -o $@ -AM_V_OBJCLD = $(am__v_OBJCLD_$(V)) -am__v_OBJCLD_ = $(am__v_OBJCLD_$(AM_DEFAULT_VERBOSITY)) +AM_V_OBJCLD = $(am__v_OBJCLD_@AM_V@) +am__v_OBJCLD_ = $(am__v_OBJCLD_@AM_DEFAULT_V@) am__v_OBJCLD_0 = @echo " OBJCLD" $@; COMPILE = $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) \ $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) @@ -194,18 +209,18 @@ LTCOMPILE = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \ $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) \ $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) \ $(AM_CFLAGS) $(CFLAGS) -AM_V_CC = $(am__v_CC_$(V)) -am__v_CC_ = $(am__v_CC_$(AM_DEFAULT_VERBOSITY)) +AM_V_CC = $(am__v_CC_@AM_V@) +am__v_CC_ = $(am__v_CC_@AM_DEFAULT_V@) am__v_CC_0 = @echo " CC " $@; CCLD = $(CC) LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \ $(LIBTOOLFLAGS) --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) \ $(AM_LDFLAGS) $(LDFLAGS) -o $@ -AM_V_CCLD = $(am__v_CCLD_$(V)) -am__v_CCLD_ = $(am__v_CCLD_$(AM_DEFAULT_VERBOSITY)) +AM_V_CCLD = $(am__v_CCLD_@AM_V@) +am__v_CCLD_ = $(am__v_CCLD_@AM_DEFAULT_V@) am__v_CCLD_0 = @echo " CCLD " $@; -AM_V_GEN = $(am__v_GEN_$(V)) -am__v_GEN_ = $(am__v_GEN_$(AM_DEFAULT_VERBOSITY)) +AM_V_GEN = $(am__v_GEN_@AM_V@) +am__v_GEN_ = $(am__v_GEN_@AM_DEFAULT_V@) am__v_GEN_0 = @echo " GEN " $@; SOURCES = $(libplayer_la_SOURCES) $(testcalibrator_SOURCES) \ $(testplayer_SOURCES) @@ -225,7 +240,7 @@ AUTOHEADER = @AUTOHEADER@ AUTOMAKE = @AUTOMAKE@ AWK = @AWK@ BOOST_PYTHON_LIBS = @BOOST_PYTHON_LIBS@ -BOOST_THREAD_LIB = @BOOST_THREAD_LIB@ +BOOST_THREAD_LIBS = @BOOST_THREAD_LIBS@ CC = @CC@ CCDEPMODE = @CCDEPMODE@ CFLAGS = @CFLAGS@ @@ -240,6 +255,7 @@ DC1394_2_CFLAGS = @DC1394_2_CFLAGS@ DC1394_2_LIBS = @DC1394_2_LIBS@ DEFS = @DEFS@ DEPDIR = @DEPDIR@ +DLLTOOL = @DLLTOOL@ DSYMUTIL = @DSYMUTIL@ DUMPBIN = @DUMPBIN@ ECHO_C = @ECHO_C@ @@ -280,6 +296,7 @@ LIPO = @LIPO@ LN_S = @LN_S@ LTLIBOBJS = @LTLIBOBJS@ MAKEINFO = @MAKEINFO@ +MANIFEST_TOOL = @MANIFEST_TOOL@ MKDIR_P = @MKDIR_P@ MTDEV_CFLAGS = @MTDEV_CFLAGS@ MTDEV_LIBS = @MTDEV_LIBS@ @@ -309,11 +326,13 @@ PTHREAD_CC = @PTHREAD_CC@ PTHREAD_CFLAGS = @PTHREAD_CFLAGS@ PTHREAD_LIBS = @PTHREAD_LIBS@ PYTHON = @PYTHON@ +PYTHON_CPPFLAGS = @PYTHON_CPPFLAGS@ PYTHON_EXEC_PREFIX = @PYTHON_EXEC_PREFIX@ -PYTHON_INCLUDES = @PYTHON_INCLUDES@ -PYTHON_LIBS = @PYTHON_LIBS@ +PYTHON_EXTRA_LIBS = @PYTHON_EXTRA_LIBS@ +PYTHON_LDFLAGS = @PYTHON_LDFLAGS@ PYTHON_PLATFORM = @PYTHON_PLATFORM@ PYTHON_PREFIX = @PYTHON_PREFIX@ +PYTHON_SITE_PKG = @PYTHON_SITE_PKG@ PYTHON_VERSION = @PYTHON_VERSION@ RANLIB = @RANLIB@ SDL_CFLAGS = @SDL_CFLAGS@ @@ -336,6 +355,7 @@ abs_builddir = @abs_builddir@ abs_srcdir = @abs_srcdir@ abs_top_builddir = @abs_top_builddir@ abs_top_srcdir = @abs_top_srcdir@ +ac_ct_AR = @ac_ct_AR@ ac_ct_CC = @ac_ct_CC@ ac_ct_CXX = @ac_ct_CXX@ ac_ct_DUMPBIN = @ac_ct_DUMPBIN@ @@ -370,7 +390,6 @@ libdir = @libdir@ libexecdir = @libexecdir@ localedir = @localedir@ localstatedir = @localstatedir@ -lt_ECHO = @lt_ECHO@ mandir = @mandir@ mkdir_p = @mkdir_p@ oldincludedir = @oldincludedir@ @@ -394,16 +413,20 @@ target_vendor = @target_vendor@ top_build_prefix = @top_build_prefix@ top_builddir = @top_builddir@ top_srcdir = @top_srcdir@ -INCLUDES = -I.. @XML2_CFLAGS@ @FREETYPE_CFLAGS@ \ - @PANGOFT2_CFLAGS@ @PYTHON_INCLUDES@ @GL_CFLAGS@ @FFMPEG_CFLAGS@ \ +AM_CPPFLAGS = -I.. @XML2_CFLAGS@ @FREETYPE_CFLAGS@ \ + @PANGOFT2_CFLAGS@ @PYTHON_CPPFLAGS@ @GL_CFLAGS@ \ @DC1394_2_CFLAGS@ @LIBRSVG_CFLAGS@ @FONTCONFIG_CFLAGS@ \ $(MTDEV_CFLAGS) @APPLE_FALSE@APPLE_SOURCES = @APPLE_TRUE@APPLE_SOURCES = SDLMain.m AppleTrackpadInputDevice.cpp @APPLE_FALSE@APPLE_LINKFLAGS = -@APPLE_TRUE@APPLE_LINKFLAGS = -read_only_relocs suppress -F/System/Library/PrivateFrameworks -framework MultitouchSupport -@APPLE_FALSE@XGL_LIBS = -lXxf86vm -lX11 +@APPLE_TRUE@APPLE_LINKFLAGS = -read_only_relocs suppress -F/System/Library/PrivateFrameworks \ +@APPLE_TRUE@ -framework MultitouchSupport + +@APPLE_FALSE@@ENABLE_EGL_FALSE@@ENABLE_RPI_FALSE@XGL_LIBS = -lXxf86vm -lX11 +@APPLE_FALSE@@ENABLE_EGL_TRUE@@ENABLE_RPI_FALSE@XGL_LIBS = -lXxf86vm -lX11 -lGLESv2 -lEGL +@APPLE_FALSE@@ENABLE_RPI_TRUE@XGL_LIBS = -lXxf86vm -lX11 -lGLESv2 -lEGL @APPLE_TRUE@XGL_LIBS = @ENABLE_MTDEV_FALSE@MTDEV_SOURCES = @ENABLE_MTDEV_TRUE@MTDEV_SOURCES = LibMTDevInputDevice.cpp @@ -417,61 +440,71 @@ INCLUDES = -I.. @XML2_CFLAGS@ @FREETYPE_CFLAGS@ \ @HAVE_XI2_1_TRUE@XINPUT2_INCLUDES = XInputMTInputDevice.h GL_SOURCES = OGLSurface.cpp SDLDisplayEngine.cpp GL_INCLUDES = OGLSurface.h SDLDisplayEngine.h -ALL_GL_LIBS = @GL_LIBS@ @SDL_LIBS@ $(XGL_LIBS) -ALL_H = Player.h PluginManager.h IInputDevice.h VideoNode.h \ - DisplayEngine.h NodeRegistry.h Arg.h ArgBase.h ArgList.h \ - Node.h AreaNode.h DisplayParams.h NodeDefinition.h TextEngine.h \ +ALL_GL_LIBS = @GL_LIBS@ @SDL_LIBS@ $(XGL_LIBS) +ALL_H = Player.h PluginManager.h IInputDevice.h VideoNode.h ExportedObject.h \ + DisplayEngine.h TypeRegistry.h Arg.h ArgBase.h ArgList.h \ + Node.h AreaNode.h DisplayParams.h TypeDefinition.h TextEngine.h \ AVGNode.h DivNode.h CursorState.h MaterialInfo.h Canvas.h MainCanvas.h \ Image.h ImageNode.h Timeout.h WordsNode.h WrapPython.h OffscreenCanvas.h \ EventDispatcher.h CursorEvent.h MouseEvent.h \ - Event.h KeyEvent.h PanoImageNode.h TestHelper.h CanvasNode.h \ + Event.h KeyEvent.h TestHelper.h CanvasNode.h \ OffscreenCanvasNode.h MultitouchInputDevice.h \ RasterNode.h CameraNode.h TrackerInputDevice.h TrackerCalibrator.h \ TouchEvent.h Contact.h TouchStatus.h TrackerTouchStatus.h BoostPython.h \ - SoundNode.h \ + SoundNode.h FontStyle.h \ VectorNode.h FilledVectorNode.h LineNode.h PolyLineNode.h RectNode.h \ CurveNode.h PolygonNode.h CircleNode.h Shape.h MeshNode.h FXNode.h \ NullFXNode.h BlurFXNode.h ShadowFXNode.h ChromaKeyFXNode.h HueSatFXNode.h \ InvertFXNode.h TUIOInputDevice.h VideoWriter.h VideoWriterThread.h \ - SVG.h SVGElement.h \ + SVG.h SVGElement.h Publisher.h SubscriberInfo.h PublisherDefinition.h \ + PublisherDefinitionRegistry.h MessageID.h VersionInfo.h \ + PythonLogSink.h BitmapManager.h BitmapManagerThread.h IBitmapLoadedListener.h \ + BitmapManagerMsg.h \ $(MTDEV_INCLUDES) $(GL_INCLUDES) $(XINPUT2_INCLUDES) EXTRA_DIST = SDLMain.h noinst_LTLIBRARIES = libplayer.la testplayer_SOURCES = testplayer.cpp testplayer_LDADD = libplayer.la ../video/libvideo.la ../audio/libaudio.la \ + ../base/triangulate/libtriangulate.la \ ../imaging/libimaging.la ../graphics/libgraphics.la ../base/libbase.la \ ../lmfit/liblmfit.la ../oscpack/liboscpack.la \ - @XML2_LIBS@ -l@BOOST_THREAD_LIB@ @PTHREAD_LIBS@ @PANGOFT2_LIBS@ @LIBRSVG_LIBS@\ + @XML2_LIBS@ @BOOST_THREAD_LIBS@ @PTHREAD_CFLAGS@ @PTHREAD_LIBS@ @PANGOFT2_LIBS@ \ + @LIBRSVG_LIBS@ \ @DC1394_2_LIBS@ @GLU_LIBS@ $(ALL_GL_LIBS) $(XI2_1_LIBS) $(XI2_2_LIBS) \ - @LIBFFMPEG@ $(BOOST_PYTHON_LIBS) $(PYTHON_LIBS) @GDK_PIXBUF_LIBS@ \ + @LIBFFMPEG@ $(BOOST_PYTHON_LIBS) $(PYTHON_LDFLAGS) @GDK_PIXBUF_LIBS@ \ @FONTCONFIG_LIBS@ testplayer_LDFLAGS = $(APPLE_LINKFLAGS) -module -XCClinker testcalibrator_SOURCES = testcalibrator.cpp testcalibrator_LDADD = libplayer.la ../video/libvideo.la ../audio/libaudio.la \ + ../base/triangulate/libtriangulate.la \ ../imaging/libimaging.la ../graphics/libgraphics.la ../base/libbase.la \ ../lmfit/liblmfit.la ../oscpack/liboscpack.la \ - @XML2_LIBS@ -l@BOOST_THREAD_LIB@ @PTHREAD_LIBS@ @LIBRSVG_LIBS@ @GDK_PIXBUF_LIBS@ + @XML2_LIBS@ @BOOST_THREAD_LIBS@ @PTHREAD_CFLAGS@ @PTHREAD_LIBS@ @LIBRSVG_LIBS@ \ + @GDK_PIXBUF_LIBS@ -libplayer_la_LIBADD = $(BOOST_PYTHON_LIBS) $(PYTHON_LIBS) $(MTDEV_LIBS) +libplayer_la_LIBADD = $(BOOST_PYTHON_LIBS) $(PYTHON_LDFLAGS) $(MTDEV_LIBS) libplayer_la_SOURCES = $(GL_SOURCES) \ - Arg.cpp AreaNode.cpp RasterNode.cpp DivNode.cpp VideoNode.cpp \ - Player.cpp PluginManager.cpp NodeRegistry.cpp ArgBase.cpp ArgList.cpp \ + Arg.cpp AreaNode.cpp RasterNode.cpp DivNode.cpp VideoNode.cpp ExportedObject.cpp \ + Player.cpp PluginManager.cpp TypeRegistry.cpp ArgBase.cpp ArgList.cpp \ DisplayEngine.cpp Canvas.cpp CanvasNode.cpp OffscreenCanvasNode.cpp \ - MainCanvas.cpp Node.cpp MultitouchInputDevice.cpp \ - PanoImageNode.cpp WordsNode.cpp CameraNode.cpp NodeDefinition.cpp TextEngine.cpp \ + MainCanvas.cpp Node.cpp MultitouchInputDevice.cpp WrapPython.cpp \ + WordsNode.cpp CameraNode.cpp TypeDefinition.cpp TextEngine.cpp \ Timeout.cpp Event.cpp DisplayParams.cpp CursorState.cpp MaterialInfo.cpp \ Image.cpp ImageNode.cpp EventDispatcher.cpp KeyEvent.cpp CursorEvent.cpp \ MouseEvent.cpp TouchEvent.cpp AVGNode.cpp TestHelper.cpp \ TrackerInputDevice.cpp TrackerTouchStatus.cpp TrackerCalibrator.cpp \ - SoundNode.cpp \ + SoundNode.cpp FontStyle.cpp \ VectorNode.cpp FilledVectorNode.cpp LineNode.cpp PolyLineNode.cpp \ RectNode.cpp CurveNode.cpp PolygonNode.cpp CircleNode.cpp Shape.cpp MeshNode.cpp \ Contact.cpp TouchStatus.cpp OffscreenCanvas.cpp FXNode.cpp TUIOInputDevice.cpp \ NullFXNode.cpp BlurFXNode.cpp ShadowFXNode.cpp ChromaKeyFXNode.cpp \ InvertFXNode.cpp HueSatFXNode.cpp VideoWriter.cpp VideoWriterThread.cpp \ - SVG.cpp SVGElement.cpp \ + SVG.cpp SVGElement.cpp Publisher.cpp SubscriberInfo.cpp PublisherDefinition.cpp \ + PublisherDefinitionRegistry.cpp MessageID.cpp VersionInfo.cpp \ + PythonLogSink.cpp BitmapManager.cpp BitmapManagerThread.cpp \ + BitmapManagerMsg.cpp \ $(MTDEV_SOURCES) $(XINPUT2_SOURCES) $(APPLE_SOURCES) $(ALL_H) libplayer_a_CXXFLAGS = -DPREFIXDIR=\"$(prefix)\" @@ -518,7 +551,7 @@ clean-noinstLTLIBRARIES: echo "rm -f \"$${dir}/so_locations\""; \ rm -f "$${dir}/so_locations"; \ done -libplayer.la: $(libplayer_la_OBJECTS) $(libplayer_la_DEPENDENCIES) +libplayer.la: $(libplayer_la_OBJECTS) $(libplayer_la_DEPENDENCIES) $(EXTRA_libplayer_la_DEPENDENCIES) $(AM_V_CXXLD)$(CXXLINK) $(libplayer_la_OBJECTS) $(libplayer_la_LIBADD) $(LIBS) clean-noinstPROGRAMS: @@ -529,10 +562,10 @@ clean-noinstPROGRAMS: list=`for p in $$list; do echo "$$p"; done | sed 's/$(EXEEXT)$$//'`; \ echo " rm -f" $$list; \ rm -f $$list -testcalibrator$(EXEEXT): $(testcalibrator_OBJECTS) $(testcalibrator_DEPENDENCIES) +testcalibrator$(EXEEXT): $(testcalibrator_OBJECTS) $(testcalibrator_DEPENDENCIES) $(EXTRA_testcalibrator_DEPENDENCIES) @rm -f testcalibrator$(EXEEXT) $(AM_V_CXXLD)$(CXXLINK) $(testcalibrator_OBJECTS) $(testcalibrator_LDADD) $(LIBS) -testplayer$(EXEEXT): $(testplayer_OBJECTS) $(testplayer_DEPENDENCIES) +testplayer$(EXEEXT): $(testplayer_OBJECTS) $(testplayer_DEPENDENCIES) $(EXTRA_testplayer_DEPENDENCIES) @rm -f testplayer$(EXEEXT) $(AM_V_CXXLD)$(testplayer_LINK) $(testplayer_OBJECTS) $(testplayer_LDADD) $(LIBS) @@ -548,6 +581,9 @@ distclean-compile: @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/Arg.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ArgBase.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ArgList.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/BitmapManager.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/BitmapManagerMsg.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/BitmapManagerThread.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/BlurFXNode.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/CameraNode.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/Canvas.Plo@am__quote@ @@ -563,8 +599,10 @@ distclean-compile: @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/DivNode.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/Event.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/EventDispatcher.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ExportedObject.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/FXNode.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/FilledVectorNode.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/FontStyle.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/HueSatFXNode.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/Image.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ImageNode.Plo@am__quote@ @@ -575,20 +613,22 @@ distclean-compile: @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/MainCanvas.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/MaterialInfo.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/MeshNode.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/MessageID.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/MouseEvent.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/MultitouchInputDevice.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/Node.Plo@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/NodeDefinition.Plo@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/NodeRegistry.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/NullFXNode.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/OGLSurface.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/OffscreenCanvas.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/OffscreenCanvasNode.Plo@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/PanoImageNode.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/Player.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/PluginManager.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/PolyLineNode.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/PolygonNode.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/Publisher.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/PublisherDefinition.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/PublisherDefinitionRegistry.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/PythonLogSink.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/RasterNode.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/RectNode.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/SDLDisplayEngine.Plo@am__quote@ @@ -598,6 +638,7 @@ distclean-compile: @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ShadowFXNode.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/Shape.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/SoundNode.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/SubscriberInfo.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/TUIOInputDevice.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/TestHelper.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/TextEngine.Plo@am__quote@ @@ -607,11 +648,15 @@ distclean-compile: @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/TrackerCalibrator.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/TrackerInputDevice.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/TrackerTouchStatus.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/TypeDefinition.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/TypeRegistry.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/VectorNode.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/VersionInfo.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/VideoNode.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/VideoWriter.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/VideoWriterThread.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/WordsNode.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/WrapPython.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/XInputMTInputDevice.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/testcalibrator.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/testplayer.Po@am__quote@ @@ -619,50 +664,44 @@ distclean-compile: .cpp.o: @am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXXCOMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $< @am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po -@am__fastdepCXX_FALSE@ $(AM_V_CXX) @AM_BACKSLASH@ -@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ -@am__fastdepCXX_FALSE@ $(CXXCOMPILE) -c -o $@ $< +@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXXCOMPILE) -c -o $@ $< .cpp.obj: @am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXXCOMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ `$(CYGPATH_W) '$<'` @am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po -@am__fastdepCXX_FALSE@ $(AM_V_CXX) @AM_BACKSLASH@ -@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ -@am__fastdepCXX_FALSE@ $(CXXCOMPILE) -c -o $@ `$(CYGPATH_W) '$<'` +@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXXCOMPILE) -c -o $@ `$(CYGPATH_W) '$<'` .cpp.lo: @am__fastdepCXX_TRUE@ $(AM_V_CXX)$(LTCXXCOMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $< @am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Plo -@am__fastdepCXX_FALSE@ $(AM_V_CXX) @AM_BACKSLASH@ -@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='$<' object='$@' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='$<' object='$@' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ -@am__fastdepCXX_FALSE@ $(LTCXXCOMPILE) -c -o $@ $< +@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(LTCXXCOMPILE) -c -o $@ $< .m.o: @am__fastdepOBJC_TRUE@ $(AM_V_OBJC)$(OBJCCOMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $< @am__fastdepOBJC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po -@am__fastdepOBJC_FALSE@ $(AM_V_OBJC) @AM_BACKSLASH@ -@AMDEP_TRUE@@am__fastdepOBJC_FALSE@ source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepOBJC_FALSE@ $(AM_V_OBJC)source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepOBJC_FALSE@ DEPDIR=$(DEPDIR) $(OBJCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ -@am__fastdepOBJC_FALSE@ $(OBJCCOMPILE) -c -o $@ $< +@am__fastdepOBJC_FALSE@ $(AM_V_OBJC@am__nodep@)$(OBJCCOMPILE) -c -o $@ $< .m.obj: @am__fastdepOBJC_TRUE@ $(AM_V_OBJC)$(OBJCCOMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ `$(CYGPATH_W) '$<'` @am__fastdepOBJC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po -@am__fastdepOBJC_FALSE@ $(AM_V_OBJC) @AM_BACKSLASH@ -@AMDEP_TRUE@@am__fastdepOBJC_FALSE@ source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepOBJC_FALSE@ $(AM_V_OBJC)source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepOBJC_FALSE@ DEPDIR=$(DEPDIR) $(OBJCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ -@am__fastdepOBJC_FALSE@ $(OBJCCOMPILE) -c -o $@ `$(CYGPATH_W) '$<'` +@am__fastdepOBJC_FALSE@ $(AM_V_OBJC@am__nodep@)$(OBJCCOMPILE) -c -o $@ `$(CYGPATH_W) '$<'` .m.lo: @am__fastdepOBJC_TRUE@ $(AM_V_OBJC)$(LTOBJCCOMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $< @am__fastdepOBJC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Plo -@am__fastdepOBJC_FALSE@ $(AM_V_OBJC) @AM_BACKSLASH@ -@AMDEP_TRUE@@am__fastdepOBJC_FALSE@ source='$<' object='$@' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepOBJC_FALSE@ $(AM_V_OBJC)source='$<' object='$@' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepOBJC_FALSE@ DEPDIR=$(DEPDIR) $(OBJCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ -@am__fastdepOBJC_FALSE@ $(LTOBJCCOMPILE) -c -o $@ $< +@am__fastdepOBJC_FALSE@ $(AM_V_OBJC@am__nodep@)$(LTOBJCCOMPILE) -c -o $@ $< mostlyclean-libtool: -rm -f *.lo @@ -803,14 +842,15 @@ check-TESTS: $(TESTS) fi; \ dashes=`echo "$$dashes" | sed s/./=/g`; \ if test "$$failed" -eq 0; then \ - echo "$$grn$$dashes"; \ + col="$$grn"; \ else \ - echo "$$red$$dashes"; \ + col="$$red"; \ fi; \ - echo "$$banner"; \ - test -z "$$skipped" || echo "$$skipped"; \ - test -z "$$report" || echo "$$report"; \ - echo "$$dashes$$std"; \ + echo "$${col}$$dashes$${std}"; \ + echo "$${col}$$banner$${std}"; \ + test -z "$$skipped" || echo "$${col}$$skipped$${std}"; \ + test -z "$$report" || echo "$${col}$$report$${std}"; \ + echo "$${col}$$dashes$${std}"; \ test "$$failed" -eq 0; \ else :; fi @@ -859,10 +899,15 @@ install-am: all-am installcheck: installcheck-am install-strip: - $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ - install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ - `test -z '$(STRIP)' || \ - echo "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'"` install + if test -z '$(STRIP)'; then \ + $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ + install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ + install; \ + else \ + $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ + install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ + "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'" install; \ + fi mostlyclean-generic: clean-generic: diff --git a/src/player/MaterialInfo.cpp b/src/player/MaterialInfo.cpp index f77d89e..2b25b48 100644 --- a/src/player/MaterialInfo.cpp +++ b/src/player/MaterialInfo.cpp @@ -1,6 +1,6 @@ // // libavg - Media Playback Engine. -// Copyright (C) 2003-2011 Ulrich von Zadow +// Copyright (C) 2003-2014 Ulrich von Zadow // // This library is free software; you can redistribute it and/or // modify it under the terms of the GNU Lesser General Public diff --git a/src/player/MaterialInfo.h b/src/player/MaterialInfo.h index 871e48f..7f1d987 100644 --- a/src/player/MaterialInfo.h +++ b/src/player/MaterialInfo.h @@ -1,6 +1,6 @@ // // libavg - Media Playback Engine. -// Copyright (C) 2003-2011 Ulrich von Zadow +// Copyright (C) 2003-2014 Ulrich von Zadow // // This library is free software; you can redistribute it and/or // modify it under the terms of the GNU Lesser General Public @@ -24,8 +24,6 @@ #include "../api.h" -#include "../base/Point.h" - namespace avg { class AVG_API MaterialInfo { diff --git a/src/player/MeshNode.cpp b/src/player/MeshNode.cpp index 363e00a..09e577f 100644 --- a/src/player/MeshNode.cpp +++ b/src/player/MeshNode.cpp @@ -1,6 +1,6 @@ // // libavg - Media Playback Engine. -// Copyright (C) 2003-2011 Ulrich von Zadow +// Copyright (C) 2003-2014 Ulrich von Zadow // // This library is free software; you can redistribute it and/or // modify it under the terms of the GNU Lesser General Public @@ -21,11 +21,10 @@ #include "MeshNode.h" -#include "../wrapper/WrapHelper.h" #include "../base/Logger.h" #include "../base/Exception.h" -#include "NodeDefinition.h" +#include "TypeDefinition.h" #include "VectorNode.h" #include <cstdlib> @@ -33,25 +32,27 @@ #include <iostream> using namespace std; -using namespace boost::python; namespace avg { -NodeDefinition MeshNode::createDefinition() +void MeshNode::registerType() { - vector<DPoint> vVert; - vector<DPoint> vTex; - vector<IntTriple> vTriangle; + vector<glm::vec2> vVert; + vector<glm::vec2> vTex; + vector<glm::ivec3> vTriangle; - return NodeDefinition("mesh", (NodeBuilder)MeshNode::buildNode<MeshNode>) - .extendDefinition(VectorNode::createDefinition()) - .addArg(Arg<vector<DPoint> >("vertexcoords", vVert, false, + TypeDefinition def = TypeDefinition("mesh", "vectornode", + ExportedObject::buildObject<MeshNode>) + .addArg(Arg<vector<glm::vec2> >("vertexcoords", vVert, false, offsetof(MeshNode, m_VertexCoords))) - .addArg(Arg<vector<DPoint> >("texcoords", vTex, false, + .addArg(Arg<vector<glm::vec2> >("texcoords", vTex, false, offsetof(MeshNode, m_TexCoords))) - .addArg(Arg<vector<IntTriple> >("triangles", vTriangle, false, + .addArg(Arg<vector<glm::ivec3> >("triangles", vTriangle, false, offsetof(MeshNode, m_Triangles))) + .addArg(Arg<bool>("backfacecull", false, false, + offsetof(MeshNode, m_bBackfaceCull))) ; + TypeRegistry::get()->registerType(def); } MeshNode::MeshNode(const ArgList& args) @@ -65,7 +66,7 @@ MeshNode::~MeshNode() { } -void MeshNode::isValid(const vector<DPoint>& coords) +void MeshNode::isValid(const vector<glm::vec2>& coords) { if (coords.size() != m_VertexCoords.size()) { throw(Exception(AVG_ERR_OUT_OF_RANGE, @@ -73,43 +74,41 @@ void MeshNode::isValid(const vector<DPoint>& coords) } } -const vector<DPoint>& MeshNode::getVertexCoords() const +const vector<glm::vec2>& MeshNode::getVertexCoords() const { return m_VertexCoords; } -void MeshNode::setVertexCoords(const vector<DPoint>& coords) +void MeshNode::setVertexCoords(const vector<glm::vec2>& coords) { isValid(coords); m_VertexCoords = coords; setDrawNeeded(); } -const vector<DPoint>& MeshNode::getTexCoords() const +const vector<glm::vec2>& MeshNode::getTexCoords() const { return m_TexCoords; } -void MeshNode::setTexCoords(const vector<DPoint>& coords) +void MeshNode::setTexCoords(const vector<glm::vec2>& coords) { isValid(coords); m_TexCoords = coords; setDrawNeeded(); } -const vector<IntTriple>& MeshNode::getTriangles() const +const vector<glm::ivec3>& MeshNode::getTriangles() const { return m_Triangles; } -void MeshNode::setTriangles(const vector<IntTriple>& triangles) +void MeshNode::setTriangles(const vector<glm::ivec3>& triangles) { for (unsigned int i = 0; i < triangles.size(); i++) { - if (static_cast<unsigned int>(triangles[i].x) < 0 || - static_cast<unsigned int>(triangles[i].y) < 0 || - static_cast<unsigned int>(triangles[i].z) < 0) + if (triangles[i].x < 0 || triangles[i].y < 0 || triangles[i].z < 0) { throw(Exception(AVG_ERR_OUT_OF_RANGE, "Triangle Index Out of Range < 0")); @@ -127,16 +126,39 @@ void MeshNode::setTriangles(const vector<IntTriple>& triangles) setDrawNeeded(); } -void MeshNode::calcVertexes(VertexArrayPtr& pVertexArray, Pixel32 color) +bool MeshNode::getBackfaceCull() const +{ + return m_bBackfaceCull; +} + +void MeshNode::setBackfaceCull(const bool bBackfaceCull) +{ + m_bBackfaceCull = bBackfaceCull; +} + +void MeshNode::calcVertexes(const VertexDataPtr& pVertexData, Pixel32 color) { for (unsigned int i = 0; i < m_VertexCoords.size(); i++) { - pVertexArray->appendPos(m_VertexCoords[i],m_TexCoords[i], color); + pVertexData->appendPos(m_VertexCoords[i],m_TexCoords[i], color); } for (unsigned int i = 0; i < m_Triangles.size(); i++) { - pVertexArray->appendTriIndexes(m_Triangles[i].x, m_Triangles[i].y, + pVertexData->appendTriIndexes(m_Triangles[i].x, m_Triangles[i].y, m_Triangles[i].z); } } +void MeshNode::render() +{ + if (m_bBackfaceCull) { + glEnable(GL_CULL_FACE); + } + + VectorNode::render(); + + if (m_bBackfaceCull) { + glDisable(GL_CULL_FACE); + } +} + } diff --git a/src/player/MeshNode.h b/src/player/MeshNode.h index 5f8f40b..e921c12 100644 --- a/src/player/MeshNode.h +++ b/src/player/MeshNode.h @@ -1,6 +1,6 @@ // // libavg - Media Playback Engine. -// Copyright (C) 2003-2011 Ulrich von Zadow +// Copyright (C) 2003-2014 Ulrich von Zadow // // This library is free software; you can redistribute it and/or // modify it under the terms of the GNU Lesser General Public @@ -25,8 +25,10 @@ #include "../api.h" #include "VectorNode.h" + +#include "../base/GLMHelper.h" #include "../graphics/Pixel32.h" -#include "../base/Triple.h" + #include <vector> namespace avg { @@ -34,28 +36,35 @@ namespace avg { class AVG_API MeshNode : public VectorNode { public: - static NodeDefinition createDefinition(); + static void registerType(); MeshNode(const ArgList& args); virtual ~MeshNode(); - void isValid(const std::vector<DPoint>& coords); + void isValid(const std::vector<glm::vec2>& coords); - const std::vector<DPoint>& getVertexCoords() const; - void setVertexCoords(const std::vector<DPoint>& coords); + const std::vector<glm::vec2>& getVertexCoords() const; + void setVertexCoords(const std::vector<glm::vec2>& coords); - const std::vector<DPoint>& getTexCoords() const; - void setTexCoords(const std::vector<DPoint>& coords); + const std::vector<glm::vec2>& getTexCoords() const; + void setTexCoords(const std::vector<glm::vec2>& coords); - const std::vector<IntTriple>& getTriangles() const; - void setTriangles(const std::vector<IntTriple>& pts); + const std::vector<glm::ivec3>& getTriangles() const; + void setTriangles(const std::vector<glm::ivec3>& pts); + + bool getBackfaceCull() const; + void setBackfaceCull(const bool bBackfaceCull); - virtual void calcVertexes(VertexArrayPtr& pVertexArray, Pixel32 color); + virtual void calcVertexes(const VertexDataPtr& pVertexData, Pixel32 color); + + virtual void render(); private: - std::vector<DPoint> m_TexCoords; - std::vector<DPoint> m_VertexCoords; - std::vector<IntTriple> m_Triangles; + std::vector<glm::vec2> m_TexCoords; + std::vector<glm::vec2> m_VertexCoords; + std::vector<glm::ivec3> m_Triangles; + + bool m_bBackfaceCull; }; } #endif diff --git a/src/player/MessageID.cpp b/src/player/MessageID.cpp new file mode 100644 index 0000000..6617e0e --- /dev/null +++ b/src/player/MessageID.cpp @@ -0,0 +1,62 @@ +// +// libavg - Media Playback Engine. +// Copyright (C) 2003-2014 Ulrich von Zadow +// +// This library is free software; you can redistribute it and/or +// modify it under the terms of the GNU Lesser General Public +// License as published by the Free Software Foundation; either +// version 2 of the License, or (at your option) any later version. +// +// This library 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 +// Lesser General Public License for more details. +// +// You should have received a copy of the GNU Lesser General Public +// License along with this library; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +// +// Current versions can be found at www.libavg.de +// + +#include "MessageID.h" + +#include "../base/StringHelper.h" + +using namespace std; + +namespace avg { + +MessageID::MessageID(const string& sName, int id) + : m_sName(sName), + m_ID(id) +{ +} + +bool MessageID::operator < (const MessageID& other) const +{ + return m_ID < other.m_ID; +} + +bool MessageID::operator == (const MessageID& other) const +{ + return m_ID == other.m_ID; +} + +std::string MessageID::getRepr() +{ + if (m_sName != "") { + return m_sName; + } else { + return toString(m_ID); + } +} + +std::ostream& operator <<(ostream& os, const MessageID& id) +{ + os << "(" << id.m_sName << ", " << id.m_ID << ")"; + return os; +} + +} + diff --git a/src/player/MessageID.h b/src/player/MessageID.h new file mode 100644 index 0000000..f7ec6d6 --- /dev/null +++ b/src/player/MessageID.h @@ -0,0 +1,48 @@ +// +// libavg - Media Playback Engine. +// Copyright (C) 2003-2014 Ulrich von Zadow +// +// This library is free software; you can redistribute it and/or +// modify it under the terms of the GNU Lesser General Public +// License as published by the Free Software Foundation; either +// version 2 of the License, or (at your option) any later version. +// +// This library 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 +// Lesser General Public License for more details. +// +// You should have received a copy of the GNU Lesser General Public +// License along with this library; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +// +// Current versions can be found at www.libavg.de +// + +#ifndef _MessageID_H_ +#define _MessageID_H_ + +#include "../api.h" + +#include <string> +#include <iostream> + +namespace avg { + +struct MessageID { + MessageID(const std::string& sName, int id); + + bool operator < (const MessageID& other) const; + bool operator == (const MessageID& other) const; + + std::string getRepr(); + + std::string m_sName; + int m_ID; +}; + +std::ostream& operator <<(std::ostream& os, const MessageID& id); + +} + +#endif diff --git a/src/player/MouseEvent.cpp b/src/player/MouseEvent.cpp index 39acc83..c56dd8c 100644 --- a/src/player/MouseEvent.cpp +++ b/src/player/MouseEvent.cpp @@ -1,6 +1,6 @@ // // libavg - Media Playback Engine. -// Copyright (C) 2003-2011 Ulrich von Zadow +// Copyright (C) 2003-2014 Ulrich von Zadow // // This library is free software; you can redistribute it and/or // modify it under the terms of the GNU Lesser General Public @@ -33,7 +33,7 @@ namespace avg { MouseEvent::MouseEvent(Event::Type eventType, bool leftButtonState, bool middleButtonState, bool rightButtonState, - const IntPoint& pos, int button, const DPoint& speed, int when) + const IntPoint& pos, int button, const glm::vec2& speed, int when) : CursorEvent(MOUSECURSORID, eventType, pos, MOUSE, when) { m_LeftButtonState = leftButtonState; @@ -75,7 +75,7 @@ bool MouseEvent::isAnyButtonPressed() const void MouseEvent::trace() { CursorEvent::trace(); - AVG_TRACE(Logger::EVENTS2, "pos: " << getPos() + AVG_TRACE(Logger::category::EVENTS, Logger::severity::DEBUG, "pos: " << getPos() << ", button: " << m_Button); } diff --git a/src/player/MouseEvent.h b/src/player/MouseEvent.h index 0c8e3ab..fb67dde 100644 --- a/src/player/MouseEvent.h +++ b/src/player/MouseEvent.h @@ -1,6 +1,6 @@ // // libavg - Media Playback Engine. -// Copyright (C) 2003-2011 Ulrich von Zadow +// Copyright (C) 2003-2014 Ulrich von Zadow // // This library is free software; you can redistribute it and/or // modify it under the terms of the GNU Lesser General Public @@ -32,7 +32,7 @@ class AVG_API MouseEvent : public CursorEvent { public: MouseEvent(Event::Type eventType, bool leftButtonState, bool middleButtonState, bool rightButtonState, - const IntPoint& pos, int button, const DPoint& speed=DPoint(0,0), + const IntPoint& pos, int button, const glm::vec2& speed=glm::vec2(0,0), int when=-1); virtual ~MouseEvent(); diff --git a/src/player/MultitouchInputDevice.cpp b/src/player/MultitouchInputDevice.cpp index b89aaef..507f3fb 100644 --- a/src/player/MultitouchInputDevice.cpp +++ b/src/player/MultitouchInputDevice.cpp @@ -1,6 +1,6 @@ // // libavg - Media Playback Engine. -// Copyright (C) 2003-2011 Ulrich von Zadow +// Copyright (C) 2003-2014 Ulrich von Zadow // // This library is free software; you can redistribute it and/or // modify it under the terms of the GNU Lesser General Public @@ -18,8 +18,6 @@ // // Current versions can be found at www.libavg.de // -// Original author of this file is igor@c-base.org -// #include "MultitouchInputDevice.h" #include "TouchEvent.h" @@ -38,6 +36,11 @@ namespace avg { MultitouchInputDevice::MultitouchInputDevice() : IInputDevice(EXTRACT_INPUTDEVICE_CLASSNAME(MultitouchInputDevice)) { + m_TouchArea = ConfigMgr::get()->getSizeOption("touch", "area"); + if (m_TouchArea.x == 0) { + m_TouchArea = Player::get()->getScreenResolution(); + } + m_TouchOffset = ConfigMgr::get()->getSizeOption("touch", "offset"); } MultitouchInputDevice::~MultitouchInputDevice() @@ -46,23 +49,22 @@ MultitouchInputDevice::~MultitouchInputDevice() void MultitouchInputDevice::start() { - m_WindowSize = Player::get()->getRootNode()->getSize(); m_pMutex = MutexPtr(new boost::mutex); } vector<EventPtr> MultitouchInputDevice::pollEvents() { - boost::mutex::scoped_lock lock(*m_pMutex); + lock_guard lock(*m_pMutex); vector<EventPtr> events; vector<TouchStatusPtr>::iterator it; // cerr << "--------poll---------" << endl; for (it = m_Touches.begin(); it != m_Touches.end(); ) { -// cerr << it->first << " "; +// cerr << (*it)->getID() << " "; CursorEventPtr pEvent = (*it)->pollEvent(); if (pEvent) { events.push_back(pEvent); - if (pEvent->getType() == Event::CURSORUP) { + if (pEvent->getType() == Event::CURSOR_UP) { it = m_Touches.erase(it); } else { ++it; @@ -75,11 +77,6 @@ vector<EventPtr> MultitouchInputDevice::pollEvents() return events; } -const DPoint& MultitouchInputDevice::getWindowSize() const -{ - return m_WindowSize; -} - int MultitouchInputDevice::getNumTouches() const { return m_TouchIDMap.size(); @@ -120,6 +117,17 @@ void MultitouchInputDevice::getDeadIDs(const set<int>& liveIDs, set<int>& deadID } } +glm::vec2 MultitouchInputDevice::getTouchArea() const +{ + return m_TouchArea; +} + +IntPoint MultitouchInputDevice::getScreenPos(const glm::vec2& pos) const +{ + return IntPoint(int(pos.x * m_TouchArea.x + m_TouchOffset.x + 0.5), + int(pos.y * m_TouchArea.y + m_TouchOffset.y) + 0.5); +} + boost::mutex& MultitouchInputDevice::getMutex() { return *m_pMutex; diff --git a/src/player/MultitouchInputDevice.h b/src/player/MultitouchInputDevice.h index 71aa2c5..7ccbfe5 100644 --- a/src/player/MultitouchInputDevice.h +++ b/src/player/MultitouchInputDevice.h @@ -1,6 +1,6 @@ // // libavg - Media Playback Engine. -// Copyright (C) 2003-2011 Ulrich von Zadow +// Copyright (C) 2003-2014 Ulrich von Zadow // // This library is free software; you can redistribute it and/or // modify it under the terms of the GNU Lesser General Public @@ -25,7 +25,8 @@ #include "../api.h" #include "IInputDevice.h" -#include "../base/Point.h" +#include "../base/GLMHelper.h" +#include "../base/ConfigMgr.h" #include <boost/thread.hpp> #include <map> @@ -48,11 +49,10 @@ public: MultitouchInputDevice(); virtual ~MultitouchInputDevice() = 0; virtual void start(); - + std::vector<EventPtr> pollEvents(); protected: - const DPoint& getWindowSize() const; int getNumTouches() const; // Note that the id used here is not the libavg cursor id but a touch-driver-specific // id handed up from the driver level. @@ -60,13 +60,16 @@ protected: void addTouchStatus(int id, TouchEventPtr pInitialEvent); void removeTouchStatus(int id); void getDeadIDs(const std::set<int>& liveIDs, std::set<int>& deadIDs); + glm::vec2 getTouchArea() const; + IntPoint getScreenPos(const glm::vec2& pos) const; boost::mutex& getMutex(); private: std::map<int, TouchStatusPtr> m_TouchIDMap; std::vector<TouchStatusPtr> m_Touches; - DPoint m_WindowSize; MutexPtr m_pMutex; + glm::vec2 m_TouchArea; + glm::vec2 m_TouchOffset; }; typedef boost::shared_ptr<MultitouchInputDevice> MultitouchInputDevicePtr; diff --git a/src/player/Node.cpp b/src/player/Node.cpp index eeedc5f..7c3f331 100644 --- a/src/player/Node.cpp +++ b/src/player/Node.cpp @@ -1,6 +1,6 @@ // // libavg - Media Playback Engine. -// Copyright (C) 2003-2011 Ulrich von Zadow +// Copyright (C) 2003-2014 Ulrich von Zadow // // This library is free software; you can redistribute it and/or // modify it under the terms of the GNU Lesser General Public @@ -21,12 +21,13 @@ #include "Node.h" -#include "NodeDefinition.h" +#include "TypeDefinition.h" #include "Arg.h" #include "Canvas.h" #include "DivNode.h" #include "Player.h" #include "CursorEvent.h" +#include "PublisherDefinition.h" #include "../base/Exception.h" #include "../base/Logger.h" @@ -37,27 +38,39 @@ #include <string> using namespace std; +using namespace boost; namespace avg { -NodeDefinition Node::createDefinition() -{ - return NodeDefinition("node") +void Node::registerType() +{ + PublisherDefinitionPtr pPubDef = PublisherDefinition::create("Node"); + pPubDef->addMessage("CURSOR_DOWN"); + pPubDef->addMessage("CURSOR_MOTION"); + pPubDef->addMessage("CURSOR_UP"); + pPubDef->addMessage("CURSOR_OVER"); + pPubDef->addMessage("CURSOR_OUT"); + pPubDef->addMessage("HOVER_DOWN"); + pPubDef->addMessage("HOVER_MOTION"); + pPubDef->addMessage("HOVER_UP"); + pPubDef->addMessage("HOVER_OVER"); + pPubDef->addMessage("HOVER_OUT"); + pPubDef->addMessage("END_OF_FILE"); + pPubDef->addMessage("SIZE_CHANGED"); + + TypeDefinition def = TypeDefinition("node") .addArg(Arg<string>("id", "", false, offsetof(Node, m_ID))) - .addArg(Arg<string>("oncursormove", "")) - .addArg(Arg<string>("oncursorup", "")) - .addArg(Arg<string>("oncursordown", "")) - .addArg(Arg<string>("oncursorover", "")) - .addArg(Arg<string>("oncursorout", "")) .addArg(Arg<bool>("active", true, false, offsetof(Node, m_bActive))) .addArg(Arg<bool>("sensitive", true, false, offsetof(Node, m_bSensitive))) - .addArg(Arg<double>("opacity", 1.0, false, offsetof(Node, m_Opacity))); + .addArg(Arg<float>("opacity", 1.0, false, offsetof(Node, m_Opacity))); + TypeRegistry::get()->registerType(def); } -Node::Node() - : m_pCanvas(), +Node::Node(const std::string& sPublisherName) + : Publisher(sPublisherName), + m_pParent(0), + m_pCanvas(), m_State(NS_UNCONNECTED) - { ObjectCounter::get()->incRef(&typeid(*this)); } @@ -68,30 +81,27 @@ Node::~Node() ObjectCounter::get()->decRef(&typeid(*this)); } -void Node::setArgs(const ArgList& args) -{ - addArgEventHandlers(Event::CURSORMOTION, args.getArgVal<string> ("oncursormove")); - addArgEventHandlers(Event::CURSORUP, args.getArgVal<string> ("oncursorup")); - addArgEventHandlers(Event::CURSORDOWN, args.getArgVal<string> ("oncursordown")); - addArgEventHandlers(Event::CURSOROVER, args.getArgVal<string> ("oncursorover")); - addArgEventHandlers(Event::CURSOROUT, args.getArgVal<string> ("oncursorout")); -} - -void Node::setTypeInfo(const NodeDefinition * pDefinition) +void Node::registerInstance(PyObject* pSelf, const DivNodePtr& pParent) { - m_pDefinition = pDefinition; + ExportedObject::registerInstance(pSelf); + if (pParent) { + pParent->appendChild(getSharedThis()); + } } -void Node::checkSetParentError(DivNodeWeakPtr pParent) +void Node::checkSetParentError(DivNode* pParent) { - if (getParent() && !!(pParent.lock())) { + if (getParent() && pParent != 0) { throw(Exception(AVG_ERR_UNSUPPORTED, string("Can't change parent of node (") + getID() + ").")); } + if (getSharedThis() == NodePtr()) { + throw(Exception(AVG_ERR_UNSUPPORTED, + "Node not registered. Please use Node.registerInstance() when deriving from libavg Nodes in python.")); + } } -void Node::setParent(DivNodeWeakPtr pParent, NodeState parentState, - CanvasPtr pCanvas) +void Node::setParent(DivNode* pParent, NodeState parentState, CanvasPtr pCanvas) { AVG_ASSERT(getState() == NS_UNCONNECTED); checkSetParentError(pParent); @@ -103,22 +113,23 @@ void Node::setParent(DivNodeWeakPtr pParent, NodeState parentState, void Node::removeParent() { - m_pParent = DivNodePtr(); + m_pParent = 0; } DivNodePtr Node::getParent() const { - if (m_pParent.expired()) { + if (m_pParent == 0) { return DivNodePtr(); } else { - return m_pParent.lock(); + NodePtr pParent = m_pParent->getSharedThis(); + return boost::dynamic_pointer_cast<DivNode>(pParent); } } -vector<NodeWeakPtr> Node::getParentChain() +vector<NodePtr> Node::getParentChain() { - vector<NodeWeakPtr> pNodes; - boost::shared_ptr<Node> pCurNode = shared_from_this(); + vector<NodePtr> pNodes; + NodePtr pCurNode = getSharedThis(); while (pCurNode) { pNodes.push_back(pCurNode); pCurNode = pCurNode->getParent(); @@ -152,7 +163,7 @@ void Node::unlink(bool bKill) { DivNodePtr pParent = getParent(); if (pParent != DivNodePtr()) { - pParent->removeChild(shared_from_this(), bKill); + pParent->removeChild(getSharedThis(), bKill); } } @@ -170,12 +181,12 @@ void Node::setID(const std::string& id) m_ID = id; } -double Node::getOpacity() const +float Node::getOpacity() const { return m_Opacity; } -void Node::setOpacity(double opacity) +void Node::setOpacity(float opacity) { m_Opacity = opacity; if (m_Opacity < 0.0) { @@ -219,7 +230,7 @@ void Node::releaseMouseEventCapture() void Node::setEventCapture(int cursorID) { - Player::get()->setEventCapture(shared_from_this(), cursorID); + Player::get()->setEventCapture(getSharedThis(), cursorID); } void Node::releaseEventCapture(int cursorID) @@ -229,6 +240,7 @@ void Node::releaseEventCapture(int cursorID) void Node::setEventHandler(Event::Type type, int sources, PyObject * pFunc) { + avgDeprecationWarning("1.7", "Node.setEventHandler()", "Node.subscribe()"); for (int source = 1; source <= Event::NONE; source *= 2) { if (source & sources) { EventID id(type, (Event::Source)source); @@ -246,6 +258,7 @@ void Node::setEventHandler(Event::Type type, int sources, PyObject * pFunc) void Node::connectEventHandler(Event::Type type, int sources, PyObject * pObj, PyObject * pFunc) { + avgDeprecationWarning("1.8", "Node.connectEventHandler()", "Node.subscribe()"); for (int source = 1; source <= Event::NONE; source *= 2) { if (source & sources) { EventID id(type, (Event::Source)source); @@ -258,6 +271,7 @@ void Node::connectEventHandler(Event::Type type, int sources, void Node::disconnectEventHandler(PyObject * pObj, PyObject * pFunc) { + avgDeprecationWarning("1.8", "Node.disconnectEventHandler()", "Node.unsubscribe()"); int numDisconnected = 0; EventHandlerMap::iterator it; for (it = m_EventHandlerMap.begin(); it != m_EventHandlerMap.end();) { @@ -294,62 +308,59 @@ bool Node::reactsToMouseEvents() return m_bActive && m_bSensitive; } -DPoint Node::getRelPos(const DPoint& absPos) const +glm::vec2 Node::getRelPos(const glm::vec2& absPos) const { - DPoint parentPos; - if (m_pParent.expired()) { + glm::vec2 parentPos; + if (m_pParent == 0) { parentPos = absPos; } else { - parentPos = m_pParent.lock()->getRelPos(absPos); + parentPos = m_pParent->getSharedThis()->getRelPos(absPos); } return toLocal(parentPos); } -DPoint Node::getAbsPos(const DPoint& relPos) const +glm::vec2 Node::getAbsPos(const glm::vec2& relPos) const { - DPoint thisPos = toGlobal(relPos); - DPoint parentPos; - if (m_pParent.expired()) { + glm::vec2 thisPos = toGlobal(relPos); + glm::vec2 parentPos; + if (m_pParent == 0) { parentPos = thisPos; } else { - parentPos = m_pParent.lock()->getAbsPos(thisPos); + parentPos = m_pParent->getSharedThis()->getAbsPos(thisPos); } return parentPos; } -DPoint Node::toLocal(const DPoint& globalPos) const +glm::vec2 Node::toLocal(const glm::vec2& globalPos) const { return globalPos; } -DPoint Node::toGlobal(const DPoint& localPos) const +glm::vec2 Node::toGlobal(const glm::vec2& localPos) const { return localPos; } -NodePtr Node::getElementByPos(const DPoint& pos) +NodePtr Node::getElementByPos(const glm::vec2& pos) { - vector<NodeWeakPtr> elements; + vector<NodePtr> elements; getElementsByPos(pos, elements); if (elements.empty()) { return NodePtr(); } else { - return elements[0].lock(); + return elements[0]; } } -void Node::getElementsByPos(const DPoint& pos, - vector<NodeWeakPtr>& pElements) +void Node::getElementsByPos(const glm::vec2& pos, vector<NodePtr>& pElements) { } -void Node::preRender() +void Node::preRender(const VertexArrayPtr& pVA, bool bIsParentActive, + float parentEffectiveOpacity) { - if (getParent()) { - m_EffectiveOpacity = m_Opacity*getParent()->getEffectiveOpacity(); - } else { - m_EffectiveOpacity = m_Opacity; - } + m_EffectiveOpacity = m_Opacity*parentEffectiveOpacity; + m_bEffectiveActive = bIsParentActive && m_bActive; } Node::NodeState Node::getState() const @@ -364,6 +375,11 @@ CanvasPtr Node::getCanvas() const bool Node::handleEvent(EventPtr pEvent) { + if (pEvent->getSource() != Event::NONE && pEvent->getSource() != Event::CUSTOM) { + string messageID = getEventMessageID(pEvent); + notifySubscribers(messageID, pEvent); + } + EventID id(pEvent->getType(), pEvent->getSource()); EventHandlerMap::iterator it = m_EventHandlerMap.find(id); if (it != m_EventHandlerMap.end()) { @@ -381,24 +397,7 @@ bool Node::handleEvent(EventPtr pEvent) } } -void Node::addArgEventHandlers(Event::Type eventType, const string& sCode) -{ - addArgEventHandler(eventType, Event::MOUSE, sCode); - addArgEventHandler(eventType, Event::TOUCH, sCode); - addArgEventHandler(eventType, Event::TRACK, sCode); -} - -void Node::addArgEventHandler(Event::Type eventType, Event::Source source, - const string& sCode) -{ - PyObject * pFunc = findPythonFunc(sCode); - if (pFunc) { - EventID id(eventType, source); - connectOneEventHandler(id, Py_None, pFunc); - } -} - -double Node::getEffectiveOpacity() const +float Node::getEffectiveOpacity() const { return m_EffectiveOpacity; } @@ -456,7 +455,7 @@ void Node::initFilename(string& sFilename) } } -void Node::checkReload(const std::string& sHRef, const ImagePtr& pImage, +bool Node::checkReload(const std::string& sHRef, const ImagePtr& pImage, Image::TextureCompression comp) { string sLastFilename = pImage->getFilename(); @@ -473,11 +472,14 @@ void Node::checkReload(const std::string& sHRef, const ImagePtr& pImage, } catch (Exception& ex) { pImage->setEmpty(); if (getState() != Node::NS_UNCONNECTED) { - AVG_TRACE(Logger::ERROR, ex.getStr()); + AVG_LOG_ERROR(ex.getStr()); } else { - AVG_TRACE(Logger::MEMORY, ex.getStr()); + AVG_TRACE(Logger::category::MEMORY, Logger::severity::INFO, ex.getStr()); } } + return true; + } else { + return false; } } @@ -488,11 +490,12 @@ bool Node::isVisible() const bool Node::getEffectiveActive() const { - if (getParent()) { - return m_bActive && getParent()->getEffectiveActive(); - } else { - return m_bActive; - } + return m_bEffectiveActive; +} + +NodePtr Node::getSharedThis() +{ + return dynamic_pointer_cast<Node>(ExportedObject::getSharedThis()); } void Node::connectOneEventHandler(const EventID& id, PyObject * pObj, @@ -528,58 +531,52 @@ void Node::dumpEventHandlers() cerr << "-----" << endl; } -PyObject * Node::findPythonFunc(const string& sCode) -{ - if (sCode.empty()) { - return 0; - } else { - PyObject * pModule = PyImport_AddModule("__main__"); - if (!pModule) { - cerr << "Could not find module __main__." << endl; - exit(-1); +string Node::getEventMessageID(const EventPtr& pEvent) +{ + Event::Source source = pEvent->getSource(); + if (source == Event::MOUSE || source == Event::TOUCH) { + switch (pEvent->getType()) { + case Event::CURSOR_DOWN: + return "CURSOR_DOWN"; + case Event::CURSOR_MOTION: + return "CURSOR_MOTION"; + case Event::CURSOR_UP: + return "CURSOR_UP"; + case Event::CURSOR_OVER: + return "CURSOR_OVER"; + case Event::CURSOR_OUT: + return "CURSOR_OUT"; + default: + AVG_ASSERT_MSG(false, + (string("Unknown message type ")+pEvent->typeStr()).c_str()); + return ""; } - PyObject * pDict = PyModule_GetDict(pModule); - PyObject * pFunc = PyDict_GetItemString(pDict, sCode.c_str()); - if (!pFunc) { - AVG_TRACE(Logger::ERROR, "Function \"" << sCode << - "\" not defined for node with id '"+getID()+"'. Aborting."); - exit(-1); + } else { + switch (pEvent->getType()) { + case Event::CURSOR_DOWN: + return "HOVER_DOWN"; + case Event::CURSOR_MOTION: + return "HOVER_MOTION"; + case Event::CURSOR_UP: + return "HOVER_UP"; + case Event::CURSOR_OVER: + return "HOVER_OVER"; + case Event::CURSOR_OUT: + return "HOVER_OUT"; + default: + AVG_ASSERT_MSG(false, + (string("Unknown message type ")+pEvent->typeStr()).c_str()); + return ""; } - return pFunc; } } bool Node::callPython(PyObject * pFunc, EventPtr pEvent) { - bool bOk = boost::python::call<bool>(pFunc, pEvent); + bool bOk = py::call<bool>(pFunc, pEvent); return bOk; } -bool Node::operator ==(const Node& other) const -{ - return this == &other; -} - -bool Node::operator !=(const Node& other) const -{ - return this != &other; -} - -long Node::getHash() const -{ - return long(this); -} - -const NodeDefinition* Node::getDefinition() const -{ - return m_pDefinition; -} - -string Node::getTypeStr() const -{ - return m_pDefinition->getName(); -} - Node::EventID::EventID(Event::Type eventType, Event::Source source) : m_Type(eventType), m_Source(source) diff --git a/src/player/Node.h b/src/player/Node.h index 1130607..9e2b439 100644 --- a/src/player/Node.h +++ b/src/player/Node.h @@ -1,6 +1,6 @@ // // libavg - Media Playback Engine. -// Copyright (C) 2003-2011 Ulrich von Zadow +// Copyright (C) 2003-2014 Ulrich von Zadow // // This library is free software; you can redistribute it and/or // modify it under the terms of the GNU Lesser General Public @@ -24,6 +24,7 @@ #include "../api.h" +#include "Publisher.h" #include "Event.h" #include "Image.h" @@ -32,15 +33,12 @@ #include <boost/shared_ptr.hpp> #include <boost/weak_ptr.hpp> -#include <boost/enable_shared_from_this.hpp> - -#include <string> -#include <vector> // Python docs say python.h should be included before any standard headers (!) #include "WrapPython.h" #include <string> +#include <vector> #include <list> #include <map> @@ -48,19 +46,15 @@ namespace avg { class Node; typedef boost::shared_ptr<Node> NodePtr; -typedef boost::weak_ptr<Node> NodeWeakPtr; class DivNode; typedef boost::shared_ptr<DivNode> DivNodePtr; -typedef boost::weak_ptr<DivNode> DivNodeWeakPtr; class ArgList; -class NodeDefinition; +class TypeDefinition; class CanvasNode; typedef boost::shared_ptr<CanvasNode> CanvasNodePtr; -typedef boost::weak_ptr<CanvasNode> CanvasNodeWeakPtr; class AVGNode; typedef boost::shared_ptr<AVGNode> AVGNodePtr; -typedef boost::weak_ptr<AVGNode> AVGNodeWeakPtr; class Image; typedef boost::shared_ptr<Image> ImagePtr; class VertexArray; @@ -69,27 +63,21 @@ class Canvas; typedef boost::shared_ptr<Canvas> CanvasPtr; typedef boost::weak_ptr<Canvas> CanvasWeakPtr; -class AVG_API Node: public boost::enable_shared_from_this<Node> +class AVG_API Node: public Publisher { public: enum NodeState {NS_UNCONNECTED, NS_CONNECTED, NS_CANRENDER}; - - static NodeDefinition createDefinition(); - template<class NodeType> - static NodePtr buildNode(const ArgList& Args) - { - return NodePtr(new NodeType(Args)); - } - virtual void setTypeInfo(const NodeDefinition * pDefinition); + + static void registerType(); + void registerInstance(PyObject* pSelf, const DivNodePtr& pParent); virtual ~Node(); - virtual void setArgs(const ArgList& args); - virtual void setParent(DivNodeWeakPtr pParent, NodeState parentState, + virtual void setParent(DivNode* pParent, NodeState parentState, CanvasPtr pCanvas); virtual void removeParent(); - void checkSetParentError(DivNodeWeakPtr pParent); + void checkSetParentError(DivNode* pParent); DivNodePtr getParent() const; - std::vector<NodeWeakPtr> getParentChain(); + std::vector<NodePtr> getParentChain(); virtual void connectDisplay(); virtual void connect(CanvasPtr pCanvas); @@ -100,8 +88,8 @@ class AVG_API Node: public boost::enable_shared_from_this<Node> virtual void setID(const std::string& ID); - double getOpacity() const; - void setOpacity(double opacity); + float getOpacity() const; + void setOpacity(float opacity); bool getActive() const; void setActive(bool bActive); @@ -118,19 +106,21 @@ class AVG_API Node: public boost::enable_shared_from_this<Node> PyObject * pObj, PyObject * pFunc); void disconnectEventHandler(PyObject * pObj, PyObject * pFunc=0); - DPoint getRelPos(const DPoint& absPos) const; - DPoint getAbsPos(const DPoint& relPos) const; - virtual DPoint toLocal(const DPoint& pos) const; - virtual DPoint toGlobal(const DPoint& pos) const; - NodePtr getElementByPos(const DPoint& pos); - virtual void getElementsByPos(const DPoint& pos, - std::vector<NodeWeakPtr>& pElements); - - virtual void preRender(); - virtual void maybeRender(const DRect& Rect) {}; - virtual void render(const DRect& Rect) {}; + glm::vec2 getRelPos(const glm::vec2& absPos) const; + glm::vec2 getAbsPos(const glm::vec2& relPos) const; + virtual glm::vec2 toLocal(const glm::vec2& pos) const; + virtual glm::vec2 toGlobal(const glm::vec2& pos) const; + NodePtr getElementByPos(const glm::vec2& pos); + virtual void getElementsByPos(const glm::vec2& pos, + std::vector<NodePtr>& pElements); + + virtual void preRender(const VertexArrayPtr& pVA, bool bIsParentActive, + float parentEffectiveOpacity); + virtual void maybeRender(const glm::mat4& parentTransform) {}; + virtual void render() {}; + virtual void renderOutlines(const VertexArrayPtr& pVA, Pixel32 color) {}; - double getEffectiveOpacity() const; + float getEffectiveOpacity() const; virtual std::string dump(int indent = 0); NodeState getState() const; @@ -139,36 +129,24 @@ class AVG_API Node: public boost::enable_shared_from_this<Node> virtual bool handleEvent(EventPtr pEvent); virtual const std::string& getID() const; - std::string getTypeStr() const; - - bool operator ==(const Node& other) const; - bool operator !=(const Node& other) const; - long getHash() const; - - virtual const NodeDefinition* getDefinition() const; - - virtual void renderOutlines(const VertexArrayPtr& pVA, Pixel32 color) {}; - + protected: - Node(); + Node(const std::string& sPublisherName="Node"); - void addArgEventHandlers(Event::Type eventType, const std::string& sCode); - void addArgEventHandler(Event::Type eventType, Event::Source source, - const std::string& sCode); bool reactsToMouseEvents(); void setState(NodeState state); void initFilename(std::string& sFilename); - void checkReload(const std::string& sHRef, const ImagePtr& pImage, + bool checkReload(const std::string& sHRef, const ImagePtr& pImage, Image::TextureCompression comp = Image::TEXTURECOMPRESSION_NONE); virtual bool isVisible() const; bool getEffectiveActive() const; + NodePtr getSharedThis(); private: std::string m_ID; - const NodeDefinition* m_pDefinition; - DivNodeWeakPtr m_pParent; + DivNode* m_pParent; struct EventID { EventID(Event::Type eventType, Event::Source source); @@ -194,19 +172,20 @@ class AVG_API Node: public boost::enable_shared_from_this<Node> void connectOneEventHandler(const EventID& id, PyObject * pObj, PyObject * pFunc); void dumpEventHandlers(); - PyObject * findPythonFunc(const std::string& sCode); + std::string getEventMessageID(const EventPtr& pEvent); bool callPython(PyObject * pFunc, avg::EventPtr pEvent); EventHandlerMap m_EventHandlerMap; CanvasWeakPtr m_pCanvas; - double m_Opacity; + float m_Opacity; NodeState m_State; bool m_bActive; bool m_bSensitive; - double m_EffectiveOpacity; + float m_EffectiveOpacity; + bool m_bEffectiveActive; }; } diff --git a/src/player/NodeRegistry.cpp b/src/player/NodeRegistry.cpp deleted file mode 100644 index 854e827..0000000 --- a/src/player/NodeRegistry.cpp +++ /dev/null @@ -1,126 +0,0 @@ -// -// libavg - Media Playback Engine. -// Copyright (C) 2003-2011 Ulrich von Zadow -// -// This library is free software; you can redistribute it and/or -// modify it under the terms of the GNU Lesser General Public -// License as published by the Free Software Foundation; either -// version 2 of the License, or (at your option) any later version. -// -// This library 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 -// Lesser General Public License for more details. -// -// You should have received a copy of the GNU Lesser General Public -// License along with this library; if not, write to the Free Software -// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA -// -// Current versions can be found at www.libavg.de -// -// Original author of this file is Nick Hebner (hebnern@gmail.com). -// - -#include "NodeRegistry.h" -#include "NodeDefinition.h" - -#include "../base/Exception.h" - -#include <set> - -using namespace std; - -namespace avg { - -NodeRegistry::NodeRegistry() -{ -} - -NodeRegistry::~NodeRegistry() -{ -} - -void NodeRegistry::registerNodeType(const NodeDefinition& def) -{ - m_NodeDefs.insert(NodeDefMap::value_type(def.getName(), def)); -} - -void NodeRegistry::updateNodeDefinition(const NodeDefinition& def) -{ - m_NodeDefs[def.getName()] = def; -} - -NodePtr NodeRegistry::createNode(const string& sType, const xmlNodePtr xmlNode) -{ - const NodeDefinition& def = getNodeDef(sType); - ArgList args(def.getDefaultArgs(), xmlNode); - NodeBuilder builder = def.getBuilder(); - NodePtr pNode = builder(args); - pNode->setTypeInfo(&def); - return pNode; -} - -NodePtr NodeRegistry::createNode(const string& sType, const boost::python::dict& pyDict) -{ - const NodeDefinition& def = getNodeDef(sType); - ArgList args(def.getDefaultArgs(), pyDict); - NodeBuilder builder = def.getBuilder(); - NodePtr pNode = builder(args); - pNode->setTypeInfo(&def); - return pNode; -} - -string NodeRegistry::getDTD() const -{ - if (m_NodeDefs.empty()) { - return string(""); - } - - stringstream ss; - - for (NodeDefMap::const_iterator defIt = m_NodeDefs.begin(); - defIt != m_NodeDefs.end(); defIt++) - { - const NodeDefinition& def = defIt->second; - writeNodeDTD(def, ss); - } - - for (NodeDefMap::const_iterator defIt = m_NodeDefs.begin(); - defIt != m_NodeDefs.end(); defIt++) - { - const NodeDefinition& def = defIt->second; - ss << def.getDTDElements(); - } - - return ss.str(); -} - -const NodeDefinition& NodeRegistry::getNodeDef(const string& sType) -{ - NodeDefMap::const_iterator it = m_NodeDefs.find(sType); - if (it == m_NodeDefs.end()) { - throw (Exception (AVG_ERR_XML_NODE_UNKNOWN, - string("Unknown node type ") + sType + " encountered.")); - } - return it->second; -} - -void NodeRegistry::writeNodeDTD(const NodeDefinition& def, stringstream& ss) const -{ - ss << "<!ELEMENT " << def.getName() << " " << def.getDTDChildrenString() << " >\n"; - if (!def.getDefaultArgs().getArgMap().empty()) { - ss << "<!ATTLIST " << def.getName(); - for (ArgMap::const_iterator argIt = def.getDefaultArgs().getArgMap().begin(); - argIt != def.getDefaultArgs().getArgMap().end(); argIt++) - { - string argName = argIt->first; - string argType = (argName == "id") ? "ID" : "CDATA"; - string argRequired = def.getDefaultArgs().getArg(argName)->isRequired() ? - "#REQUIRED" : "#IMPLIED"; - ss << "\n " << argName << " " << argType << " " << argRequired; - } - ss << " >\n"; - } -} - -} diff --git a/src/player/NullFXNode.cpp b/src/player/NullFXNode.cpp index 544b6d9..d0d943d 100644 --- a/src/player/NullFXNode.cpp +++ b/src/player/NullFXNode.cpp @@ -1,6 +1,6 @@ // // libavg - Media Playback Engine. -// Copyright (C) 2003-2011 Ulrich von Zadow +// Copyright (C) 2003-2014 Ulrich von Zadow // // This library is free software; you can redistribute it and/or // modify it under the terms of the GNU Lesser General Public @@ -22,7 +22,6 @@ #include "NullFXNode.h" #include "../base/ObjectCounter.h" -#include "../graphics/ShaderRegistry.h" #include <string> diff --git a/src/player/NullFXNode.h b/src/player/NullFXNode.h index b79c7b4..107ce4b 100644 --- a/src/player/NullFXNode.h +++ b/src/player/NullFXNode.h @@ -1,6 +1,6 @@ // // libavg - Media Playback Engine. -// Copyright (C) 2003-2011 Ulrich von Zadow +// Copyright (C) 2003-2014 Ulrich von Zadow // // This library is free software; you can redistribute it and/or // modify it under the terms of the GNU Lesser General Public diff --git a/src/player/OGLSurface.cpp b/src/player/OGLSurface.cpp index c83acbe..b0aa58e 100644 --- a/src/player/OGLSurface.cpp +++ b/src/player/OGLSurface.cpp @@ -1,6 +1,6 @@ // // libavg - Media Playback Engine. -// Copyright (C) 2003-2011 Ulrich von Zadow +// Copyright (C) 2003-2014 Ulrich von Zadow // // This library is free software; you can redistribute it and/or // modify it under the terms of the GNU Lesser General Public @@ -27,23 +27,21 @@ #include "../base/ScopeTimer.h" #include "../base/ObjectCounter.h" -#include "../graphics/ShaderRegistry.h" #include "../graphics/GLContext.h" #include "../graphics/GLTexture.h" #include <iostream> #include <sstream> -using namespace std; +#include "../glm/gtc/matrix_transform.hpp" -#define COLORSPACE_SHADER "COLORSPACE" +using namespace std; -static float yuvCoeff[3][4] = -{ - {1.0f, 0.0f, 1.40f, 0.0f}, - {1.0f, -0.34f, -0.71f, 0.0f}, - {1.0f, 1.77f, 0.0f, 0.0f}, -}; +static glm::mat4 yuvCoeff( + 1.0f, 1.0f, 1.0f, 0.0f, + 0.0f, -0.34f, 1.77f, 0.0f, + 1.40f, -0.71f, 0.0f, 0.0f, + 0.0f, 0.0f, 0.0f, 1.0f); namespace avg { @@ -52,6 +50,7 @@ OGLSurface::OGLSurface() m_Gamma(1,1,1), m_Brightness(1,1,1), m_Contrast(1,1,1), + m_AlphaGamma(1), m_bIsDirty(true) { ObjectCounter::get()->incRef(&typeid(*this)); @@ -62,20 +61,6 @@ OGLSurface::~OGLSurface() ObjectCounter::get()->decRef(&typeid(*this)); } -void OGLSurface::attach() -{ - if (!GLContext::getCurrent()->isUsingShaders()) { - if (m_pMaskTexture) { - throw Exception(AVG_ERR_VIDEO_GENERAL, - "Can't set mask bitmap since shader support is disabled."); - } - if (gammaIsModified() || colorIsModified()) { - throw Exception(AVG_ERR_VIDEO_GENERAL, - "Can't use color correction (gamma, brightness, contrast) since shader support is disabled."); - } - } -} - void OGLSurface::create(PixelFormat pf, GLTexturePtr pTex0, GLTexturePtr pTex1, GLTexturePtr pTex2, GLTexturePtr pTex3) { @@ -116,82 +101,68 @@ void OGLSurface::destroy() void OGLSurface::activate(const IntPoint& logicalSize, bool bPremultipliedAlpha) const { - if (useShader()) { - OGLShaderPtr pShader = getShader(COLORSPACE_SHADER); - pShader->activate(); - OGLErrorCheck(AVG_ERR_VIDEO_GENERAL, "OGLSurface::activate()"); - switch (m_pf) { - case YCbCr420p: - case YCbCrJ420p: - pShader->setUniformIntParam("colorModel", 1); - break; - case YCbCrA420p: - pShader->setUniformIntParam("colorModel", 3); - break; - case A8: - pShader->setUniformIntParam("colorModel", 2); - break; - default: - pShader->setUniformIntParam("colorModel", 0); - } - - m_pTextures[0]->activate(GL_TEXTURE0); - pShader->setUniformIntParam("texture", 0); - - if (pixelFormatIsPlanar(m_pf)) { - m_pTextures[1]->activate(GL_TEXTURE1); - pShader->setUniformIntParam("cbTexture", 1); - m_pTextures[2]->activate(GL_TEXTURE2); - pShader->setUniformIntParam("crTexture", 2); - if (m_pf == YCbCrA420p) { - m_pTextures[3]->activate(GL_TEXTURE3); - pShader->setUniformIntParam("aTexture", 3); - } - } - if (pixelFormatIsPlanar(m_pf) || colorIsModified()) { - Matrix3x4 mat = calcColorspaceMatrix(); - pShader->setUniformVec4fParam("colorCoeff0", - mat.val[0][0], mat.val[1][0], mat.val[2][0], 0); - pShader->setUniformVec4fParam("colorCoeff1", - mat.val[0][1], mat.val[1][1], mat.val[2][1], 0); - pShader->setUniformVec4fParam("colorCoeff2", - mat.val[0][2], mat.val[1][2], mat.val[2][2], 0); - pShader->setUniformVec4fParam("colorCoeff3", - mat.val[0][3], mat.val[1][3], mat.val[2][3], 1); - } + StandardShaderPtr pShader = StandardShader::get(); + + GLContext::checkError("OGLSurface::activate()"); + switch (m_pf) { + case YCbCr420p: + case YCbCrJ420p: + pShader->setColorModel(1); + break; + case YCbCrA420p: + pShader->setColorModel(3); + break; + case A8: + pShader->setColorModel(2); + break; + default: + pShader->setColorModel(0); + } - pShader->setUniformVec4fParam("gamma", float(1/m_Gamma.x), float(1/m_Gamma.y), - float(1/m_Gamma.z), 1.0); - pShader->setUniformIntParam("bUseColorCoeff", colorIsModified()); + m_pTextures[0]->activate(GL_TEXTURE0); - pShader->setUniformIntParam("bPremultipliedAlpha", bPremultipliedAlpha); - pShader->setUniformIntParam("bUseMask", bool(m_pMaskTexture)); - if (m_pMaskTexture) { - m_pMaskTexture->activate(GL_TEXTURE4); - pShader->setUniformIntParam("maskTexture", 4); - pShader->setUniformDPointParam("maskPos", m_MaskPos); - // maskScale is (1,1) for everything excepting words nodes. - DPoint maskScale(1,1); - if (logicalSize != IntPoint(0,0)) { - maskScale = DPoint((double)logicalSize.x/m_Size.x, - (double)logicalSize.y/m_Size.y); - } - pShader->setUniformDPointParam("maskSize", m_MaskSize*maskScale); + if (pixelFormatIsPlanar(m_pf)) { + m_pTextures[1]->activate(GL_TEXTURE1); + m_pTextures[2]->activate(GL_TEXTURE2); + if (m_pf == YCbCrA420p) { + m_pTextures[3]->activate(GL_TEXTURE3); } - - OGLErrorCheck(AVG_ERR_VIDEO_GENERAL, "OGLSurface::activate: params"); + } + if (pixelFormatIsPlanar(m_pf) || colorIsModified()) { + glm::mat4 mat = calcColorspaceMatrix(); + pShader->setColorspaceMatrix(mat); } else { - m_pTextures[0]->activate(GL_TEXTURE0); - if (GLContext::getCurrent()->isUsingShaders()) { - glproc::UseProgramObject(0); - } - for (int i=1; i<5; ++i) { - glproc::ActiveTexture(GL_TEXTURE0 + i); - glDisable(GL_TEXTURE_2D); + pShader->disableColorspaceMatrix(); + } + pShader->setGamma(glm::vec4(1/m_Gamma.x, 1/m_Gamma.y, 1/m_Gamma.z, + 1./m_AlphaGamma)); + + pShader->setPremultipliedAlpha(bPremultipliedAlpha); + if (m_pMaskTexture) { + m_pMaskTexture->activate(GL_TEXTURE4); + // Special case for pot textures: + // The tex coords in the vertex array are scaled to fit the image texture. We + // need to undo this and fit to the mask texture. In the npot case, everything + // evaluates to (1,1); + glm::vec2 texSize = glm::vec2(m_pTextures[0]->getGLSize()); + glm::vec2 imgSize = glm::vec2(m_pTextures[0]->getSize()); + glm::vec2 maskTexSize = glm::vec2(m_pMaskTexture->getGLSize()); + glm::vec2 maskImgSize = glm::vec2(m_pMaskTexture->getSize()); + glm::vec2 maskScale = glm::vec2(maskTexSize.x/maskImgSize.x, + maskTexSize.y/maskImgSize.y); + glm::vec2 imgScale = glm::vec2(texSize.x/imgSize.x, texSize.y/imgSize.y); + glm::vec2 maskPos = m_MaskPos/maskScale; + // Special case for words nodes. + if (logicalSize != IntPoint(0,0)) { + maskScale *= glm::vec2((float)logicalSize.x/m_Size.x, + (float)logicalSize.y/m_Size.y); } - glproc::ActiveTexture(GL_TEXTURE0); - OGLErrorCheck(AVG_ERR_VIDEO_GENERAL, "OGLSurface::activate: fixed function"); + pShader->setMask(true, maskPos, m_MaskSize*maskScale/imgScale); + } else { + pShader->setMask(false); } + pShader->activate(); + GLContext::checkError("OGLSurface::activate"); } GLTexturePtr OGLSurface::getTex(int i) const @@ -199,7 +170,7 @@ GLTexturePtr OGLSurface::getTex(int i) const return m_pTextures[i]; } -void OGLSurface::setMaskCoords(DPoint maskPos, DPoint maskSize) +void OGLSurface::setMaskCoords(glm::vec2 maskPos, glm::vec2 maskSize) { m_MaskPos = maskPos; m_MaskSize = maskSize; @@ -226,94 +197,19 @@ bool OGLSurface::isCreated() const return m_pTextures[0]; } -void OGLSurface::setColorParams(const DTriple& gamma, const DTriple& brightness, - const DTriple& contrast) +void OGLSurface::setColorParams(const glm::vec3& gamma, const glm::vec3& brightness, + const glm::vec3& contrast) { m_Gamma = gamma; m_Brightness = brightness; m_Contrast = contrast; - if (!GLContext::getCurrent()->isUsingShaders() && - (gammaIsModified() || colorIsModified())) - { - throw Exception(AVG_ERR_VIDEO_GENERAL, - "Can't use color correction (gamma, brightness, contrast) since shader support is disabled."); - } m_bIsDirty = true; } -void OGLSurface::createShader() +void OGLSurface::setAlphaGamma(float gamma) { - string sProgram = - "uniform sampler2D texture;\n" - "uniform sampler2D yTexture;\n" - "uniform sampler2D cbTexture;\n" - "uniform sampler2D crTexture;\n" - "uniform sampler2D aTexture;\n" - "uniform sampler2D maskTexture;\n" - "uniform int colorModel; // 0=rgb, 1=yuv, 2=greyscale, 3=yuva\n" - "uniform vec4 colorCoeff0;\n" - "uniform vec4 colorCoeff1;\n" - "uniform vec4 colorCoeff2;\n" - "uniform vec4 colorCoeff3;\n" - "uniform bool bUseColorCoeff;\n" - "uniform vec4 gamma;\n" - "uniform bool bPremultipliedAlpha;\n" - "uniform bool bUseMask;\n" - "uniform vec2 maskPos;\n" - "uniform vec2 maskSize;\n" - "\n" - "vec4 convertYCbCr(mat4 colorCoeff)\n" - "{\n" - " vec4 yuv;\n" - " yuv = vec4(texture2D(texture, gl_TexCoord[0].st).r,\n" - " texture2D(cbTexture, (gl_TexCoord[0].st)).r,\n" - " texture2D(crTexture, (gl_TexCoord[0].st)).r,\n" - " 1.0);\n" - " vec4 rgb;\n" - " rgb = colorCoeff*yuv;\n" - " return vec4(rgb.rgb, gl_Color.a);\n" - "}\n" - "\n" - "void main(void)\n" - "{\n" - " vec4 rgba;\n" - " mat4 colorCoeff;\n" - " colorCoeff[0] = colorCoeff0;\n" - " colorCoeff[1] = colorCoeff1;\n" - " colorCoeff[2] = colorCoeff2;\n" - " colorCoeff[3] = colorCoeff3;\n" - " if (colorModel == 0) {\n" - " rgba = texture2D(texture, gl_TexCoord[0].st);\n" - " if (bUseColorCoeff) {\n" - " rgba = colorCoeff*rgba;\n" - " };\n" - " rgba.a *= gl_Color.a;\n" - " } else if (colorModel == 1) {\n" - " rgba = convertYCbCr(colorCoeff);\n" - " } else if (colorModel == 2) {\n" - " rgba = gl_Color;\n" - " if (bUseColorCoeff) {\n" - " rgba = colorCoeff*rgba;\n" - " };\n" - " rgba.a *= texture2D(texture, gl_TexCoord[0].st).a;\n" - " } else if (colorModel == 3) {\n" - " rgba = convertYCbCr(colorCoeff);\n" - " rgba.a *= texture2D(aTexture, gl_TexCoord[0].st).r;\n" - " } else {\n" - " rgba = vec4(1,1,1,1);\n" - " }\n" - " rgba = pow(rgba, gamma);\n" - " if (bUseMask) {\n" - " if (bPremultipliedAlpha) {\n" - " rgba.rgb *= texture2D(maskTexture,\n" - " (gl_TexCoord[0].st/maskSize)-maskPos).r;\n" - " }\n" - " rgba.a *= texture2D(maskTexture,\n" - " (gl_TexCoord[0].st/maskSize)-maskPos).r;\n" - " }\n" - " gl_FragColor = rgba;\n" - "}\n"; - getOrCreateShader(COLORSPACE_SHADER, sProgram); + m_AlphaGamma = gamma; + m_bIsDirty = true; } bool OGLSurface::isDirty() const @@ -335,40 +231,27 @@ void OGLSurface::resetDirty() } } -bool OGLSurface::useShader() const -{ - return GLContext::getCurrent()->isUsingShaders() && - (m_pMaskTexture || pixelFormatIsPlanar(m_pf) || gammaIsModified() || - colorIsModified()); -} - -Matrix3x4 OGLSurface::calcColorspaceMatrix() const +glm::mat4 OGLSurface::calcColorspaceMatrix() const { - Matrix3x4 mat; + glm::mat4 mat; if (colorIsModified()) { - mat *= Matrix3x4::createScale(m_Brightness); - mat *= Matrix3x4::createTranslate(float(0.5-m_Contrast.x/2), - float(0.5-m_Contrast.y/2), float(0.5-m_Contrast.z/2)); - mat *= Matrix3x4::createScale(m_Contrast); + mat = glm::scale(mat, m_Brightness); + glm::vec3 contrast = glm::vec3(0.5f, 0.5f, 0.5f) - m_Contrast/2.f; + mat = glm::translate(mat, contrast); + mat = glm::scale(mat, m_Contrast); } if (m_pf == YCbCr420p || m_pf == YCbCrJ420p || m_pf == YCbCrA420p) { - mat *= Matrix3x4(*yuvCoeff); - mat *= Matrix3x4::createTranslate(0.0, -0.5, -0.5); + mat *= yuvCoeff; + mat = glm::translate(mat, glm::vec3(0.0, -0.5, -0.5)); if (m_pf == YCbCr420p || m_pf == YCbCrA420p) { - mat *= Matrix3x4::createScale(255.0f/(235-16), 255.0f/(240-16) , - 255.0f/(240-16)); - mat *= Matrix3x4::createTranslate(-16.0f/255, -16.0f/255, -16.0f/255); + mat = glm::scale(mat, + glm::vec3(255.0f/(235-16), 255.0f/(235-16), 255.0f/(235-16))); + mat = glm::translate(mat, glm::vec3(-16.0f/255, -16.0f/255, -16.0f/255)); } } return mat; } -bool OGLSurface::gammaIsModified() const -{ - return (fabs(m_Gamma.x-1.0) > 0.00001 || fabs(m_Gamma.y-1.0) > 0.00001 || - fabs(m_Gamma.z-1.0) > 0.00001); -} - bool OGLSurface::colorIsModified() const { return (fabs(m_Brightness.x-1.0) > 0.00001 || fabs(m_Brightness.y-1.0) > 0.00001 || diff --git a/src/player/OGLSurface.h b/src/player/OGLSurface.h index a780b4a..38e6ef4 100644 --- a/src/player/OGLSurface.h +++ b/src/player/OGLSurface.h @@ -1,6 +1,6 @@ // // libavg - Media Playback Engine. -// Copyright (C) 2003-2011 Ulrich von Zadow +// Copyright (C) 2003-2014 Ulrich von Zadow // // This library is free software; you can redistribute it and/or // modify it under the terms of the GNU Lesser General Public @@ -24,12 +24,11 @@ #include "../api.h" -#include "../base/Point.h" -#include "../base/Triple.h" -#include "../base/Matrix3x4.h" +#include "../base/GLMHelper.h" #include "../graphics/Bitmap.h" #include "../graphics/OGLHelper.h" +#include "../graphics/StandardShader.h" #include <vector> #include <string> @@ -45,7 +44,6 @@ public: OGLSurface(); virtual ~OGLSurface(); - void attach(); virtual void create(PixelFormat pf, GLTexturePtr pTex0, GLTexturePtr pTex1 = GLTexturePtr(), GLTexturePtr pTex2 = GLTexturePtr(), GLTexturePtr pTex3 = GLTexturePtr()); @@ -55,39 +53,38 @@ public: bool bPremultipliedAlpha = false) const; GLTexturePtr getTex(int i=0) const; - void setMaskCoords(DPoint maskPos, DPoint maskSize); + void setMaskCoords(glm::vec2 maskPos, glm::vec2 maskSize); PixelFormat getPixelFormat(); IntPoint getSize(); IntPoint getTextureSize(); bool isCreated() const; - void setColorParams(const DTriple& gamma, const DTriple& brightness, - const DTriple& contrast); - static void createShader(); + void setColorParams(const glm::vec3& gamma, const glm::vec3& brightness, + const glm::vec3& contrast); + void setAlphaGamma(float gamma); bool isDirty() const; void resetDirty(); private: - bool useShader() const; - Matrix3x4 calcColorspaceMatrix() const; - bool gammaIsModified() const; + glm::mat4 calcColorspaceMatrix() const; bool colorIsModified() const; GLTexturePtr m_pTextures[4]; IntPoint m_Size; PixelFormat m_pf; GLTexturePtr m_pMaskTexture; - DPoint m_MaskPos; - DPoint m_MaskSize; + glm::vec2 m_MaskPos; + glm::vec2 m_MaskSize; - - DTriple m_Gamma; - DTriple m_Brightness; - DTriple m_Contrast; + glm::vec3 m_Gamma; + glm::vec3 m_Brightness; + glm::vec3 m_Contrast; + float m_AlphaGamma; bool m_bIsDirty; + }; } diff --git a/src/player/OffscreenCanvas.cpp b/src/player/OffscreenCanvas.cpp index 6ff1c52..758bf43 100644 --- a/src/player/OffscreenCanvas.cpp +++ b/src/player/OffscreenCanvas.cpp @@ -1,6 +1,6 @@ // // libavg - Media Playback Engine. -// Copyright (C) 2003-2011 Ulrich von Zadow +// Copyright (C) 2003-2014 Ulrich von Zadow // // This library is free software; you can redistribute it and/or // modify it under the terms of the GNU Lesser General Public @@ -25,10 +25,12 @@ #include "Player.h" #include "../base/Exception.h" -#include "../base/ProfilingZone.h" +#include "../base/ProfilingZoneID.h" #include "../base/ObjectCounter.h" +#include "../base/ScopeTimer.h" #include "../graphics/FilterUnmultiplyAlpha.h" +#include "../graphics/BitmapLoader.h" #include <iostream> @@ -62,38 +64,40 @@ void OffscreenCanvas::setRoot(NodePtr pRootNode) void OffscreenCanvas::initPlayback() { m_bUseMipmaps = getMipmap(); - m_pFBO = FBOPtr(new FBO(getSize(), B8G8R8A8, 1, getMultiSampleSamples(), true, - m_bUseMipmaps)); + PixelFormat pf; + if (BitmapLoader::get()->isBlueFirst()) { + pf = B8G8R8A8; + } else { + pf = R8G8B8A8; + } + bool bUseDepthBuffer = GLContext::getMain()->useDepthBuffer(); + m_pFBO = FBOPtr(new FBO(getSize(), pf, 1, getMultiSampleSamples(), bUseDepthBuffer, + true, m_bUseMipmaps)); Canvas::initPlayback(getMultiSampleSamples()); m_bIsRendered = false; } -void OffscreenCanvas::stopPlayback() +void OffscreenCanvas::stopPlayback(bool bIsAbort) { m_pFBO = FBOPtr(); - Canvas::stopPlayback(); + Canvas::stopPlayback(bIsAbort); m_bIsRendered = false; } BitmapPtr OffscreenCanvas::screenshot() const { - return screenshot(false); + BitmapPtr pBmp = screenshotIgnoreAlpha(); + FilterUnmultiplyAlpha().applyInPlace(pBmp); + return pBmp; } -static ProfilingZoneID OffscreenRenderProfilingZone("Render OffscreenCanvas"); - -BitmapPtr OffscreenCanvas::screenshot(bool bIgnoreAlpha) const +BitmapPtr OffscreenCanvas::screenshotIgnoreAlpha() const { if (!isRunning() || !m_bIsRendered) { throw(Exception(AVG_ERR_UNSUPPORTED, "OffscreenCanvas::screenshot(): Canvas has not been rendered. No screenshot available")); } BitmapPtr pBmp = m_pFBO->getImage(0); - if (bIgnoreAlpha) { - pBmp->setPixelFormat(B8G8R8X8); - } else { - FilterUnmultiplyAlpha().applyInPlace(pBmp); - } return pBmp; } @@ -126,7 +130,7 @@ void OffscreenCanvas::setAutoRender(bool bAutoRender) void OffscreenCanvas::manualRender() { emitPreRenderSignal(); - render(); + renderTree(); emitFrameEndSignal(); } @@ -184,10 +188,13 @@ bool OffscreenCanvas::isCameraImageAvailable() const void OffscreenCanvas::addDependentCanvas(CanvasPtr pCanvas) { - AVG_ASSERT(!(pCanvas == shared_from_this())); m_pDependentCanvases.push_back(pCanvas); - Player::get()->newCanvasDependency( - dynamic_pointer_cast<OffscreenCanvas>(shared_from_this())); + try { + Player::get()->newCanvasDependency(); + } catch (Exception&) { + m_pDependentCanvases.pop_back(); + throw; + } } void OffscreenCanvas::removeDependentCanvas(CanvasPtr pCanvas) @@ -202,14 +209,9 @@ void OffscreenCanvas::removeDependentCanvas(CanvasPtr pCanvas) AVG_ASSERT(false); } -bool OffscreenCanvas::hasDependentCanvas(CanvasPtr pCanvas) const +const vector<CanvasPtr>& OffscreenCanvas::getDependentCanvases() const { - for (unsigned i = 0; i < m_pDependentCanvases.size(); ++i) { - if (pCanvas == m_pDependentCanvases[i]) { - return true; - } - } - return false; + return m_pDependentCanvases; } unsigned OffscreenCanvas::getNumDependentCanvases() const @@ -223,8 +225,11 @@ bool OffscreenCanvas::isSupported() throw(Exception(AVG_ERR_UNSUPPORTED, "OffscreenCanvas::isSupported(): Player.play() needs to be called before support can be queried.")); } - - return FBO::isFBOSupported() && FBO::isPackedDepthStencilSupported(); + if (GLContext::getMain()->isGLES()) { + return true; + } else { + return FBO::isFBOSupported() && FBO::isPackedDepthStencilSupported(); + } } bool OffscreenCanvas::isMultisampleSupported() @@ -245,14 +250,20 @@ void OffscreenCanvas::dump() const } } -void OffscreenCanvas::render() +static ProfilingZoneID OffscreenRenderProfilingZone("Render OffscreenCanvas"); + +void OffscreenCanvas::renderTree() { if (!isRunning()) { throw(Exception(AVG_ERR_UNSUPPORTED, - "OffscreenCanvas::render(): Player.play() needs to be called before rendering offscreen canvases.")); + "OffscreenCanvas::renderTree(): Player.play() needs to be called before rendering offscreen canvases.")); + } + preRender(); + m_pFBO->activate(); + { + ScopeTimer Timer(OffscreenRenderProfilingZone); + Canvas::render(IntPoint(getRootNode()->getSize()), true); } - Canvas::render(IntPoint(getRootNode()->getSize()), true, m_pFBO, - OffscreenRenderProfilingZone); m_pFBO->copyToDestTexture(); m_bIsRendered = true; } diff --git a/src/player/OffscreenCanvas.h b/src/player/OffscreenCanvas.h index 808f950..4d740b6 100644 --- a/src/player/OffscreenCanvas.h +++ b/src/player/OffscreenCanvas.h @@ -1,6 +1,6 @@ // // libavg - Media Playback Engine. -// Copyright (C) 2003-2011 Ulrich von Zadow +// Copyright (C) 2003-2014 Ulrich von Zadow // // This library is free software; you can redistribute it and/or // modify it under the terms of the GNU Lesser General Public @@ -41,10 +41,10 @@ class AVG_API OffscreenCanvas: public Canvas virtual ~OffscreenCanvas(); virtual void setRoot(NodePtr pRootNode); virtual void initPlayback(); - virtual void stopPlayback(); + virtual void stopPlayback(bool bIsAbort); virtual BitmapPtr screenshot() const; - virtual BitmapPtr screenshot(bool bIgnoreAlpha) const; + virtual BitmapPtr screenshotIgnoreAlpha() const; bool getHandleEvents() const; int getMultiSampleSamples() const; bool getMipmap() const; @@ -65,7 +65,7 @@ class AVG_API OffscreenCanvas: public Canvas void addDependentCanvas(CanvasPtr pCanvas); void removeDependentCanvas(CanvasPtr pCanvas); - bool hasDependentCanvas(CanvasPtr pCanvas) const; + const std::vector<CanvasPtr>& getDependentCanvases() const; unsigned getNumDependentCanvases() const; static bool isSupported(); @@ -73,7 +73,7 @@ class AVG_API OffscreenCanvas: public Canvas void dump() const; protected: - virtual void render(); + virtual void renderTree(); private: FBOPtr m_pFBO; @@ -82,7 +82,6 @@ class AVG_API OffscreenCanvas: public Canvas bool m_bIsRendered; CameraNode* m_pCameraNodeRef; - int m_cameraFrameRate; }; typedef boost::shared_ptr<OffscreenCanvas> OffscreenCanvasPtr; diff --git a/src/player/OffscreenCanvasNode.cpp b/src/player/OffscreenCanvasNode.cpp index 5c72802..8f712c3 100644 --- a/src/player/OffscreenCanvasNode.cpp +++ b/src/player/OffscreenCanvasNode.cpp @@ -1,6 +1,6 @@ // // libavg - Media Playback Engine. -// Copyright (C) 2003-2011 Ulrich von Zadow +// Copyright (C) 2003-2014 Ulrich von Zadow // // This library is free software; you can redistribute it and/or // modify it under the terms of the GNU Lesser General Public @@ -22,7 +22,7 @@ #include "OffscreenCanvasNode.h" #include "Player.h" -#include "NodeDefinition.h" +#include "TypeDefinition.h" #include "../base/FileHelper.h" @@ -30,10 +30,10 @@ using namespace std; namespace avg { -NodeDefinition OffscreenCanvasNode::createDefinition() +void OffscreenCanvasNode::registerType() { - return NodeDefinition("canvas", Node::buildNode<OffscreenCanvasNode>) - .extendDefinition(CanvasNode::createDefinition()) + TypeDefinition def = TypeDefinition("canvas", "canvasbase", + ExportedObject::buildObject<OffscreenCanvasNode>) .addArg(Arg<bool>("handleevents", false, false, offsetof(OffscreenCanvasNode, m_bHandleEvents))) .addArg(Arg<int>("multisamplesamples", 1, false, @@ -42,6 +42,7 @@ NodeDefinition OffscreenCanvasNode::createDefinition() offsetof(OffscreenCanvasNode, m_bMipmap))) .addArg(Arg<bool>("autorender", true, false, offsetof(OffscreenCanvasNode, m_bAutoRender))); + TypeRegistry::get()->registerType(def); } OffscreenCanvasNode::OffscreenCanvasNode(const ArgList& args) diff --git a/src/player/OffscreenCanvasNode.h b/src/player/OffscreenCanvasNode.h index 47e1ed7..9d2e850 100644 --- a/src/player/OffscreenCanvasNode.h +++ b/src/player/OffscreenCanvasNode.h @@ -1,6 +1,6 @@ // // libavg - Media Playback Engine. -// Copyright (C) 2003-2011 Ulrich von Zadow +// Copyright (C) 2003-2014 Ulrich von Zadow // // This library is free software; you can redistribute it and/or // modify it under the terms of the GNU Lesser General Public @@ -32,7 +32,7 @@ namespace avg { class AVG_API OffscreenCanvasNode : public CanvasNode { public: - static NodeDefinition createDefinition(); + static void registerType(); OffscreenCanvasNode(const ArgList& args); virtual ~OffscreenCanvasNode(); diff --git a/src/player/PanoImageNode.cpp b/src/player/PanoImageNode.cpp deleted file mode 100644 index 89157bb..0000000 --- a/src/player/PanoImageNode.cpp +++ /dev/null @@ -1,351 +0,0 @@ -// -// libavg - Media Playback Engine. -// Copyright (C) 2003-2011 Ulrich von Zadow -// -// This library is free software; you can redistribute it and/or -// modify it under the terms of the GNU Lesser General Public -// License as published by the Free Software Foundation; either -// version 2 of the License, or (at your option) any later version. -// -// This library 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 -// Lesser General Public License for more details. -// -// You should have received a copy of the GNU Lesser General Public -// License along with this library; if not, write to the Free Software -// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA -// -// Current versions can be found at www.libavg.de -// - -#include "PanoImageNode.h" -#include "NodeDefinition.h" - -#include "../base/MathHelper.h" -#include "../base/Logger.h" -#include "../base/ProfilingZone.h" -#include "../base/ScopeTimer.h" -#include "../base/Exception.h" -#include "../base/XMLHelper.h" - -#include "../graphics/OGLHelper.h" - -#include <iostream> -#include <sstream> -#include <math.h> - -using namespace std; - -const int TEX_WIDTH = 64; - -namespace avg { - -NodeDefinition PanoImageNode::createDefinition() -{ - return NodeDefinition("panoimage", Node::buildNode<PanoImageNode>) - .extendDefinition(AreaNode::createDefinition()) - .addArg(Arg<UTF8String>("href", "", false, offsetof(PanoImageNode, m_href))) - .addArg(Arg<double>("sensorwidth", 1.0, false, offsetof(PanoImageNode, m_SensorWidth))) - .addArg(Arg<double>("sensorheight", 1.0, false, offsetof(PanoImageNode, m_SensorHeight))) - .addArg(Arg<double>("focallength", 10.0, false, offsetof(PanoImageNode, m_FocalLength))) - .addArg(Arg<double>("rotation", -1.0, false, offsetof(PanoImageNode, m_Rotation))); -} - -PanoImageNode::PanoImageNode (const ArgList& Args) -{ - Args.setMembers(this); - m_pBmp = BitmapPtr(new Bitmap(IntPoint(1,1), R8G8B8)); - load(); -} - -PanoImageNode::~PanoImageNode () -{ - clearTextures(); -} - -void PanoImageNode::connectDisplay() -{ - AreaNode::connectDisplay(); - - setupTextures(); -} - -void PanoImageNode::disconnect(bool bKill) -{ - clearTextures(); - AreaNode::disconnect(bKill); -} - -static ProfilingZoneID PanoRenderProfilingZone("PanoImageNode::render"); - -void PanoImageNode::render(const DRect& Rect) -{ - ScopeTimer Timer(PanoRenderProfilingZone); - pushGLState(); - glproc::ActiveTexture(GL_TEXTURE0); - - gluLookAt(0, 0, 0, // Eye - 0, 0, -1, // Center - 0, 1, 0); // Up. - OGLErrorCheck(AVG_ERR_VIDEO_GENERAL, - "PanoImageNode::render: gluLookAt()"); - - glMatrixMode(GL_PROJECTION); - OGLErrorCheck(AVG_ERR_VIDEO_GENERAL, - "PanoImageNode::render: glMatrixMode(GL_PROJECTION)"); - glLoadIdentity(); - OGLErrorCheck(AVG_ERR_VIDEO_GENERAL, - "PanoImageNode::render: glLoadIdentity()"); - - calcProjection(); - gluPerspective(m_fovy*180/M_PI, m_aspect, 0.1, 2); - OGLErrorCheck(AVG_ERR_VIDEO_GENERAL, - "PanoImageNode::render: gluPerspective()"); - glMatrixMode(GL_MODELVIEW); - OGLErrorCheck(AVG_ERR_VIDEO_GENERAL, - "PanoImageNode::render: glMatrixMode(GL_MODELVIEW)"); - - glDisable (GL_CLIP_PLANE0); - glDisable (GL_CLIP_PLANE1); - glDisable (GL_CLIP_PLANE2); - glDisable (GL_CLIP_PLANE3); - OGLErrorCheck(AVG_ERR_VIDEO_GENERAL, - "PanoImageNode::render: glDisable(GL_CLIP_PLANEx)"); - DPoint Vpt = getSize(); - glViewport(0, 0, int(Vpt.x), int(Vpt.y)); - OGLErrorCheck(AVG_ERR_VIDEO_GENERAL, - "PanoImageNode::render: glViewport()"); - glColor4d(1.0, 1.0, 1.0, getEffectiveOpacity()); - OGLErrorCheck(AVG_ERR_VIDEO_GENERAL, - "PanoImageNode::render: glColor4d()"); -//glPolygonMode(GL_FRONT_AND_BACK, GL_LINE); - - double HorizOffset = m_Rotation+m_fovy*m_aspect/2; -// glutWireSphere(1, 20, 16); - for (unsigned int i=0; i<m_TileTextureIDs.size(); ++i) { - unsigned int TexID = m_TileTextureIDs[i]; - glBindTexture(GL_TEXTURE_2D, TexID); - OGLErrorCheck(AVG_ERR_VIDEO_GENERAL, - "PanoImageNode::render: glBindTexture()"); - double StartAngle=i*m_SliceAngle-HorizOffset; - double StartX = sin(StartAngle); - double StartZ = -cos(StartAngle); - double EndAngle; - if (i<m_TileTextureIDs.size()-1) { - EndAngle = (i+1)*m_SliceAngle-HorizOffset; - } else { - EndAngle = m_CylAngle-HorizOffset; - } - double EndX = sin(EndAngle); - double EndZ = -cos(EndAngle); - double TexPartUsed = double(m_pBmp->getSize().y)/m_TexHeight; - glBegin(GL_QUADS); - glTexCoord2d(0.0, 0.0); - glVertex3d(StartX, m_CylHeight, StartZ); - glTexCoord2d(0.0, TexPartUsed); - glVertex3d(StartX, -m_CylHeight, StartZ); - glTexCoord2d(1.0, TexPartUsed); - glVertex3d(EndX, -m_CylHeight, EndZ); - glTexCoord2d(1.0, 0.0); - glVertex3d(EndX, m_CylHeight, EndZ); - glEnd(); - OGLErrorCheck(AVG_ERR_VIDEO_GENERAL, - "PanoImageNode::render: glEnd()"); - } - - popGLState(); -} - -double PanoImageNode::getScreenPosFromAngle(double Angle) const -{ - double HorizOffsetAngle = Angle-m_Rotation-m_fovy*m_aspect/2; - double PixelDistFromCenter = m_FocalLength*tan(HorizOffsetAngle)/m_SensorWidth - *getSize().x; - return PixelDistFromCenter+getSize().x/2; -} - -double PanoImageNode::getScreenPosFromPanoPos(int PanoPos) const -{ - double AnglePerPixel = m_CylAngle*1/double(m_pBmp->getSize().x); - return getScreenPosFromAngle(AnglePerPixel*PanoPos); -} - -const UTF8String& PanoImageNode::getHRef() const -{ - return m_href; -} - -void PanoImageNode::setHRef(const UTF8String& href) -{ - m_href = href; - load(); - if (getState() == NS_CANRENDER) { - setupTextures(); - } -} - -double PanoImageNode::getSensorWidth () const -{ - return m_SensorWidth; -} - -void PanoImageNode::setSensorWidth (double sensorWidth) -{ - m_SensorWidth = sensorWidth; -} - -double PanoImageNode::getSensorHeight () const -{ - return m_SensorHeight; -} - -void PanoImageNode::setSensorHeight (double sensorHeight) -{ - m_SensorHeight = sensorHeight; -} - -double PanoImageNode::getFocalLength () const -{ - return m_FocalLength; -} - -void PanoImageNode::setFocalLength (double focalLength) -{ - m_FocalLength = focalLength; -} - -double PanoImageNode::getRotation () const -{ - return m_Rotation; -} - -void PanoImageNode::setRotation (double rotation) -{ - m_Rotation = rotation; -} - -double PanoImageNode::getMaxRotation () const -{ - return m_MaxRotation; -} - -void PanoImageNode::calcProjection() -{ - // Takes SensorWidth, SensorHeight and FocalLength and calculates - // loads of derived values needed for projection. - m_fovy = 2*atan((m_SensorHeight/2)/m_FocalLength); - m_aspect = m_SensorWidth/m_SensorHeight; - m_CylHeight = tan(m_fovy)/2; - m_CylAngle = m_fovy*m_pBmp->getSize().x/m_pBmp->getSize().y; - m_SliceAngle = m_CylAngle*TEX_WIDTH/double(m_pBmp->getSize().x); - m_MaxRotation = m_CylAngle-m_fovy*m_aspect; -} - -DPoint PanoImageNode::getPreferredMediaSize() -{ - double SensorAspect = m_SensorWidth/m_SensorHeight; - double Width = m_pBmp->getSize().y*SensorAspect; - return DPoint(Width, m_pBmp->getSize().y); -} - -void PanoImageNode::load() -{ - m_Filename = m_href; - AVG_TRACE(Logger::MEMORY, "Loading " << m_Filename); - if (m_Filename != "") { - initFilename(m_Filename); - try { - - m_pBmp = BitmapPtr(new Bitmap(m_Filename)); - } catch (Exception & ex) { - AVG_TRACE(Logger::ERROR, ex.getStr()); - } - } - - calcProjection(); - if (m_Rotation == -1) { - m_Rotation = m_MaxRotation/2; - } -} - -void PanoImageNode::setupTextures() -{ - if (!m_TileTextureIDs.empty()) { - clearTextures(); - } - m_TexHeight = nextpow2(m_pBmp->getSize().y); - int NumTextures = int(ceil(double(m_pBmp->getSize().x)/TEX_WIDTH)); - glproc::ActiveTexture(GL_TEXTURE0); - OGLErrorCheck(AVG_ERR_VIDEO_GENERAL, - "PanoImageNode::setupTextures: glproc::ActiveTexture(GL_TEXTURE0);"); - glPixelStorei(GL_UNPACK_ALIGNMENT, 1); - OGLErrorCheck(AVG_ERR_VIDEO_GENERAL, - "PanoImageNode::setupTextures: glPixelStorei(GL_UNPACK_ALIGNMENT)"); - glPixelStorei(GL_UNPACK_ROW_LENGTH, m_pBmp->getSize().x); - OGLErrorCheck(AVG_ERR_VIDEO_GENERAL, - "PanoImageNode::setupTextures: glPixelStorei(GL_UNPACK_ROW_LENGTH)"); - glEnable(GL_TEXTURE_2D); - OGLErrorCheck(AVG_ERR_VIDEO_GENERAL, - "PanoImageNode::setupTextures: glEnable(GL_TEXTURE_2D);"); - for (int i=0; i<NumTextures; i++) { - BitmapPtr pRegion; - if (i != NumTextures-1) { - pRegion = BitmapPtr(new Bitmap(*m_pBmp, - IntRect(i*TEX_WIDTH, 0, (i+1)*TEX_WIDTH, m_pBmp->getSize().y))); - } else { - // The last column isn't necessarily as wide as the others. - pRegion = BitmapPtr(new Bitmap(*m_pBmp, - IntRect(i*TEX_WIDTH, 0, - m_pBmp->getSize().x, m_pBmp->getSize().y))); - } - - unsigned int TexID; - glGenTextures(1, &TexID); - OGLErrorCheck(AVG_ERR_VIDEO_GENERAL, - "PanoImageNode::setupTextures: glGenTextures()"); - m_TileTextureIDs.push_back(TexID); - glBindTexture(GL_TEXTURE_2D, TexID); - OGLErrorCheck(AVG_ERR_VIDEO_GENERAL, - "PanoImageNode::setupTextures: glBindTexture()"); - - glTexParameteri(GL_TEXTURE_2D, - GL_TEXTURE_MIN_FILTER, GL_LINEAR); - glTexParameteri(GL_TEXTURE_2D, - GL_TEXTURE_MAG_FILTER, GL_LINEAR); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); - OGLErrorCheck(AVG_ERR_VIDEO_GENERAL, - "PanoImageNode::setupTextures: glTexParameteri()"); - - int DestMode; - if (pRegion->getPixelFormat() == R8G8B8X8) { - DestMode = GL_RGB; - } else { - DestMode = GL_RGBA; - } - glTexImage2D(GL_TEXTURE_2D, 0, - DestMode, TEX_WIDTH, m_TexHeight, 0, - GL_RGBA, GL_UNSIGNED_BYTE, 0); - OGLErrorCheck(AVG_ERR_VIDEO_GENERAL, - "PanoImageNode::setupTextures: glTexImage2D()"); - unsigned char * pStartPos = pRegion->getPixels(); - glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, - pRegion->getSize().x, pRegion->getSize().y, - GL_RGBA, GL_UNSIGNED_BYTE, pStartPos); - OGLErrorCheck(AVG_ERR_VIDEO_GENERAL, - "PanoImageNode::setupTextures: glTexSubImage2D()"); - } - glPixelStorei(GL_UNPACK_ROW_LENGTH, 0); -} - -void PanoImageNode::clearTextures() -{ - for (unsigned int i=0; i<m_TileTextureIDs.size(); ++i) { - unsigned int TexID = m_TileTextureIDs[i]; - glDeleteTextures(1, &TexID); - } - m_TileTextureIDs.clear(); -} - -} diff --git a/src/player/PanoImageNode.h b/src/player/PanoImageNode.h deleted file mode 100644 index 916d2f2..0000000 --- a/src/player/PanoImageNode.h +++ /dev/null @@ -1,95 +0,0 @@ -// -// libavg - Media Playback Engine. -// Copyright (C) 2003-2011 Ulrich von Zadow -// -// This library is free software; you can redistribute it and/or -// modify it under the terms of the GNU Lesser General Public -// License as published by the Free Software Foundation; either -// version 2 of the License, or (at your option) any later version. -// -// This library 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 -// Lesser General Public License for more details. -// -// You should have received a copy of the GNU Lesser General Public -// License along with this library; if not, write to the Free Software -// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA -// -// Current versions can be found at www.libavg.de -// - -#ifndef _PanoImageNode_H_ -#define _PanoImageNode_H_ - -#include "../api.h" -#include "../avgconfigwrapper.h" - -#include "AreaNode.h" -#include "../base/UTF8String.h" -#include "../graphics/Bitmap.h" - -#include <string> -#include <vector> - -namespace avg { - -class AVG_API PanoImageNode: public AreaNode -{ - public: - static NodeDefinition createDefinition(); - - PanoImageNode(const ArgList& Args); - virtual ~PanoImageNode(); - - virtual void connectDisplay(); - virtual void disconnect(bool bKill); - virtual void render(const DRect& Rect); - - double getScreenPosFromPanoPos(int PanoPos) const; - double getScreenPosFromAngle(double Angle) const; - const UTF8String& getHRef() const; - void setHRef(const UTF8String& href); - double getSensorWidth() const; - void setSensorWidth(double sensorWidth); - double getSensorHeight() const; - void setSensorHeight(double sensorHeight); - double getFocalLength() const; - void setFocalLength(double focalLength); - double getRotation() const; - void setRotation(double rotation); - double getMaxRotation() const; - - protected: - virtual DPoint getPreferredMediaSize(); - - private: - void load(); - void calcProjection(); - void setupTextures(); - void clearTextures(); - - UTF8String m_href; - std::string m_Filename; - double m_SensorWidth; - double m_SensorHeight; - double m_FocalLength; - BitmapPtr m_pBmp; - int m_TexHeight; - std::vector<unsigned int> m_TileTextureIDs; - - // Derived values calculated in calcProjection - double m_fovy; // Vertical field of view - double m_aspect; // Sensor aspect ratio - double m_CylHeight; - double m_CylAngle; // Total angle covered by panorama - double m_SliceAngle; // Angle per slice - double m_MaxRotation; // Maximum rotation angle (=Total angle - visible area) - - double m_Rotation; -}; - -} - -#endif //_PanoImageNode_H_ - diff --git a/src/player/Player.cpp b/src/player/Player.cpp index 086f168..77f27d0 100644 --- a/src/player/Player.cpp +++ b/src/player/Player.cpp @@ -1,6 +1,6 @@ // // libavg - Media Playback Engine. -// Copyright (C) 2003-2011 Ulrich von Zadow +// Copyright (C) 2003-2014 Ulrich von Zadow // // This library is free software; you can redistribute it and/or // modify it under the terms of the GNU Lesser General Public @@ -29,7 +29,6 @@ #include "VideoNode.h" #include "CameraNode.h" #include "ImageNode.h" -#include "PanoImageNode.h" #include "SoundNode.h" #include "LineNode.h" #include "RectNode.h" @@ -38,7 +37,7 @@ #include "PolygonNode.h" #include "CircleNode.h" #include "MeshNode.h" -#include "NodeDefinition.h" +#include "FontStyle.h" #include "PluginManager.h" #include "TextEngine.h" #include "TestHelper.h" @@ -48,6 +47,7 @@ #include "SDLDisplayEngine.h" #include "MultitouchInputDevice.h" #include "TUIOInputDevice.h" +#include "OGLSurface.h" #ifdef __APPLE__ #include "AppleTrackpadInputDevice.h" #endif @@ -64,6 +64,8 @@ #include "KeyEvent.h" #include "MouseEvent.h" #include "EventDispatcher.h" +#include "PublisherDefinition.h" +#include "BitmapManager.h" #include "../base/FileHelper.h" #include "../base/StringHelper.h" @@ -73,13 +75,16 @@ #include "../base/ConfigMgr.h" #include "../base/XMLHelper.h" #include "../base/ScopeTimer.h" -#include "../base/MathHelper.h" +#include "../base/WorkerThread.h" +#include "../base/DAG.h" -#include "../graphics/BitmapManager.h" +#include "../graphics/BitmapLoader.h" +#include "../graphics/ShaderRegistry.h" +#include "../graphics/Display.h" #include "../imaging/Camera.h" -#include "../audio/SDLAudioEngine.h" +#include "../audio/AudioEngine.h" #include <libxml/xmlmemory.h> @@ -94,6 +99,9 @@ #include <fenv.h> #endif +#include <glib-object.h> +#include <typeinfo> + using namespace std; using namespace boost; @@ -102,23 +110,27 @@ namespace avg { Player * Player::s_pPlayer=0; Player::Player() - : m_pDisplayEngine(), + : Publisher("Player"), + m_pDisplayEngine(), + m_bDisplayEngineBroken(false), + m_bIsTraversingTree(false), m_pMultitouchInputDevice(), m_bInHandleTimers(false), m_bCurrentTimeoutDeleted(false), + m_bKeepWindowOpen(false), m_bStopOnEscape(true), m_bIsPlaying(false), m_bFakeFPS(false), m_FakeFPS(0), m_FrameTime(0), m_Volume(1), - m_dtd(0), m_bPythonAvailable(true), - m_pLastMouseEvent(new MouseEvent(Event::CURSORMOTION, false, false, false, - IntPoint(-1, -1), MouseEvent::NO_BUTTON, DPoint(-1, -1), 0)), - m_EventHookPyFunc(Py_None) + m_pLastMouseEvent(new MouseEvent(Event::CURSOR_MOTION, false, false, false, + IntPoint(-1, -1), MouseEvent::NO_BUTTON, glm::vec2(-1, -1), 0)), + m_EventHookPyFunc(Py_None), + m_bMouseEnabled(true) { -string sDummy; + string sDummy; #ifdef _WIN32 if (getEnv("AVG_WIN_CRASH_SILENTLY", sDummy)) { DWORD dwMode = SetErrorMode(SEM_NOGPFAULTERRORBOX); @@ -129,31 +141,42 @@ string sDummy; // Turning this on causes fp exceptions in the linux nvidia drivers. // feenableexcept(FE_DIVBYZERO | FE_INVALID | FE_OVERFLOW); #endif + setAffinityMask(true); + if (s_pPlayer) { throw Exception(AVG_ERR_UNKNOWN, "Player has already been instantiated."); } - ThreadProfilerPtr pProfiler = ThreadProfiler::get(); + ThreadProfiler* pProfiler = ThreadProfiler::get(); pProfiler->setName("main"); + + SDLDisplayEngine::initSDL(); initConfig(); - // Register all node types - registerNodeType(AVGNode::createDefinition()); - registerNodeType(OffscreenCanvasNode::createDefinition()); - registerNodeType(CanvasNode::createDefinition()); - registerNodeType(DivNode::createDefinition()); - registerNodeType(ImageNode::createDefinition()); - registerNodeType(WordsNode::createDefinition()); - registerNodeType(VideoNode::createDefinition()); - registerNodeType(CameraNode::createDefinition()); - registerNodeType(PanoImageNode::createDefinition()); - registerNodeType(SoundNode::createDefinition()); - registerNodeType(LineNode::createDefinition()); - registerNodeType(RectNode::createDefinition()); - registerNodeType(CurveNode::createDefinition()); - registerNodeType(PolyLineNode::createDefinition()); - registerNodeType(PolygonNode::createDefinition()); - registerNodeType(CircleNode::createDefinition()); - registerNodeType(MeshNode::createDefinition()); + FontStyle::registerType(); + Node::registerType(); + AreaNode::registerType(); + RasterNode::registerType(); + VectorNode::registerType(); + FilledVectorNode::registerType(); + + DivNode::registerType(); + CanvasNode::registerType(); + OffscreenCanvasNode::registerType(); + AVGNode::registerType(); + ImageNode::registerType(); + WordsNode::registerType(); + VideoNode::registerType(); + CameraNode::registerType(); + SoundNode::registerType(); + LineNode::registerType(); + RectNode::registerType(); + CurveNode::registerType(); + PolyLineNode::registerType(); + PolygonNode::registerType(); + CircleNode::registerType(); + MeshNode::registerType(); + + Contact::registerType(); m_pTestHelper = TestHelperPtr(new TestHelper()); @@ -173,9 +196,11 @@ void deletePlayer() Player::~Player() { - if (m_dtd) { - xmlFreeDtd(m_dtd); + m_pMainCanvas = MainCanvasPtr(); + if (m_pDisplayEngine) { + m_pDisplayEngine->teardown(); } + SDLDisplayEngine::quitSDL(); } Player* Player::get() @@ -225,19 +250,41 @@ void Player::setWindowPos(int x, int y) m_DP.m_Pos.y = y; } -void Player::setOGLOptions(bool bUsePOTTextures, bool bUseShaders, - bool bUsePixelBuffers, int multiSampleSamples) +void Player::setWindowTitle(const string& sTitle) +{ + m_pDisplayEngine->setWindowTitle(sTitle); +} + +void Player::useGLES(bool bGLES) +{ + errorIfPlaying("Player.useGLES"); + m_GLConfig.m_bGLES = bGLES; +#ifdef AVG_ENABLE_EGL + m_GLConfig.m_bGLES = true; +#endif + BitmapLoader::init(!m_GLConfig.m_bGLES); +} + +void Player::setOGLOptions(bool bUsePOTTextures, bool bUsePixelBuffers, + int multiSampleSamples, GLConfig::ShaderUsage shaderUsage, + bool bUseDebugContext) { errorIfPlaying("Player.setOGLOptions"); m_GLConfig.m_bUsePOTTextures = bUsePOTTextures; - m_GLConfig.m_bUseShaders = bUseShaders; m_GLConfig.m_bUsePixelBuffers = bUsePixelBuffers; - m_GLConfig.m_MultiSampleSamples = multiSampleSamples; + setMultiSampleSamples(multiSampleSamples); + m_GLConfig.m_ShaderUsage = shaderUsage; + m_GLConfig.m_bUseDebugContext = bUseDebugContext; } void Player::setMultiSampleSamples(int multiSampleSamples) { errorIfPlaying("Player.setMultiSampleSamples"); + if (multiSampleSamples < 1) { + throw Exception(AVG_ERR_OUT_OF_RANGE, + "MultiSampleSamples must be 1 or greater (was " + + toString(multiSampleSamples) + ")."); + } m_GLConfig.m_MultiSampleSamples = multiSampleSamples; } @@ -248,40 +295,40 @@ void Player::setAudioOptions(int samplerate, int channels) m_AP.m_Channels = channels; } -DPoint Player::getScreenResolution() +void Player::enableGLErrorChecks(bool bEnable) +{ + GLContext::enableErrorChecks(bEnable); +} + +glm::vec2 Player::getScreenResolution() { - return DPoint(safeGetDisplayEngine()->getScreenResolution()); + return glm::vec2(Display::get()->getScreenResolution()); } -double Player::getPixelsPerMM() +float Player::getPixelsPerMM() { - return safeGetDisplayEngine()->getPixelsPerMM(); + return Display::get()->getPixelsPerMM(); } -DPoint Player::getPhysicalScreenDimensions() +glm::vec2 Player::getPhysicalScreenDimensions() { - return safeGetDisplayEngine()->getPhysicalScreenDimensions(); + return Display::get()->getPhysicalScreenDimensions(); } -void Player::assumePixelsPerMM(double ppmm) +void Player::assumePixelsPerMM(float ppmm) { - safeGetDisplayEngine()->assumePixelsPerMM(ppmm); + Display::get()->assumePixelsPerMM(ppmm); } CanvasPtr Player::loadFile(const string& sFilename) { errorIfPlaying("Player.loadFile"); NodePtr pNode = loadMainNodeFromFile(sFilename); - m_pEventDispatcher = EventDispatcherPtr(new EventDispatcher(this)); if (m_pMainCanvas) { - cleanup(); + cleanup(false); } - m_pMainCanvas = MainCanvasPtr(new MainCanvas(this)); - m_pMainCanvas->setRoot(pNode); - m_DP.m_Size = m_pMainCanvas->getSize(); - - registerFrameEndListener(BitmapManager::get()); + initMainCanvas(pNode); return m_pMainCanvas; } @@ -290,16 +337,11 @@ CanvasPtr Player::loadString(const string& sAVG) { errorIfPlaying("Player.loadString"); if (m_pMainCanvas) { - cleanup(); + cleanup(false); } NodePtr pNode = loadMainNodeFromString(sAVG); - m_pEventDispatcher = EventDispatcherPtr(new EventDispatcher(this)); - m_pMainCanvas = MainCanvasPtr(new MainCanvas(this)); - m_pMainCanvas->setRoot(pNode); - m_DP.m_Size = m_pMainCanvas->getSize(); - - registerFrameEndListener(BitmapManager::get()); + initMainCanvas(pNode); return m_pMainCanvas; } @@ -316,26 +358,20 @@ OffscreenCanvasPtr Player::loadCanvasString(const string& sAVG) return registerOffscreenCanvas(pNode); } -CanvasPtr Player::createMainCanvas(const boost::python::dict& params) +CanvasPtr Player::createMainCanvas(const py::dict& params) { errorIfPlaying("Player.createMainCanvas"); if (m_pMainCanvas) { - cleanup(); + cleanup(false); } NodePtr pNode = createNode("avg", params); - - m_pEventDispatcher = EventDispatcherPtr(new EventDispatcher(this)); - m_pMainCanvas = MainCanvasPtr(new MainCanvas(this)); - m_pMainCanvas->setRoot(pNode); - m_DP.m_Size = m_pMainCanvas->getSize(); - - registerFrameEndListener(BitmapManager::get()); + initMainCanvas(pNode); return m_pMainCanvas; } -OffscreenCanvasPtr Player::createCanvas(const boost::python::dict& params) +OffscreenCanvasPtr Player::createCanvas(const py::dict& params) { NodePtr pNode = createNode("canvas", params); return registerOffscreenCanvas(pNode); @@ -351,7 +387,7 @@ void Player::deleteCanvas(const string& sID) string("deleteCanvas: Canvas with id ")+sID +" is still referenced.")); } - (*it)->stopPlayback(); + (*it)->stopPlayback(false); m_pCanvases.erase(it); return; } @@ -376,105 +412,75 @@ OffscreenCanvasPtr Player::getCanvas(const string& sID) const } } -void Player::newCanvasDependency(const OffscreenCanvasPtr pCanvas) +void Player::newCanvasDependency() { - OffscreenCanvasPtr pNewCanvas; - unsigned i; - for (i = 0; i < m_pCanvases.size(); ++i) { - if (pCanvas == m_pCanvases[i]) { - pNewCanvas = m_pCanvases[i]; - m_pCanvases.erase(m_pCanvases.begin()+i); - continue; + DAG dag; + for (unsigned i = 0; i < m_pCanvases.size(); ++i) { + set<long> dependentCanvasSet; + OffscreenCanvasPtr pCanvas = m_pCanvases[i]; + const vector<CanvasPtr>& pDependents = pCanvas->getDependentCanvases(); + for (unsigned j = 0; j < pDependents.size(); ++j) { + dependentCanvasSet.insert(pDependents[j]->getHash()); } + dag.addNode(pCanvas->getHash(), dependentCanvasSet); } - AVG_ASSERT(pNewCanvas); - bool bFound = false; - for (i = 0; i < m_pCanvases.size(); ++i) { - if (pNewCanvas->hasDependentCanvas(m_pCanvases[i])) { - bFound = true; - break; - } + dag.addNode(m_pMainCanvas->getHash(), set<long>()); + + vector<long> sortedCanvasIDs; + try { + dag.sort(sortedCanvasIDs); + } catch (Exception&) { + throw Exception(AVG_ERR_INVALID_ARGS, "Circular dependency between canvases."); } - if (bFound) { - for (unsigned j = i; j < m_pCanvases.size(); ++j) { - if (m_pCanvases[j]->hasDependentCanvas(pNewCanvas)) { - throw Exception(AVG_ERR_INVALID_ARGS, - "Circular dependency between canvases."); + + vector<OffscreenCanvasPtr> pTempCanvases = m_pCanvases; + m_pCanvases.clear(); + for (unsigned i = 0; i < sortedCanvasIDs.size(); ++i) { + long canvasID = sortedCanvasIDs[i]; + for (unsigned j = 0; j < pTempCanvases.size(); ++j) { + OffscreenCanvasPtr pCandidateCanvas = pTempCanvases[j]; + if (pCandidateCanvas->getHash() == canvasID) { + m_pCanvases.push_back(pCandidateCanvas); + break; } } - m_pCanvases.insert(m_pCanvases.begin()+i, pNewCanvas); - } else { - AVG_ASSERT(pNewCanvas->hasDependentCanvas(m_pMainCanvas)); - m_pCanvases.push_back(pNewCanvas); - } -/* - for (unsigned k=0; k<m_pCanvases.size(); ++k) { - m_pCanvases[k]->dump(); } -*/ } NodePtr Player::loadMainNodeFromFile(const string& sFilename) { - string RealFilename; - try { - AVG_TRACE(Logger::MEMORY, std::string("Player::loadFile(") + sFilename + ")"); - - // When loading an avg file, assets are loaded from a directory relative - // to the file. - char szBuf[1024]; - char * pBuf = getcwd(szBuf, 1024); - if (sFilename[0] == '/') { - RealFilename = sFilename; - } else { - m_CurDirName = string(pBuf)+"/"; - RealFilename = m_CurDirName+sFilename; - } - m_CurDirName = RealFilename.substr(0, RealFilename.rfind('/')+1); - - string sAVG; - readWholeFile(RealFilename, sAVG); - NodePtr pNode = internalLoad(sAVG); + string sRealFilename; + AVG_TRACE(Logger::category::MEMORY, Logger::severity::INFO, + "Player::loadFile(" << sFilename << ")"); - // Reset the directory to load assets from to the current dir. + // When loading an avg file, assets are loaded from a directory relative + // to the file. + char szBuf[1024]; + char * pBuf = getcwd(szBuf, 1024); + if (sFilename[0] == '/') { + sRealFilename = sFilename; + } else { m_CurDirName = string(pBuf)+"/"; - return pNode; - } catch (Exception& ex) { - switch (ex.getCode()) { - case AVG_ERR_XML_PARSE: - throw (Exception(AVG_ERR_XML_PARSE, - string("Error parsing xml document ")+RealFilename)); - break; - case AVG_ERR_XML_VALID: - throw (Exception(AVG_ERR_XML_VALID, - RealFilename + " does not validate.")); - break; - default: - throw; - } + sRealFilename = m_CurDirName+sFilename; } + m_CurDirName = sRealFilename.substr(0, sRealFilename.rfind('/')+1); + + string sAVG; + readWholeFile(sRealFilename, sAVG); + NodePtr pNode = internalLoad(sAVG, sRealFilename); + + // Reset the directory to load assets from to the current dir. + m_CurDirName = string(pBuf)+"/"; + return pNode; } NodePtr Player::loadMainNodeFromString(const string& sAVG) { - try { - AVG_TRACE(Logger::MEMORY, "Player::loadString()"); + AVG_TRACE(Logger::category::MEMORY, Logger::severity::INFO, "Player::loadString()"); - string sEffectiveDoc = removeStartEndSpaces(sAVG); - NodePtr pNode = internalLoad(sEffectiveDoc); - return pNode; - } catch (Exception& ex) { - switch (ex.getCode()) { - case AVG_ERR_XML_PARSE: - throw Exception(AVG_ERR_XML_PARSE, "Error parsing xml string."); - break; - case AVG_ERR_XML_VALID: - throw Exception(AVG_ERR_XML_VALID, "Error validating xml string."); - break; - default: - throw; - } - } + string sEffectiveDoc = removeStartEndSpaces(sAVG); + NodePtr pNode = internalLoad(sEffectiveDoc, ""); + return pNode; } void Player::play() @@ -484,21 +490,24 @@ void Player::play() throw Exception(AVG_ERR_NO_NODE, "Play called, but no xml file loaded."); } initPlayback(); + notifySubscribers("PLAYBACK_START"); try { ThreadProfiler::get()->start(); doFrame(true); while (!m_bStopping) { doFrame(false); } + notifySubscribers("PLAYBACK_END"); } catch (...) { - cleanup(); + cleanup(true); + m_bDisplayEngineBroken = true; throw; } - cleanup(); - AVG_TRACE(Logger::PLAYER, "Playback ended."); + cleanup(false); + AVG_TRACE(Logger::category::PLAYER, Logger::severity::INFO, "Playback ended."); } catch (Exception& ex) { m_bIsPlaying = false; - AVG_TRACE(Logger::ERROR, ex.getStr()); + AVG_LOG_ERROR(ex.getStr()); throw; } } @@ -508,7 +517,7 @@ void Player::stop() if (m_bIsPlaying) { m_bStopping = true; } else { - cleanup(); + cleanup(false); } } @@ -517,11 +526,11 @@ bool Player::isStopping() return m_bStopping; } -void Player::initPlayback() +void Player::initPlayback(const std::string& sShaderPath) { m_bIsPlaying = true; - AVG_TRACE(Logger::PLAYER, "Playback started."); - initGraphics(); + AVG_TRACE(Logger::category::PLAYER, Logger::severity::INFO, "Playback started."); + initGraphics(sShaderPath); initAudio(); try { for (unsigned i = 0; i < m_pCanvases.size(); ++i) { @@ -529,7 +538,8 @@ void Player::initPlayback() } m_pMainCanvas->initPlayback(m_pDisplayEngine); } catch (Exception&) { - cleanup(); + cleanup(true); + m_bDisplayEngineBroken = true; throw; } m_pEventDispatcher->addInputDevice( @@ -537,6 +547,7 @@ void Player::initPlayback() m_pEventDispatcher->addInputDevice(m_pTestHelper); m_pDisplayEngine->initRender(); + Display::get()->rereadScreenResolution(); m_bStopping = false; if (m_pMultitouchInputDevice) { m_pMultitouchInputDevice->start(); @@ -551,27 +562,25 @@ bool Player::isPlaying() return m_bIsPlaying; } -void Player::setFramerate(double rate) +void Player::setFramerate(float rate) { if (m_bIsPlaying) { m_pDisplayEngine->setFramerate(rate); - } else { - m_DP.m_Framerate = rate; - m_DP.m_VBRate = 0; } + m_DP.m_Framerate = rate; + m_DP.m_VBRate = 0; } void Player::setVBlankFramerate(int rate) { if (m_bIsPlaying) { m_pDisplayEngine->setVBlankRate(rate); - } else { - m_DP.m_Framerate = 0; - m_DP.m_VBRate = rate; } + m_DP.m_Framerate = 0; + m_DP.m_VBRate = rate; } -double Player::getEffectiveFramerate() +float Player::getEffectiveFramerate() { if (m_bIsPlaying) { if (m_bFakeFPS) { @@ -589,7 +598,7 @@ TestHelper * Player::getTestHelper() return m_pTestHelper.get(); } -void Player::setFakeFPS(double fps) +void Player::setFakeFPS(float fps) { if (fabs(fps + 1.0) < 0.0001) { // fps = -1 @@ -599,8 +608,8 @@ void Player::setFakeFPS(double fps) m_FakeFPS = fps; } - if (SDLAudioEngine::get()) { - SDLAudioEngine::get()->setAudioEnabled(!m_bFakeFPS); + if (AudioEngine::get()) { + AudioEngine::get()->setAudioEnabled(!m_bFakeFPS); } } @@ -618,39 +627,24 @@ long long Player::getFrameTime() return m_FrameTime; } -double Player::getFrameDuration() +float Player::getFrameDuration() { if (!m_bIsPlaying) { throw Exception(AVG_ERR_UNSUPPORTED, "Must call Player.play() before getFrameDuration()."); } if (m_bFakeFPS) { - return 1000.0/m_FakeFPS; + return 1000.0f/m_FakeFPS; } else { - double framerate = m_pDisplayEngine->getEffectiveFramerate(); + float framerate = m_pDisplayEngine->getEffectiveFramerate(); if (framerate > 0) { - return 1000./framerate; + return 1000.f/framerate; } else { return 0; } } } -TrackerInputDevice * Player::addTracker() -{ - if (!m_pMainCanvas) { - throw Exception(AVG_ERR_UNSUPPORTED, - "You must use loadFile() before addTracker()."); - } - m_pMultitouchInputDevice = IInputDevicePtr(new TrackerInputDevice()); - addInputDevice(m_pMultitouchInputDevice); - if (m_bIsPlaying) { - m_pMultitouchInputDevice->start(); - } - - return dynamic_cast<TrackerInputDevice*>(m_pMultitouchInputDevice.get()); -} - TrackerInputDevice * Player::getTracker() { TrackerInputDevice* pTracker = dynamic_cast<TrackerInputDevice*>( @@ -660,6 +654,10 @@ TrackerInputDevice * Player::getTracker() void Player::enableMultitouch() { + if (!m_bIsPlaying) { + throw Exception(AVG_ERR_UNSUPPORTED, + "Must call Player.play() before enableMultitouch()."); + } string sDriver; getEnv("AVG_MULTITOUCH_DRIVER", sDriver); @@ -671,7 +669,7 @@ void Player::enableMultitouch() #elif defined (AVG_ENABLE_MTDEV) sDriver = "LINUXMTDEV"; #else - AVG_TRACE(Logger::WARNING, "Valid values for AVG_MULTITOUCH_DRIVER are WIN7TOUCH, XINPUT, LINUXMTDEV, TRACKER, TUIO and APPLETRACKPAD."); + AVG_LOG_WARNING("Valid values for AVG_MULTITOUCH_DRIVER are WIN7TOUCH, XINPUT, LINUXMTDEV, TRACKER, TUIO and APPLETRACKPAD."); throw Exception(AVG_ERR_MT_INIT, "Multitouch support: No default driver available. Set AVG_MULTITOUCH_DRIVER."); #endif @@ -700,7 +698,7 @@ void Player::enableMultitouch() } else if (sDriver == "TRACKER") { m_pMultitouchInputDevice = IInputDevicePtr(new TrackerInputDevice); } else { - AVG_TRACE(Logger::WARNING, "Valid values for AVG_MULTITOUCH_DRIVER are WIN7TOUCH, XINPUT, LINUXMTDEV, TRACKER, TUIO and APPLETRACKPAD."); + AVG_LOG_WARNING("Valid values for AVG_MULTITOUCH_DRIVER are WIN7TOUCH, XINPUT, LINUXMTDEV, TRACKER, TUIO and APPLETRACKPAD."); throw Exception(AVG_ERR_UNSUPPORTED, string("Unsupported multitouch driver '")+ sDriver +"'."); } @@ -715,6 +713,15 @@ void Player::enableMultitouch() addInputDevice(m_pMultitouchInputDevice); } +void Player::enableMouse(bool enabled) +{ + m_bMouseEnabled = enabled; + + if (m_pEventDispatcher) { + m_pEventDispatcher->enableMouse(enabled); + } +} + bool Player::isMultitouchAvailable() const { if (m_bIsPlaying) { @@ -729,15 +736,17 @@ void Player::setEventCapture(NodePtr pNode, int cursorID=MOUSECURSORID) { std::map<int, EventCaptureInfoPtr>::iterator it = m_EventCaptureInfoMap.find(cursorID); - if (it != m_EventCaptureInfoMap.end() && !(it->second->m_pNode.expired())) { + if (it != m_EventCaptureInfoMap.end()) { EventCaptureInfoPtr pCaptureInfo = it->second; - NodePtr pOldNode = pCaptureInfo->m_pNode.lock(); - if (pOldNode == pNode) { - pCaptureInfo->m_CaptureCount++; - } else { - throw Exception(AVG_ERR_INVALID_CAPTURE, "setEventCapture called for '" - + pNode->getID() + "', but cursor already captured by '" - + pOldNode->getID() + "'."); + NodePtr pOldNode = pCaptureInfo->m_pNode; + if (pOldNode->getState() != Node::NS_UNCONNECTED) { + if (pOldNode == pNode) { + pCaptureInfo->m_CaptureCount++; + } else { + throw Exception(AVG_ERR_INVALID_CAPTURE, "setEventCapture called for '" + + pNode->getID() + "', but cursor already captured by '" + + pOldNode->getID() + "'."); + } } } else { m_EventCaptureInfoMap[cursorID] = EventCaptureInfoPtr( @@ -749,7 +758,9 @@ void Player::releaseEventCapture(int cursorID) { std::map<int, EventCaptureInfoPtr>::iterator it = m_EventCaptureInfoMap.find(cursorID); - if (it == m_EventCaptureInfoMap.end() || (it->second->m_pNode.expired()) ) { + if (it == m_EventCaptureInfoMap.end() || + (it->second->m_pNode->getState() == Node::NS_UNCONNECTED)) + { throw Exception(AVG_ERR_INVALID_CAPTURE, "releaseEventCapture called, but cursor not captured."); } else { @@ -767,38 +778,40 @@ bool Player::isCaptured(int cursorID) return (it != m_EventCaptureInfoMap.end()); } -int Player::setInterval(int time, PyObject * pyfunc) +void Player::removeDeadEventCaptures() { - Timeout* pTimeout = new Timeout(time, pyfunc, true, getFrameTime()); - if (m_bInHandleTimers) { - m_NewTimeouts.push_back(pTimeout); - } else { - addTimeout(pTimeout); + std::map<int, EventCaptureInfoPtr>::iterator it; + for (it = m_EventCaptureInfoMap.begin(); it != m_EventCaptureInfoMap.end();) { + std::map<int, EventCaptureInfoPtr>::iterator lastIt = it; + it++; + if (lastIt->second->m_pNode->getState() == Node::NS_UNCONNECTED) { + m_EventCaptureInfoMap.erase(lastIt); + } } - return pTimeout->GetID(); +} + +int Player::setInterval(int time, PyObject * pyfunc) +{ + return internalSetTimeout(time, pyfunc, true); } int Player::setTimeout(int time, PyObject * pyfunc) { - Timeout* pTimeout = new Timeout(time, pyfunc, false, getFrameTime()); - if (m_bInHandleTimers) { - m_NewTimeouts.push_back(pTimeout); - } else { - addTimeout(pTimeout); - } - return pTimeout->GetID(); + return internalSetTimeout(time, pyfunc, false); } int Player::setOnFrameHandler(PyObject * pyfunc) { - return setInterval(0, pyfunc); + avgDeprecationWarning("1.8", "Player.setOnFrameHandler", + "Player.subscribe(Player.ON_FRAME)"); + return internalSetTimeout(0, pyfunc, true); } bool Player::clearInterval(int id) { vector<Timeout*>::iterator it; for (it = m_PendingTimeouts.begin(); it != m_PendingTimeouts.end(); it++) { - if (id == (*it)->GetID()) { + if (id == (*it)->getID()) { if (it == m_PendingTimeouts.begin() && m_bInHandleTimers) { m_bCurrentTimeoutDeleted = true; } @@ -808,7 +821,7 @@ bool Player::clearInterval(int id) } } for (it = m_NewTimeouts.begin(); it != m_NewTimeouts.end(); it++) { - if (id == (*it)->GetID()) { + if (id == (*it)->getID()) { delete *it; m_NewTimeouts.erase(it); return true; @@ -817,11 +830,26 @@ bool Player::clearInterval(int id) return false; } +void Player::callFromThread(PyObject * pyfunc) +{ + lock_guard lock(m_AsyncCallMutex); + Timeout* pTimeout = new Timeout(0, pyfunc, false, getFrameTime()); + m_AsyncCalls.push_back(pTimeout); +} + MouseEventPtr Player::getMouseState() const { return m_pLastMouseEvent; } +EventPtr Player::getCurrentEvent() const +{ + if (!m_pCurrentEvent) { + throw Exception(AVG_ERR_UNSUPPORTED, "No current event."); + } + return m_pCurrentEvent; +} + void Player::setMousePos(const IntPoint& pos) { m_pDisplayEngine->setMousePos(pos); @@ -838,6 +866,11 @@ BitmapPtr Player::screenshot() throw Exception(AVG_ERR_UNSUPPORTED, "Must call Player.play() before screenshot()."); } + if (GLContext::getMain()->isGLES()) { + // Some GLES implementations invalidate the buffer after eglSwapBuffers. + // The only way we can get at the contents at this point is to rerender them. + m_pMainCanvas->render(m_pDisplayEngine->getWindowSize(), false); + } return m_pDisplayEngine->screenshot(); } @@ -849,6 +882,11 @@ void Player::showCursor(bool bShow) m_DP.m_bShowCursor = bShow; } +bool Player::isCursorShown() +{ + return m_DP.m_bShowCursor; +} + void Player::setCursor(const Bitmap* pBmp, IntPoint hotSpot) { IntPoint size = pBmp->getSize(); @@ -924,14 +962,26 @@ std::string Player::getRootMediaDir() return sMediaDir; } -const NodeDefinition& Player::getNodeDef(const std::string& sType) +void Player::disablePython() { - return m_NodeRegistry.getNodeDef(sType); + m_bPythonAvailable = false; } -void Player::disablePython() +void Player::startTraversingTree() { - m_bPythonAvailable = false; + AVG_ASSERT(!m_bIsTraversingTree); + m_bIsTraversingTree = true; +} + +void Player::endTraversingTree() +{ + AVG_ASSERT(m_bIsTraversingTree); + m_bIsTraversingTree = false; +} + +bool Player::isTraversingTree() const +{ + return m_bIsTraversingTree; } void Player::registerFrameEndListener(IFrameEndListener* pListener) @@ -976,21 +1026,15 @@ void Player::unregisterPreRenderListener(IPreRenderListener* pListener) bool Player::handleEvent(EventPtr pEvent) { AVG_ASSERT(pEvent); - - PyObject * pEventHook = getEventHook(); - if (pEventHook != Py_None) { - // If the catchall returns true, stop processing the event - if (boost::python::call<bool>(pEventHook, pEvent)) { - return true; - } - } + EventPtr pLastEvent = m_pCurrentEvent; + m_pCurrentEvent = pEvent; if (MouseEventPtr pMouseEvent = boost::dynamic_pointer_cast<MouseEvent>(pEvent)) { m_pLastMouseEvent = pMouseEvent; } if (CursorEventPtr pCursorEvent = boost::dynamic_pointer_cast<CursorEvent>(pEvent)) { - if (pEvent->getType() == Event::CURSOROUT || - pEvent->getType() == Event::CURSOROVER) + if (pEvent->getType() == Event::CURSOR_OUT || + pEvent->getType() == Event::CURSOR_OVER) { pEvent->trace(); pCursorEvent->getNode()->handleEvent(pEvent); @@ -1001,8 +1045,18 @@ bool Player::handleEvent(EventPtr pEvent) else if (KeyEventPtr pKeyEvent = boost::dynamic_pointer_cast<KeyEvent>(pEvent)) { pEvent->trace(); + switch (pEvent->getType()) { + case Event::KEY_DOWN: + notifySubscribers("KEY_DOWN", pEvent); + break; + case Event::KEY_UP: + notifySubscribers("KEY_UP", pEvent); + break; + default: + AVG_ASSERT(false); + } getRootNode()->handleEvent(pKeyEvent); - if (getStopOnEscape() && pEvent->getType() == Event::KEYDOWN + if (getStopOnEscape() && pEvent->getType() == Event::KEY_DOWN && pKeyEvent->getKeyCode() == avg::key::KEY_ESCAPE) { stop(); @@ -1017,20 +1071,23 @@ bool Player::handleEvent(EventPtr pEvent) stop(); } } + m_pCurrentEvent = pLastEvent; return true; } static ProfilingZoneID MainProfilingZone("Player - Total frame time"); static ProfilingZoneID TimersProfilingZone("Player - handleTimers"); static ProfilingZoneID EventsProfilingZone("Dispatch events"); +static ProfilingZoneID MainCanvasProfilingZone("Main canvas rendering"); +static ProfilingZoneID OffscreenProfilingZone("Offscreen rendering"); void Player::doFrame(bool bFirstFrame) { { ScopeTimer Timer(MainProfilingZone); if (!bFirstFrame) { + m_NumFrames++; if (m_bFakeFPS) { - m_NumFrames++; m_FrameTime = (long long)((m_NumFrames*1000.0)/m_FakeFPS); } else { m_FrameTime = m_pDisplayEngine->getDisplayTime(); @@ -1043,12 +1100,18 @@ void Player::doFrame(bool bFirstFrame) ScopeTimer Timer(EventsProfilingZone); m_pEventDispatcher->dispatch(); sendFakeEvents(); + removeDeadEventCaptures(); } } for (unsigned i = 0; i < m_pCanvases.size(); ++i) { + ScopeTimer Timer(OffscreenProfilingZone); dispatchOffscreenRendering(m_pCanvases[i].get()); } - m_pMainCanvas->doFrame(m_bPythonAvailable); + { + ScopeTimer Timer(MainCanvasProfilingZone); + m_pMainCanvas->doFrame(m_bPythonAvailable); + } + GLContext::mandatoryCheckError("End of frame"); if (m_bPythonAvailable) { Py_BEGIN_ALLOW_THREADS; try { @@ -1062,11 +1125,10 @@ void Player::doFrame(bool bFirstFrame) endFrame(); } } - if (m_pDisplayEngine->wasFrameLate()) { - ThreadProfiler::get()->dumpFrame(); - } - ThreadProfiler::get()->reset(); + if (m_NumFrames == 5) { + ThreadProfiler::get()->restart(); + } } void Player::endFrame() @@ -1076,7 +1138,7 @@ void Player::endFrame() m_pDisplayEngine->checkJitter(); } -double Player::getFramerate() +float Player::getFramerate() { if (!m_pDisplayEngine) { return m_DP.m_Framerate; @@ -1084,32 +1146,37 @@ double Player::getFramerate() return m_pDisplayEngine->getFramerate(); } -double Player::getVideoRefreshRate() +float Player::getVideoRefreshRate() +{ + return Display::get()->getRefreshRate(); +} + +size_t Player::getVideoMemInstalled() { if (!m_pDisplayEngine) { - return 0; + throw Exception(AVG_ERR_UNSUPPORTED, + "Player.getVideoMemInstalled must be called after Player.play()."); } - return m_pDisplayEngine->getRefreshRate(); + return GLContext::getMain()->getVideoMemInstalled(); } -bool Player::isUsingShaders() +size_t Player::getVideoMemUsed() { if (!m_pDisplayEngine) { throw Exception(AVG_ERR_UNSUPPORTED, - "Player.isUsingShaders must be called after Player.play()."); + "Player.getVideoMemUsed must be called after Player.play()."); } - return GLContext::getCurrent()->isUsingShaders(); + return GLContext::getMain()->getVideoMemUsed(); } -void Player::setGamma(double red, double green, double blue) +void Player::setGamma(float red, float green, float blue) { if (m_pDisplayEngine) { m_pDisplayEngine->setGamma(red, green, blue); - } else { - m_DP.m_Gamma[0] = red; - m_DP.m_Gamma[1] = green; - m_DP.m_Gamma[2] = blue; } + m_DP.m_Gamma[0] = red; + m_DP.m_Gamma[1] = green; + m_DP.m_Gamma[2] = blue; } void Player::initConfig() @@ -1119,8 +1186,7 @@ void Player::initConfig() m_DP.m_BPP = atoi(pMgr->getOption("scr", "bpp")->c_str()); if (m_DP.m_BPP != 15 && m_DP.m_BPP != 16 && m_DP.m_BPP != 24 && m_DP.m_BPP != 32) { - AVG_TRACE(Logger::ERROR, - "BPP must be 15, 16, 24 or 32. Current value is " + AVG_LOG_ERROR("BPP must be 15, 16, 24 or 32. Current value is " << m_DP.m_BPP << ". Aborting." ); exit(-1); } @@ -1128,17 +1194,14 @@ void Player::initConfig() m_DP.m_WindowSize.x = atoi(pMgr->getOption("scr", "windowwidth")->c_str()); m_DP.m_WindowSize.y = atoi(pMgr->getOption("scr", "windowheight")->c_str()); - m_DP.m_DotsPerMM = atof(pMgr->getOption("scr", "dotspermm")->c_str()); if (m_DP.m_bFullscreen && (m_DP.m_WindowSize != IntPoint(0, 0))) { - AVG_TRACE(Logger::ERROR, - "Can't set fullscreen and window size at once. Aborting."); + AVG_LOG_ERROR("Can't set fullscreen and window size at once. Aborting."); exit(-1); } if (m_DP.m_WindowSize.x != 0 && m_DP.m_WindowSize.y != 0) { - AVG_TRACE(Logger::ERROR, "Can't set window width and height at once"); - AVG_TRACE(Logger::ERROR, - "(aspect ratio is determined by avg file). Aborting."); + AVG_LOG_ERROR("Can't set window width and height at once"); + AVG_LOG_ERROR("(aspect ratio is determined by avg file). Aborting."); exit(-1); } @@ -1147,90 +1210,111 @@ void Player::initConfig() m_AP.m_OutputBufferSamples = atoi(pMgr->getOption("aud", "outputbuffersamples")->c_str()); + m_GLConfig.m_bGLES = pMgr->getBoolOption("scr", "gles", false); m_GLConfig.m_bUsePOTTextures = pMgr->getBoolOption("scr", "usepow2textures", false); - m_GLConfig.m_bUseShaders = pMgr->getBoolOption("scr", "useshaders", true); m_GLConfig.m_bUsePixelBuffers = pMgr->getBoolOption("scr", "usepixelbuffers", true); - m_GLConfig.m_MultiSampleSamples = pMgr->getIntOption("scr", "multisamplesamples", 4); + int multiSampleSamples = pMgr->getIntOption("scr", "multisamplesamples", 8); + if (multiSampleSamples < 1) { + AVG_LOG_ERROR("multisamplesamples must be >= 1. Aborting") + exit(-1); + } + m_GLConfig.m_MultiSampleSamples = multiSampleSamples; + + string sShaderUsage; + pMgr->getStringOption("scr", "shaderusage", "auto", sShaderUsage); + if (sShaderUsage == "full") { + m_GLConfig.m_ShaderUsage = GLConfig::FULL; + } else if (sShaderUsage == "minimal") { + m_GLConfig.m_ShaderUsage = GLConfig::MINIMAL; + } else if (sShaderUsage == "auto") { + m_GLConfig.m_ShaderUsage = GLConfig::AUTO; + } else { + throw Exception(AVG_ERR_OUT_OF_RANGE, + "avgrc parameter shaderusage must be full, minimal, fragmentonly or auto"); + } + string sDummy; + m_GLConfig.m_bUseDebugContext = getEnv("AVG_USE_DEBUG_GL_CONTEXT", sDummy); +#ifdef AVG_ENABLE_EGL + m_GLConfig.m_bGLES = true; +#endif + BitmapLoader::init(!m_GLConfig.m_bGLES); + pMgr->getGammaOption("scr", "gamma", m_DP.m_Gamma); } -void Player::initGraphics() +void Player::initGraphics(const string& sShaderPath) { + if (!Display::isInitialized()) { + ConfigMgr* pMgr = ConfigMgr::get(); + float dotsPerMM = float(atof(pMgr->getOption("scr", "dotspermm")->c_str())); + Display::get()->assumePixelsPerMM(dotsPerMM); + } // Init display configuration. - AVG_TRACE(Logger::CONFIG, "Display bpp: " << m_DP.m_BPP); + AVG_TRACE(Logger::category::CONFIG, Logger::severity::INFO, + "Display bpp: " << m_DP.m_BPP); + + if (m_bDisplayEngineBroken) { + m_bDisplayEngineBroken = false; + m_pDisplayEngine->teardown(); + m_pDisplayEngine = SDLDisplayEnginePtr(); + } if (!m_pDisplayEngine) { m_pDisplayEngine = SDLDisplayEnginePtr(new SDLDisplayEngine()); } - AVG_TRACE(Logger::CONFIG, "Requested OpenGL configuration: "); + AVG_TRACE(Logger::category::CONFIG, Logger::severity::INFO, + "Requested OpenGL configuration: "); m_GLConfig.log(); - m_pDisplayEngine->init(m_DP, m_GLConfig); + m_DP.m_WindowSize = m_pDisplayEngine->calcWindowSize(m_DP); + if (m_pDisplayEngine->getWindowSize() != m_DP.m_WindowSize || + m_pDisplayEngine->isFullscreen() == true) + { + m_pDisplayEngine->teardown(); + m_pDisplayEngine->init(m_DP, m_GLConfig); + } + AVG_TRACE(Logger::category::CONFIG, Logger::severity::INFO, + "Pixels per mm: " << Display::get()->getPixelsPerMM()); + if (sShaderPath != "") { + ShaderRegistry::get()->setShaderPath(sShaderPath); + } + m_pDisplayEngine->setGamma(1.0, 1.0, 1.0); + m_GLConfig = GLContext::getCurrent()->getConfig(); } void Player::initAudio() { - SDLAudioEngine* pAudioEngine = SDLAudioEngine::get(); + AudioEngine* pAudioEngine = AudioEngine::get(); if (!pAudioEngine) { - pAudioEngine = new SDLAudioEngine(); + pAudioEngine = new AudioEngine(); } pAudioEngine->init(m_AP, m_Volume); pAudioEngine->setAudioEnabled(!m_bFakeFPS); pAudioEngine->play(); } -void Player::updateDTD() +void Player::initMainCanvas(NodePtr pRootNode) { - if (m_dtd) { - xmlFreeDtd(m_dtd); - } - // Find and parse dtd. - registerDTDEntityLoader("avg.dtd", m_NodeRegistry.getDTD().c_str()); - string sDTDFName = "avg.dtd"; - m_dtd = xmlParseDTD(NULL, (const xmlChar*) sDTDFName.c_str()); - assert (m_dtd); - m_bDirtyDTD = false; + m_pEventDispatcher = EventDispatcherPtr(new EventDispatcher(this, m_bMouseEnabled)); + m_pMainCanvas = MainCanvasPtr(new MainCanvas(this)); + m_pMainCanvas->setRoot(pRootNode); + m_DP.m_Size = m_pMainCanvas->getSize(); + + registerFrameEndListener(BitmapManager::get()); } -NodePtr Player::internalLoad(const string& sAVG) +NodePtr Player::internalLoad(const string& sAVG, const string& sFilename) { - xmlDocPtr doc = 0; - try { - xmlPedanticParserDefault(1); - xmlDoValidityCheckingDefaultValue=0; - - doc = xmlParseMemory(sAVG.c_str(), sAVG.length()); - if (!doc) { - throw (Exception(AVG_ERR_XML_PARSE, "")); - } - - if (m_bDirtyDTD) { - updateDTD(); - } - - xmlValidCtxtPtr cvp = xmlNewValidCtxt(); - cvp->error = xmlParserValidityError; - cvp->warning = xmlParserValidityWarning; - int valid=xmlValidateDtd(cvp, doc, m_dtd); - xmlFreeValidCtxt(cvp); - if (!valid) { - throw (Exception(AVG_ERR_XML_VALID, "")); - } - xmlNodePtr xmlNode = xmlDocGetRootElement(doc); - NodePtr pNode = createNodeFromXml(doc, xmlNode); - if (!pNode) { - throw (Exception(AVG_ERR_XML_PARSE, - "Root node of an avg tree needs to be an <avg> node.")); - } - xmlFreeDoc(doc); - return pNode; - } catch (Exception& ex) { - AVG_TRACE(Logger::ERROR, ex.getStr()); - if (doc) { - xmlFreeDoc(doc); - } - throw; + XMLParser parser; + parser.setDTD(TypeRegistry::get()->getDTD(), "avg.dtd"); + parser.parse(sAVG, sFilename); + xmlNodePtr xmlNode = parser.getRootNode(); + NodePtr pNode = createNodeFromXml(parser.getDoc(), xmlNode); + if (!pNode) { + throw (Exception(AVG_ERR_XML_PARSE, + "Root node of an avg tree needs to be an <avg> node.")); } + return pNode; } SDLDisplayEnginePtr Player::safeGetDisplayEngine() @@ -1242,41 +1326,38 @@ SDLDisplayEnginePtr Player::safeGetDisplayEngine() } -void Player::registerNodeType(NodeDefinition def, const char* pParentNames[]) -{ - m_NodeRegistry.registerNodeType(def); - - if (pParentNames) { - string sChildArray[1]; - sChildArray[0] = def.getName(); - vector<string> sChildren = vectorFromCArray(1, sChildArray); - const char **ppCurParentName = pParentNames; - - while (*ppCurParentName) { - NodeDefinition nodeDefinition = m_NodeRegistry.getNodeDef(*ppCurParentName); - nodeDefinition.addChildren(sChildren); - m_NodeRegistry.updateNodeDefinition(nodeDefinition); - - ++ppCurParentName; - } - } - m_bDirtyDTD = true; -} - -NodePtr Player::createNode(const string& sType, const boost::python::dict& params) +NodePtr Player::createNode(const string& sType, + const py::dict& params, const boost::python::object& self) { DivNodePtr pParentNode; - boost::python::dict attrs = params; - boost::python::object parent; + py::dict attrs = params; + py::object parent; if (params.has_key("parent")) { parent = params["parent"]; attrs.attr("__delitem__")("parent"); - pParentNode = boost::python::extract<DivNodePtr>(parent); - } - NodePtr pNode = m_NodeRegistry.createNode(sType, attrs); - if (pParentNode) { - pParentNode->appendChild(pNode); - } + pParentNode = py::extract<DivNodePtr>(parent); + } + NodePtr pNode = dynamic_pointer_cast<Node>( + TypeRegistry::get()->createObject(sType, attrs)); + + // See if the class names of self and pNode match. If they don't, there is a + // python derived class that's being constructed and we can't set parent here. + string sSelfClassName = py::extract<string>( + self.attr("__class__").attr("__name__")); + py::object pythonClassName = + (py::object(pNode).attr("__class__").attr("__name__")); + string sThisClassName = py::extract<string>(pythonClassName); + bool bHasDerivedClass = sSelfClassName != sThisClassName && + sSelfClassName != "NoneType"; + if (bHasDerivedClass) { + if (pParentNode) { + throw Exception(AVG_ERR_UNSUPPORTED, + "Can't pass 'parent' parameter to C++ class constructor if there is a derived python class. Use Node.registerInstance() instead."); + } + pNode->registerInstance(self.ptr(), pParentNode); + } else { + pNode->registerInstance(0, pParentNode); + } if (parent) { attrs["parent"] = parent; } @@ -1288,43 +1369,29 @@ NodePtr Player::createNodeFromXmlString(const string& sXML) xmlPedanticParserDefault(1); xmlDoValidityCheckingDefaultValue =0; - xmlDocPtr doc; - doc = xmlParseMemory(sXML.c_str(), int(sXML.length())); - if (!doc) { - throw (Exception(AVG_ERR_XML_PARSE, - string("Error parsing xml:\n ")+sXML)); - } - NodePtr pNode = createNodeFromXml(doc, xmlDocGetRootElement(doc)); - - if (m_bDirtyDTD) - updateDTD(); + XMLParser parser; + parser.setDTD(TypeRegistry::get()->getDTD(), "avg.dtd"); + parser.parse(sXML, ""); - xmlValidCtxtPtr cvp = xmlNewValidCtxt(); - cvp->error = xmlParserValidityError; - cvp->warning = xmlParserValidityWarning; - int valid=xmlValidateDtd(cvp, doc, m_dtd); - xmlFreeValidCtxt(cvp); - if (!valid) { - throw (Exception(AVG_ERR_XML_PARSE, - "Could not validate '"+sXML+"'")); - } +// cvp->error = xmlParserValidityError; +// cvp->warning = xmlParserValidityWarning; + xmlNodePtr xmlNode = parser.getRootNode(); + NodePtr pNode = createNodeFromXml(parser.getDoc(), xmlNode); - xmlFreeDoc(doc); return pNode; } NodePtr Player::createNodeFromXml(const xmlDocPtr xmlDoc, const xmlNodePtr xmlNode) { - NodePtr pCurNode; const char * nodeType = (const char *)xmlNode->name; - if (!strcmp (nodeType, "text") || - !strcmp (nodeType, "comment")) { + if (!strcmp (nodeType, "text") || !strcmp (nodeType, "comment")) { // Ignore whitespace & comments return NodePtr(); } - pCurNode = m_NodeRegistry.createNode(nodeType, xmlNode); + NodePtr pCurNode = dynamic_pointer_cast<Node>( + TypeRegistry::get()->createObject(nodeType, xmlNode)); if (!strcmp(nodeType, "words")) { // TODO: This is an end-run around the generic serialization mechanism // that will probably break at some point. @@ -1399,16 +1466,16 @@ void Player::sendOver(const CursorEventPtr pOtherEvent, Event::Type type, void Player::handleCursorEvent(CursorEventPtr pEvent, bool bOnlyCheckCursorOver) { // Find all nodes under the cursor. - vector<NodeWeakPtr> pCursorNodes; + vector<NodePtr> pCursorNodes; DivNodePtr pEventReceiverNode = pEvent->getInputDevice()->getEventReceiverNode(); if (!pEventReceiverNode) { pEventReceiverNode = getRootNode(); } pEventReceiverNode->getElementsByPos(pEvent->getPos(), pCursorNodes); ContactPtr pContact = pEvent->getContact(); - if (pContact && pContact->hasListeners() && !bOnlyCheckCursorOver) { + if (pContact && !bOnlyCheckCursorOver) { if (!pCursorNodes.empty()) { - NodePtr pNode = pCursorNodes.begin()->lock(); + NodePtr pNode = *(pCursorNodes.begin()); pEvent->setNode(pNode); } pContact->sendEventToListeners(pEvent); @@ -1417,7 +1484,7 @@ void Player::handleCursorEvent(CursorEventPtr pEvent, bool bOnlyCheckCursorOver) int cursorID = pEvent->getCursorID(); // Determine the nodes the event should be sent to. - vector<NodeWeakPtr> pDestNodes = pCursorNodes; + vector<NodePtr> pDestNodes = pCursorNodes; if (m_EventCaptureInfoMap.find(cursorID) != m_EventCaptureInfoMap.end()) { NodeWeakPtr pEventCaptureNode = m_EventCaptureInfoMap[cursorID]->m_pNode; @@ -1428,7 +1495,7 @@ void Player::handleCursorEvent(CursorEventPtr pEvent, bool bOnlyCheckCursorOver) } } - vector<NodeWeakPtr> pLastCursorNodes; + vector<NodePtr> pLastCursorNodes; { map<int, CursorStatePtr>::iterator it; it = m_pLastCursorStates.find(cursorID); @@ -1438,50 +1505,48 @@ void Player::handleCursorEvent(CursorEventPtr pEvent, bool bOnlyCheckCursorOver) } // Send out events. - vector<NodeWeakPtr>::const_iterator itLast; - vector<NodeWeakPtr>::iterator itCur; + vector<NodePtr>::const_iterator itLast; + vector<NodePtr>::iterator itCur; for (itLast = pLastCursorNodes.begin(); itLast != pLastCursorNodes.end(); ++itLast) { - NodePtr pLastNode = itLast->lock(); + NodePtr pLastNode = *itLast; for (itCur = pCursorNodes.begin(); itCur != pCursorNodes.end(); ++itCur) { - if (itCur->lock() == pLastNode) { + if (*itCur == pLastNode) { break; } } if (itCur == pCursorNodes.end()) { - sendOver(pEvent, Event::CURSOROUT, pLastNode); + sendOver(pEvent, Event::CURSOR_OUT, pLastNode); } } // Send over events. for (itCur = pCursorNodes.begin(); itCur != pCursorNodes.end(); ++itCur) { - NodePtr pCurNode = itCur->lock(); + NodePtr pCurNode = *itCur; for (itLast = pLastCursorNodes.begin(); itLast != pLastCursorNodes.end(); ++itLast) { - if (itLast->lock() == pCurNode) { + if (*itLast == pCurNode) { break; } } if (itLast == pLastCursorNodes.end()) { - sendOver(pEvent, Event::CURSOROVER, pCurNode); + sendOver(pEvent, Event::CURSOR_OVER, pCurNode); } } if (!bOnlyCheckCursorOver) { // Iterate through the nodes and send the event to all of them. - vector<NodeWeakPtr>::iterator it; + vector<NodePtr>::iterator it; for (it = pDestNodes.begin(); it != pDestNodes.end(); ++it) { - NodePtr pNode = (*it).lock(); - if (pNode) { - CursorEventPtr pNodeEvent = boost::dynamic_pointer_cast<CursorEvent>( - pEvent->cloneAs(pEvent->getType())); - pNodeEvent->setNode(pNode); - if (pNodeEvent->getType() != Event::CURSORMOTION) { - pNodeEvent->trace(); + NodePtr pNode = *it; + if (pNode->getState() != Node::NS_UNCONNECTED) { + pEvent->setNode(pNode); + if (pEvent->getType() != Event::CURSOR_MOTION) { + pEvent->trace(); } - if (pNode->handleEvent(pNodeEvent) == true) { + if (pNode->handleEvent(pEvent) == true) { // stop bubbling break; } @@ -1489,12 +1554,12 @@ void Player::handleCursorEvent(CursorEventPtr pEvent, bool bOnlyCheckCursorOver) } } - if (pEvent->getType() == Event::CURSORUP && pEvent->getSource() != Event::MOUSE) { + if (pEvent->getType() == Event::CURSOR_UP && pEvent->getSource() != Event::MOUSE) { // Cursor has disappeared: send out events. - vector<NodeWeakPtr>::iterator it; + vector<NodePtr>::iterator it; for (it = pCursorNodes.begin(); it != pCursorNodes.end(); ++it) { - NodePtr pNode = it->lock(); - sendOver(pEvent, Event::CURSOROUT, pNode); + NodePtr pNode = *it; + sendOver(pEvent, Event::CURSOR_OUT, pNode); } m_pLastCursorStates.erase(cursorID); } else { @@ -1539,14 +1604,14 @@ void Player::handleTimers() m_bInHandleTimers = true; it = m_PendingTimeouts.begin(); - while (it != m_PendingTimeouts.end() && (*it)->IsReady(getFrameTime()) + while (it != m_PendingTimeouts.end() && (*it)->isReady(getFrameTime()) && !m_bStopping) { - (*it)->Fire(getFrameTime()); + (*it)->fire(getFrameTime()); if (m_bCurrentTimeoutDeleted) { it = m_PendingTimeouts.begin(); } else { - if ((*it)->IsInterval()) { + if ((*it)->isInterval()) { Timeout* pTempTimeout = *it; it = m_PendingTimeouts.erase(it); m_NewTimeouts.insert(m_NewTimeouts.begin(), pTempTimeout); @@ -1561,8 +1626,25 @@ void Player::handleTimers() addTimeout(*it); } m_NewTimeouts.clear(); + + notifySubscribers("ON_FRAME"); + m_bInHandleTimers = false; + if (m_bPythonAvailable) { + std::vector<Timeout *> tempAsyncCalls; + Py_BEGIN_ALLOW_THREADS; + { + lock_guard lock(m_AsyncCallMutex); + tempAsyncCalls = m_AsyncCalls; + m_AsyncCalls.clear(); + } + Py_END_ALLOW_THREADS; + for (it = tempAsyncCalls.begin(); it != tempAsyncCalls.end(); ++it) { + (*it)->fire(getFrameTime()); + delete *it; + } + } } SDLDisplayEngine * Player::getDisplayEngine() const @@ -1570,6 +1652,11 @@ SDLDisplayEngine * Player::getDisplayEngine() const return m_pDisplayEngine.get(); } +void Player::keepWindowOpen() +{ + m_bKeepWindowOpen = true; +} + void Player::setStopOnEscape(bool bStop) { m_bStopOnEscape = bStop; @@ -1580,19 +1667,44 @@ bool Player::getStopOnEscape() const return m_bStopOnEscape; } -void Player::setVolume(double volume) +void Player::setVolume(float volume) { m_Volume = volume; - if (SDLAudioEngine::get()) { - SDLAudioEngine::get()->setVolume(m_Volume); + if (AudioEngine::get()) { + AudioEngine::get()->setVolume(m_Volume); } } -double Player::getVolume() const +float Player::getVolume() const { return m_Volume; } +string Player::getConfigOption(const string& sSubsys, const string& sName) const +{ + const string* psValue = ConfigMgr::get()->getOption(sSubsys, sName); + if (!psValue) { + throw Exception(AVG_ERR_INVALID_ARGS, string("Unknown config option ") + sSubsys + + ":" + sName); + } else { + return *psValue; + } +} + +bool Player::isUsingGLES() const +{ + return m_GLConfig.m_bGLES; +} + +bool Player::areFullShadersSupported() const +{ + if (!m_bIsPlaying) { + throw Exception(AVG_ERR_UNSUPPORTED, + "Must call Player.play() before areFullShadersSupported()."); + } + return (m_GLConfig.m_ShaderUsage == GLConfig::FULL); +} + OffscreenCanvasPtr Player::getCanvasFromURL(const std::string& sURL) { if (sURL.substr(0, 7) != "canvas:") { @@ -1609,7 +1721,7 @@ OffscreenCanvasPtr Player::getCanvasFromURL(const std::string& sURL) string("Canvas with url '")+sURL+"' not found."); } -void Player::cleanup() +void Player::cleanup(bool bIsAbort) { // Kill all timeouts. vector<Timeout*>::iterator it; @@ -1624,7 +1736,7 @@ void Player::cleanup() if (m_pMainCanvas) { unregisterFrameEndListener(BitmapManager::get()); delete BitmapManager::get(); - m_pMainCanvas->stopPlayback(); + m_pMainCanvas->stopPlayback(bIsAbort); m_pMainCanvas = MainCanvasPtr(); } @@ -1632,46 +1744,53 @@ void Player::cleanup() m_pMultitouchInputDevice = IInputDevicePtr(); } for (unsigned i = 0; i < m_pCanvases.size(); ++i) { - m_pCanvases[i]->stopPlayback(); + m_pCanvases[i]->stopPlayback(bIsAbort); } m_pCanvases.clear(); if (m_pDisplayEngine) { - m_pDisplayEngine->deinitRender(); - m_pDisplayEngine->teardown(); + m_DP.m_WindowSize = IntPoint(0,0); + if (!m_bKeepWindowOpen) { + m_pDisplayEngine->deinitRender(); + m_pDisplayEngine->teardown(); + m_pDisplayEngine = SDLDisplayEnginePtr(); + } } - if (SDLAudioEngine::get()) { - SDLAudioEngine::get()->teardown(); + if (AudioEngine::get()) { + AudioEngine::get()->teardown(); } m_pEventDispatcher = EventDispatcherPtr(); - m_pLastMouseEvent = MouseEventPtr(new MouseEvent(Event::CURSORMOTION, false, false, - false, IntPoint(-1, -1), MouseEvent::NO_BUTTON, DPoint(-1, -1), 0)); + m_pLastMouseEvent = MouseEventPtr(new MouseEvent(Event::CURSOR_MOTION, false, false, + false, IntPoint(-1, -1), MouseEvent::NO_BUTTON, glm::vec2(-1, -1), 0)); m_FrameTime = 0; m_bIsPlaying = false; m_CurDirName = getCWD(); + + removeSubscribers(); } -int Player::addTimeout(Timeout* pTimeout) +int Player::internalSetTimeout(int time, PyObject * pyfunc, bool bIsInterval) { - vector<Timeout*>::iterator it = m_PendingTimeouts.begin(); - while (it != m_PendingTimeouts.end() && (**it)<*pTimeout) { - it++; + Timeout* pTimeout = new Timeout(time, pyfunc, bIsInterval, getFrameTime()); + if (m_bInHandleTimers) { + m_NewTimeouts.push_back(pTimeout); + } else { + addTimeout(pTimeout); } - m_PendingTimeouts.insert(it, pTimeout); - return pTimeout->GetID(); + return pTimeout->getID(); } -void Player::removeTimeout(Timeout* pTimeout) +int Player::addTimeout(Timeout* pTimeout) { - delete pTimeout; vector<Timeout*>::iterator it = m_PendingTimeouts.begin(); - while (*it != pTimeout) { + while (it != m_PendingTimeouts.end() && (**it)<*pTimeout) { it++; } - m_PendingTimeouts.erase(it); + m_PendingTimeouts.insert(it, pTimeout); + return pTimeout->getID(); } void Player::setPluginPath(const string& newPath) @@ -1684,7 +1803,7 @@ string Player::getPluginPath() const return PluginManager::get().getSearchPath(); } -boost::python::object Player::loadPlugin(const std::string& name) +py::object Player::loadPlugin(const std::string& name) { return PluginManager::get().loadPlugin(name); } diff --git a/src/player/Player.h b/src/player/Player.h index 8c8e786..32d0da5 100644 --- a/src/player/Player.h +++ b/src/player/Player.h @@ -1,6 +1,6 @@ // // libavg - Media Playback Engine. -// Copyright (C) 2003-2011 Ulrich von Zadow +// Copyright (C) 2003-2014 Ulrich von Zadow // // This library is free software; you can redistribute it and/or // modify it under the terms of the GNU Lesser General Public @@ -23,8 +23,9 @@ #define _Player_H_ #include "../api.h" +#include "Publisher.h" #include "Timeout.h" -#include "NodeRegistry.h" +#include "TypeRegistry.h" #include "DisplayParams.h" #include "CursorState.h" #include "TestHelper.h" @@ -35,6 +36,7 @@ #include <libxml/parser.h> #include <boost/shared_ptr.hpp> +#include <boost/thread/thread.hpp> #include <string> #include <vector> @@ -57,6 +59,7 @@ class EventDispatcher; class MouseEvent; class CursorEvent; class SDLDisplayEngine; +class Display; typedef boost::shared_ptr<Node> NodePtr; typedef boost::weak_ptr<Node> NodeWeakPtr; @@ -68,8 +71,9 @@ typedef boost::shared_ptr<EventDispatcher> EventDispatcherPtr; typedef boost::shared_ptr<MouseEvent> MouseEventPtr; typedef boost::shared_ptr<CursorEvent> CursorEventPtr; typedef boost::shared_ptr<SDLDisplayEngine> SDLDisplayEnginePtr; +typedef boost::shared_ptr<Display> DisplayPtr; -class AVG_API Player +class AVG_API Player: public Publisher { public: Player(); @@ -82,60 +86,66 @@ class AVG_API Player bool isFullscreen(); void setWindowFrame(bool bHasWindowFrame); void setWindowPos(int x=0, int y=0); - void setOGLOptions(bool bUsePOTTextures, bool bUseShaders, - bool bUsePixelBuffers, int multiSampleSamples); + void setWindowTitle(const std::string& sTitle); + void useGLES(bool bGLES); + void setOGLOptions(bool bUsePOTTextures, bool bUsePixelBuffers, + int multiSampleSamples, GLConfig::ShaderUsage shaderUsage, + bool bUseDebugContext); void setMultiSampleSamples(int multiSampleSamples); void setAudioOptions(int samplerate, int channels); - DPoint getScreenResolution(); - double getPixelsPerMM(); - DPoint getPhysicalScreenDimensions(); - void assumePixelsPerMM(double ppmm); + void enableGLErrorChecks(bool bEnable); + glm::vec2 getScreenResolution(); + float getPixelsPerMM(); + glm::vec2 getPhysicalScreenDimensions(); + void assumePixelsPerMM(float ppmm); CanvasPtr loadFile(const std::string& sFilename); CanvasPtr loadString(const std::string& sAVG); OffscreenCanvasPtr loadCanvasFile(const std::string& sFilename); OffscreenCanvasPtr loadCanvasString(const std::string& sAVG); - CanvasPtr createMainCanvas(const boost::python::dict& params); - OffscreenCanvasPtr createCanvas(const boost::python::dict& params); + CanvasPtr createMainCanvas(const py::dict& params); + OffscreenCanvasPtr createCanvas(const py::dict& params); void deleteCanvas(const std::string& sID); CanvasPtr getMainCanvas() const; OffscreenCanvasPtr getCanvas(const std::string& sID) const; - void newCanvasDependency(const OffscreenCanvasPtr pCanvas); + void newCanvasDependency(); void play(); void stop(); bool isStopping(); - void initPlayback(); - void cleanup(); + void initPlayback(const std::string& sShaderPath = ""); + void cleanup(bool bIsAbort); bool isPlaying(); - void setFramerate(double rate); + void setFramerate(float rate); void setVBlankFramerate(int rate); - double getEffectiveFramerate(); + float getEffectiveFramerate(); TestHelper * getTestHelper(); - void setFakeFPS(double fps); + void setFakeFPS(float fps); long long getFrameTime(); - double getFrameDuration(); + float getFrameDuration(); - void registerNodeType(NodeDefinition Def, const char* pParentNames[] = 0); - - NodePtr createNode(const std::string& sType, const boost::python::dict& PyDict); + NodePtr createNode(const std::string& sType, const py::dict& PyDict, + const py::object& self=py::object()); NodePtr createNodeFromXmlString(const std::string& sXML); int setInterval(int time, PyObject * pyfunc); int setTimeout(int time, PyObject * pyfunc); int setOnFrameHandler(PyObject * pyfunc); bool clearInterval(int id); + void callFromThread(PyObject * pyfunc); void addInputDevice(IInputDevicePtr pSource); MouseEventPtr getMouseState() const; - TrackerInputDevice * addTracker(); + EventPtr getCurrentEvent() const; TrackerInputDevice * getTracker(); void enableMultitouch(); + void enableMouse(bool enabled); bool isMultitouchAvailable() const; void setEventCapture(NodePtr pNode, int cursorID); void releaseEventCapture(int cursorID); bool isCaptured(int cursorID); + void removeDeadEventCaptures(); EventPtr getCurEvent() const; void setMousePos(const IntPoint& pos); int getKeyModifierState() const; @@ -143,29 +153,38 @@ class AVG_API Player BitmapPtr screenshot(); void setCursor(const Bitmap* pBmp, IntPoint hotSpot); void showCursor(bool bShow); + bool isCursorShown(); NodePtr getElementByID(const std::string& id); AVGNodePtr getRootNode(); void doFrame(bool bFirstFrame); - double getFramerate(); - double getVideoRefreshRate(); - bool isUsingShaders(); - void setGamma(double red, double green, double blue); + float getFramerate(); + float getVideoRefreshRate(); + size_t getVideoMemInstalled(); + size_t getVideoMemUsed(); + void setGamma(float red, float green, float blue); SDLDisplayEngine * getDisplayEngine() const; + void keepWindowOpen(); void setStopOnEscape(bool bStop); bool getStopOnEscape() const; - void setVolume(double volume); - double getVolume() const; + void setVolume(float volume); + float getVolume() const; + std::string getConfigOption(const std::string& sSubsys, const std::string& sName) + const; + bool isUsingGLES() const; + bool areFullShadersSupported() const; OffscreenCanvasPtr getCanvasFromURL(const std::string& sURL); std::string getCurDirName(); std::string getRootMediaDir(); - const NodeDefinition& getNodeDef(const std::string& sType); void disablePython(); + void startTraversingTree(); + void endTraversingTree(); + bool isTraversingTree() const; - boost::python::object loadPlugin(const std::string& name); + py::object loadPlugin(const std::string& name); void setPluginPath(const std::string& newPath); std::string getPluginPath() const; @@ -183,14 +202,13 @@ class AVG_API Player private: void initConfig(); - void initGraphics(); + void initGraphics(const std::string& sShaderPath); void initAudio(); - - void updateDTD(); + void initMainCanvas(NodePtr pRootNode); NodePtr loadMainNodeFromFile(const std::string& sFilename); NodePtr loadMainNodeFromString(const std::string& sAVG); - NodePtr internalLoad(const std::string& sAVG); + NodePtr internalLoad(const std::string& sAVG, const std::string& sFilename); SDLDisplayEnginePtr safeGetDisplayEngine(); NodePtr createNodeFromXml(const xmlDocPtr xmlDoc, @@ -210,42 +228,44 @@ class AVG_API Player MainCanvasPtr m_pMainCanvas; SDLDisplayEnginePtr m_pDisplayEngine; + bool m_bDisplayEngineBroken; TestHelperPtr m_pTestHelper; std::string m_CurDirName; + bool m_bIsTraversingTree; bool m_bStopping; - NodeRegistry m_NodeRegistry; IInputDevicePtr m_pMultitouchInputDevice; + // Timeout handling + int internalSetTimeout(int time, PyObject * pyfunc, bool bIsInterval); int addTimeout(Timeout* pTimeout); - void removeTimeout(Timeout* pTimeout); void handleTimers(); bool m_bInHandleTimers; bool m_bCurrentTimeoutDeleted; std::vector<Timeout *> m_PendingTimeouts; std::vector<Timeout *> m_NewTimeouts; // Timeouts to be added this frame. + std::vector<Timeout *> m_AsyncCalls; + boost::mutex m_AsyncCallMutex; // Configuration variables. DisplayParams m_DP; AudioParams m_AP; GLConfig m_GLConfig; + bool m_bKeepWindowOpen; bool m_bStopOnEscape; bool m_bIsPlaying; // Time calculation bool m_bFakeFPS; - double m_FakeFPS; + float m_FakeFPS; long long m_FrameTime; long long m_PlayStartTime; long long m_NumFrames; - double m_Volume; - - bool m_bDirtyDTD; - xmlDtdPtr m_dtd; + float m_Volume; bool m_bPythonAvailable; @@ -258,7 +278,7 @@ class AVG_API Player struct EventCaptureInfo { EventCaptureInfo(const NodeWeakPtr& pNode); - NodeWeakPtr m_pNode; + NodePtr m_pNode; int m_CaptureCount; }; typedef boost::shared_ptr<EventCaptureInfo> EventCaptureInfoPtr; @@ -266,11 +286,13 @@ class AVG_API Player std::map<int, EventCaptureInfoPtr> m_EventCaptureInfoMap; MouseEventPtr m_pLastMouseEvent; + EventPtr m_pCurrentEvent; // The indexes of this map are cursorids. std::map<int, CursorStatePtr> m_pLastCursorStates; PyObject * m_EventHookPyFunc; + bool m_bMouseEnabled; }; } diff --git a/src/player/PluginManager.cpp b/src/player/PluginManager.cpp index a117a5b..57d33f0 100644 --- a/src/player/PluginManager.cpp +++ b/src/player/PluginManager.cpp @@ -1,6 +1,6 @@ // // libavg - Media Playback Engine. -// Copyright (C) 2003-2011 Ulrich von Zadow +// Copyright (C) 2003-2014 Ulrich von Zadow // // This library is free software; you can redistribute it and/or // modify it under the terms of the GNU Lesser General Public @@ -23,8 +23,6 @@ #include "PluginManager.h" -#include "NodeDefinition.h" - #include "../base/DlfcnWrapper.h" #include "../base/FileHelper.h" #include "../base/Logger.h" @@ -58,8 +56,10 @@ PluginManager& PluginManager::get() PluginManager::PluginManager() { - setSearchPath(string("."PATH_DELIMITER) + "./plugin"PATH_DELIMITER + - getAvgLibPath() + "plugin"); + setSearchPath(string("."PATH_DELIMITER) + + "./plugin"PATH_DELIMITER + + "./plugin/.libs"PATH_DELIMITER + + getPath(getAvgLibPath()) + "plugin"); } void PluginManager::setSearchPath(const string& sNewPath) @@ -73,7 +73,7 @@ string PluginManager::getSearchPath() const return m_sCurrentSearchPath; } -boost::python::object PluginManager::loadPlugin(const std::string& sPluginName) +py::object PluginManager::loadPlugin(const std::string& sPluginName) { // is it loaded aready? PluginMap::iterator i = m_LoadedPlugins.find(sPluginName); @@ -89,7 +89,7 @@ boost::python::object PluginManager::loadPlugin(const std::string& sPluginName) ++referenceCount; m_LoadedPlugins[sPluginName] = make_pair(i->second.first, referenceCount); } - boost::python::object sysModule(boost::python::handle<>(PyImport_ImportModule("sys"))); + py::object sysModule(py::handle<>(PyImport_ImportModule("sys"))); return sysModule.attr("modules")[sPluginName]; } @@ -106,7 +106,7 @@ string PluginManager::locateSharedObject(const string& sFilename) } string sMessage = "Unable to locate plugin file '" + sFilename + "'. Was looking in " + m_sCurrentSearchPath; - AVG_TRACE(Logger::PLUGIN, sMessage); + AVG_TRACE(Logger::category::PLUGIN, Logger::severity::INFO, sMessage); throw PluginNotFound(sMessage); } @@ -145,7 +145,8 @@ void PluginManager::parsePath(const string& sPath) m_PathComponents.push_back(sDirectory); } while (!sRemaining.empty()); - AVG_TRACE(Logger::PLUGIN, "Plugin search path set to '" << sPath << "'"); + AVG_TRACE(Logger::category::PLUGIN, Logger::severity::INFO, + "Plugin search path set to '" << sPath << "'"); } void* PluginManager::internalLoadPlugin(const string& sFullpath) @@ -153,7 +154,8 @@ void* PluginManager::internalLoadPlugin(const string& sFullpath) void *handle = dlopen(sFullpath.c_str(), RTLD_LOCAL | RTLD_NOW); if (!handle) { string sMessage(dlerror()); - AVG_TRACE(Logger::PLUGIN, "Could not load plugin. dlopen failed with message '" + AVG_TRACE(Logger::category::PLUGIN, Logger::severity::ERROR, + "Could not load plugin. dlopen failed with message '" << sMessage << "'"); throw PluginCorrupted(sMessage); } @@ -163,7 +165,8 @@ void* PluginManager::internalLoadPlugin(const string& sFullpath) dlclose(handle); throw e; } - AVG_TRACE(Logger::PLUGIN, "Loaded plugin '" << sFullpath << "'"); + AVG_TRACE(Logger::category::PLUGIN,Logger::severity::INFO, + "Loaded plugin '" << sFullpath << "'"); return handle; } @@ -176,7 +179,8 @@ void PluginManager::registerPlugin(void* handle) if (registerPlugin) { registerPlugin(); } else { - AVG_TRACE(Logger::PLUGIN, "No plugin registration function detected"); + AVG_TRACE(Logger::category::PLUGIN, Logger::severity::ERROR, + "No plugin registration function detected"); throw PluginCorrupted("No plugin registration function detected"); } } diff --git a/src/player/PluginManager.h b/src/player/PluginManager.h index f46b8d7..37a5d23 100644 --- a/src/player/PluginManager.h +++ b/src/player/PluginManager.h @@ -1,6 +1,6 @@ // // libavg - Media Playback Engine. -// Copyright (C) 2003-2011 Ulrich von Zadow +// Copyright (C) 2003-2014 Ulrich von Zadow // // This library is free software; you can redistribute it and/or // modify it under the terms of the GNU Lesser General Public @@ -52,7 +52,7 @@ public: void setSearchPath(const std::string& aNewPath); std::string getSearchPath() const; - boost::python::object loadPlugin(const std::string& aPluginName); + py::object loadPlugin(const std::string& aPluginName); private: PluginManager(); diff --git a/src/player/PolyLineNode.cpp b/src/player/PolyLineNode.cpp index 48f40f6..16899f7 100644 --- a/src/player/PolyLineNode.cpp +++ b/src/player/PolyLineNode.cpp @@ -1,6 +1,6 @@ // // libavg - Media Playback Engine. -// Copyright (C) 2003-2011 Ulrich von Zadow +// Copyright (C) 2003-2014 Ulrich von Zadow // // This library is free software; you can redistribute it and/or // modify it under the terms of the GNU Lesser General Public @@ -21,7 +21,7 @@ #include "PolyLineNode.h" -#include "NodeDefinition.h" +#include "TypeDefinition.h" #include "../graphics/VertexArray.h" #include "../base/Exception.h" @@ -33,17 +33,18 @@ using namespace std; namespace avg { -NodeDefinition PolyLineNode::createDefinition() +void PolyLineNode::registerType() { - vector<DPoint> v; - vector<double> vd; - return NodeDefinition("polyline", Node::buildNode<PolyLineNode>) - .extendDefinition(VectorNode::createDefinition()) + vector<glm::vec2> v; + vector<float> vd; + TypeDefinition def = TypeDefinition("polyline", "vectornode", + ExportedObject::buildObject<PolyLineNode>) .addArg(Arg<string>("linejoin", "bevel")) - .addArg(Arg<vector<DPoint> >("pos", v, false, offsetof(PolyLineNode, m_Pts))) - .addArg(Arg<vector<double> >("texcoords", vd, false, + .addArg(Arg<vector<glm::vec2> >("pos", v, false, offsetof(PolyLineNode, m_Pts))) + .addArg(Arg<vector<float> >("texcoords", vd, false, offsetof(PolyLineNode, m_TexCoords))) ; + TypeRegistry::get()->registerType(def); } PolyLineNode::PolyLineNode(const ArgList& args) @@ -62,20 +63,13 @@ PolyLineNode::~PolyLineNode() { } -const vector<DPoint>& PolyLineNode::getPos() const +const vector<glm::vec2>& PolyLineNode::getPos() const { return m_Pts; } -void PolyLineNode::setPos(const vector<DPoint>& pts) +void PolyLineNode::setPos(const vector<glm::vec2>& pts) { - vector<DPoint>::const_iterator it; - for (it = pts.begin(); it != pts.end(); ++it) { - if (it->isNaN() || it->isInf()) { - throw Exception(AVG_ERR_INVALID_ARGS, - "polyline positions must not be nan or inf."); - } - } m_Pts = pts; m_TexCoords.clear(); m_EffTexCoords.clear(); @@ -83,12 +77,12 @@ void PolyLineNode::setPos(const vector<DPoint>& pts) setDrawNeeded(); } -const vector<double>& PolyLineNode::getTexCoords() const +const vector<float>& PolyLineNode::getTexCoords() const { return m_TexCoords; } -void PolyLineNode::setTexCoords(const vector<double>& coords) +void PolyLineNode::setTexCoords(const vector<float>& coords) { if (coords.size() > m_Pts.size()) { throw(Exception(AVG_ERR_OUT_OF_RANGE, @@ -110,7 +104,7 @@ void PolyLineNode::setLineJoin(const string& s) setDrawNeeded(); } -void PolyLineNode::calcVertexes(VertexArrayPtr& pVertexArray, Pixel32 color) +void PolyLineNode::calcVertexes(const VertexDataPtr& pVertexData, Pixel32 color) { if (getNumDifferentPts(m_Pts) < 2) { return; @@ -118,7 +112,7 @@ void PolyLineNode::calcVertexes(VertexArrayPtr& pVertexArray, Pixel32 color) if (m_EffTexCoords.empty()) { calcEffPolyLineTexCoords(m_EffTexCoords, m_TexCoords, m_CumulDist); } - calcPolyLine(m_Pts, m_EffTexCoords, false, m_LineJoin, pVertexArray, color); + calcPolyLine(m_Pts, m_EffTexCoords, false, m_LineJoin, pVertexData, color); } } diff --git a/src/player/PolyLineNode.h b/src/player/PolyLineNode.h index 80b4255..41ee162 100644 --- a/src/player/PolyLineNode.h +++ b/src/player/PolyLineNode.h @@ -1,6 +1,6 @@ // // libavg - Media Playback Engine. -// Copyright (C) 2003-2011 Ulrich von Zadow +// Copyright (C) 2003-2014 Ulrich von Zadow // // This library is free software; you can redistribute it and/or // modify it under the terms of the GNU Lesser General Public @@ -35,27 +35,27 @@ namespace avg { class AVG_API PolyLineNode : public VectorNode { public: - static NodeDefinition createDefinition(); + static void registerType(); PolyLineNode(const ArgList& args); virtual ~PolyLineNode(); - const std::vector<DPoint>& getPos() const; - void setPos(const std::vector<DPoint>& pts); + const std::vector<glm::vec2>& getPos() const; + void setPos(const std::vector<glm::vec2>& pts); - const std::vector<double>& getTexCoords() const; - void setTexCoords(const std::vector<double>& coords); + const std::vector<float>& getTexCoords() const; + void setTexCoords(const std::vector<float>& coords); std::string getLineJoin() const; void setLineJoin(const std::string& s); - virtual void calcVertexes(VertexArrayPtr& pVertexArray, Pixel32 color); + virtual void calcVertexes(const VertexDataPtr& pVertexData, Pixel32 color); private: - std::vector<DPoint> m_Pts; - std::vector<double> m_CumulDist; - std::vector<double> m_TexCoords; - std::vector<double> m_EffTexCoords; + std::vector<glm::vec2> m_Pts; + std::vector<float> m_CumulDist; + std::vector<float> m_TexCoords; + std::vector<float> m_EffTexCoords; LineJoin m_LineJoin; }; diff --git a/src/player/PolygonNode.cpp b/src/player/PolygonNode.cpp index 4c9411d..6e81b9b 100644 --- a/src/player/PolygonNode.cpp +++ b/src/player/PolygonNode.cpp @@ -1,6 +1,6 @@ // // libavg - Media Playback Engine. -// Copyright (C) 2003-2011 Ulrich von Zadow +// Copyright (C) 2003-2014 Ulrich von Zadow // // This library is free software; you can redistribute it and/or // modify it under the terms of the GNU Lesser General Public @@ -21,12 +21,14 @@ #include "PolygonNode.h" -#include "NodeDefinition.h" +#include "TypeDefinition.h" #include "../graphics/VertexArray.h" #include "../base/Exception.h" #include "../base/GeomHelper.h" -#include "../base/Triangulate.h" +#include "../base/triangulate/Triangulate.h" + +#include "../glm/gtx/norm.hpp" #include <iostream> #include <sstream> @@ -35,17 +37,20 @@ using namespace std; namespace avg { -NodeDefinition PolygonNode::createDefinition() +void PolygonNode::registerType() { - vector<DPoint> v; - vector<double> vd; - return NodeDefinition("polygon", Node::buildNode<PolygonNode>) - .extendDefinition(FilledVectorNode::createDefinition()) + VectorVec2Vector cv; + vector<glm::vec2> v; + vector<float> vd; + TypeDefinition def = TypeDefinition("polygon", "filledvectornode", + ExportedObject::buildObject<PolygonNode>) .addArg(Arg<string>("linejoin", "bevel")) - .addArg(Arg<vector<DPoint> >("pos", v, false, offsetof(PolygonNode, m_Pts))) - .addArg(Arg<vector<double> >("texcoords", vd, false, + .addArg(Arg<vector<glm::vec2> >("pos", v, false, offsetof(PolygonNode, m_Pts))) + .addArg(Arg<vector<float> >("texcoords", vd, false, offsetof(PolygonNode, m_TexCoords))) + .addArg(Arg<VectorVec2Vector>("holes", cv, false, offsetof(PolygonNode, m_Holes))) ; + TypeRegistry::get()->registerType(def); } PolygonNode::PolygonNode(const ArgList& args) @@ -56,6 +61,18 @@ PolygonNode::PolygonNode(const ArgList& args) throw(Exception(AVG_ERR_OUT_OF_RANGE, "Too many texture coordinates in polygon")); } + if (m_Pts.size() != 0 && m_Pts.size() < 3) { + throw(Exception(AVG_ERR_UNSUPPORTED, + "A polygon must have min. tree points.")); + } + if (m_Holes.size() > 0) { + for (unsigned int i = 0; i < m_Holes.size(); i++) { + if (m_Holes[i].size() < 3) { + throw(Exception(AVG_ERR_UNSUPPORTED, + "A hole of a polygon must have min. tree points.")); + } + } + } setLineJoin(args.getArgVal<string>("linejoin")); calcPolyLineCumulDist(m_CumulDist, m_Pts, true); } @@ -64,13 +81,14 @@ PolygonNode::~PolygonNode() { } -const vector<DPoint>& PolygonNode::getPos() const +const vector<glm::vec2>& PolygonNode::getPos() const { return m_Pts; } -void PolygonNode::setPos(const vector<DPoint>& pts) +void PolygonNode::setPos(const vector<glm::vec2>& pts) { + m_Pts.clear(); m_Pts = pts; m_TexCoords.clear(); m_EffTexCoords.clear(); @@ -78,12 +96,25 @@ void PolygonNode::setPos(const vector<DPoint>& pts) setDrawNeeded(); } -const vector<double>& PolygonNode::getTexCoords() const +const vector<float>& PolygonNode::getTexCoords() const { return m_TexCoords; } -void PolygonNode::setTexCoords(const vector<double>& coords) +const VectorVec2Vector& PolygonNode::getHoles() const +{ + return m_Holes; +} + +void PolygonNode::setHoles(const VectorVec2Vector& holes) +{ + m_Holes = holes; + m_TexCoords.clear(); + m_EffTexCoords.clear(); + setDrawNeeded(); +} + +void PolygonNode::setTexCoords(const vector<float>& coords) { if (coords.size() > m_Pts.size()+1) { throw(Exception(AVG_ERR_OUT_OF_RANGE, @@ -105,14 +136,14 @@ void PolygonNode::setLineJoin(const string& s) setDrawNeeded(); } -void PolygonNode::getElementsByPos(const DPoint& pos, vector<NodeWeakPtr>& pElements) +void PolygonNode::getElementsByPos(const glm::vec2& pos, vector<NodePtr>& pElements) { if (reactsToMouseEvents() && pointInPolygon(pos, m_Pts)) { - pElements.push_back(shared_from_this()); + pElements.push_back(getSharedThis()); } } -void PolygonNode::calcVertexes(VertexArrayPtr& pVertexArray, Pixel32 color) +void PolygonNode::calcVertexes(const VertexDataPtr& pVertexData, Pixel32 color) { if (getNumDifferentPts(m_Pts) < 3) { return; @@ -120,28 +151,43 @@ void PolygonNode::calcVertexes(VertexArrayPtr& pVertexArray, Pixel32 color) if (m_EffTexCoords.empty()) { calcEffPolyLineTexCoords(m_EffTexCoords, m_TexCoords, m_CumulDist); } - calcPolyLine(m_Pts, m_EffTexCoords, true, m_LineJoin, pVertexArray, color); + calcPolyLine(m_Pts, m_EffTexCoords, true, m_LineJoin, pVertexData, color); + + for (unsigned i = 0; i < m_Holes.size(); i++) { + calcPolyLine(m_Holes[i], m_EffTexCoords, true, m_LineJoin, pVertexData, color); + } } -void PolygonNode::calcFillVertexes(VertexArrayPtr& pVertexArray, Pixel32 color) +void PolygonNode::calcFillVertexes(const VertexDataPtr& pVertexData, Pixel32 color) { if (getNumDifferentPts(m_Pts) < 3) { return; } // Remove duplicate points - vector<DPoint> pts; + vector<glm::vec2> pts; + vector<unsigned int> holeIndexes; pts.reserve(m_Pts.size()); - pts.push_back(m_Pts[0]); + if (glm::distance2(m_Pts[0], m_Pts[m_Pts.size()-1]) > 0.1) { + pts.push_back(m_Pts[0]); + } for (unsigned i = 1; i < m_Pts.size(); ++i) { - if (calcDistSquared(m_Pts[i], m_Pts[i-1]) > 0.1) { + if (glm::distance2(m_Pts[i], m_Pts[i-1]) > 0.1) { pts.push_back(m_Pts[i]); } } + if (m_Holes.size() > 0) { + for (unsigned int i = 0; i < m_Holes.size(); i++) { //loop over collection + holeIndexes.push_back(pts.size()); + for (unsigned int j = 0; j < m_Holes[i].size(); j++) { //loop over vector + pts.push_back(m_Holes[i][j]); + } + } + } if (color.getA() > 0) { - DPoint minCoord = pts[0]; - DPoint maxCoord = pts[0]; + glm::vec2 minCoord = pts[0]; + glm::vec2 maxCoord = pts[0]; for (unsigned i = 1; i < pts.size(); ++i) { if (pts[i].x < minCoord.x) { minCoord.x = pts[i].x; @@ -156,14 +202,15 @@ void PolygonNode::calcFillVertexes(VertexArrayPtr& pVertexArray, Pixel32 color) maxCoord.y = pts[i].y; } } - vector<int> triIndexes; - triangulatePolygon(pts, triIndexes); + vector<unsigned int> triIndexes; + triangulatePolygon(triIndexes, pts, holeIndexes); + for (unsigned i = 0; i < pts.size(); ++i) { - DPoint texCoord = calcFillTexCoord(pts[i], minCoord, maxCoord); - pVertexArray->appendPos(pts[i], texCoord, color); + glm::vec2 texCoord = calcFillTexCoord(pts[i], minCoord, maxCoord); + pVertexData->appendPos(pts[i], texCoord, color); } for (unsigned i = 0; i < triIndexes.size(); i+=3) { - pVertexArray->appendTriIndexes(triIndexes[i], triIndexes[i+1], + pVertexData->appendTriIndexes(triIndexes[i], triIndexes[i+1], triIndexes[i+2]); } } diff --git a/src/player/PolygonNode.h b/src/player/PolygonNode.h index e8d4899..850f88f 100644 --- a/src/player/PolygonNode.h +++ b/src/player/PolygonNode.h @@ -1,6 +1,6 @@ // // libavg - Media Playback Engine. -// Copyright (C) 2003-2011 Ulrich von Zadow +// Copyright (C) 2003-2014 Ulrich von Zadow // // This library is free software; you can redistribute it and/or // modify it under the terms of the GNU Lesser General Public @@ -32,33 +32,39 @@ namespace avg { +typedef std::vector<std::vector<glm::vec2> > VectorVec2Vector; + class AVG_API PolygonNode : public FilledVectorNode { public: - static NodeDefinition createDefinition(); + static void registerType(); PolygonNode(const ArgList& args); virtual ~PolygonNode(); - const std::vector<DPoint>& getPos() const; - void setPos(const std::vector<DPoint>& pts); + const std::vector<glm::vec2>& getPos() const; + void setPos(const std::vector<glm::vec2>& pts); + + const std::vector<float>& getTexCoords() const; + void setTexCoords(const std::vector<float>& coords); - const std::vector<double>& getTexCoords() const; - void setTexCoords(const std::vector<double>& coords); + const VectorVec2Vector& getHoles() const; + void setHoles(const VectorVec2Vector& holes); std::string getLineJoin() const; void setLineJoin(const std::string& s); - void getElementsByPos(const DPoint& pos, std::vector<NodeWeakPtr>& pElements); + void getElementsByPos(const glm::vec2& pos, std::vector<NodePtr>& pElements); - virtual void calcVertexes(VertexArrayPtr& pVertexArray, Pixel32 color); - virtual void calcFillVertexes(VertexArrayPtr& pVertexArray, Pixel32 color); + virtual void calcVertexes(const VertexDataPtr& pVertexData, Pixel32 color); + virtual void calcFillVertexes(const VertexDataPtr& pVertexData, Pixel32 color); private: - std::vector<DPoint> m_Pts; - std::vector<double> m_CumulDist; - std::vector<double> m_TexCoords; - std::vector<double> m_EffTexCoords; + std::vector<glm::vec2> m_Pts; + std::vector<float> m_CumulDist; + std::vector<float> m_TexCoords; + std::vector<float> m_EffTexCoords; + VectorVec2Vector m_Holes; LineJoin m_LineJoin; }; diff --git a/src/player/Publisher.cpp b/src/player/Publisher.cpp new file mode 100644 index 0000000..01bbea3 --- /dev/null +++ b/src/player/Publisher.cpp @@ -0,0 +1,248 @@ +// +// libavg - Media Playback Engine. +// Copyright (C) 2003-2014 Ulrich von Zadow +// +// This library is free software; you can redistribute it and/or +// modify it under the terms of the GNU Lesser General Public +// License as published by the Free Software Foundation; either +// version 2 of the License, or (at your option) any later version. +// +// This library 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 +// Lesser General Public License for more details. +// +// You should have received a copy of the GNU Lesser General Public +// License along with this library; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +// +// Current versions can be found at www.libavg.de +// + +#include "Publisher.h" + +#include "SubscriberInfo.h" +#include "PublisherDefinitionRegistry.h" +#include "Player.h" + +#include "../base/Exception.h" +#include "../base/StringHelper.h" + +using namespace std; + +namespace avg { + +int Publisher::s_LastSubscriberID = 0; + +Publisher::Publisher() +{ + m_pPublisherDef = PublisherDefinition::create(""); +} + +Publisher::Publisher(const string& sTypeName) +{ + m_pPublisherDef = PublisherDefinitionRegistry::get()->getDefinition(sTypeName); + vector<MessageID> messageIDs = m_pPublisherDef->getMessageIDs(); + for (unsigned i=0; i<messageIDs.size(); ++i) { + m_SignalMap[messageIDs[i]] = list<SubscriberInfoPtr>(); + } +} + +Publisher::~Publisher() +{ +} + +int Publisher::subscribe(MessageID messageID, const py::object& callable) +{ + SubscriberInfoList& subscribers = safeFindSubscribers(messageID); + int subscriberID = s_LastSubscriberID; + s_LastSubscriberID++; +// cerr << this << " subscribe " << messageID << ", " << subscriberID << endl; + subscribers.push_front(SubscriberInfoPtr(new SubscriberInfo(subscriberID, callable))); + return subscriberID; +} + +void Publisher::unsubscribe(MessageID messageID, int subscriberID) +{ +// cerr << this << " unsubscribe " << messageID << ", " << subscriberID << endl; +// cerr << " "; +// dumpSubscribers(messageID); + SubscriberInfoList& subscribers = safeFindSubscribers(messageID); + SubscriberInfoList::iterator it; + for (it = subscribers.begin(); it != subscribers.end(); it++) { + if ((*it)->getID() == subscriberID) { + unsubscribeIterator(messageID, it); + return; + } + } +// cerr << " End of unsubscribe: "; +// dumpSubscribers(messageID); + throwSubscriberNotFound(messageID, subscriberID); +} + +void Publisher::unsubscribe1(int subscriberID) +{ + SignalMap::iterator it; + for (it = m_SignalMap.begin(); it != m_SignalMap.end(); ++it) { + SubscriberInfoList& subscribers = it->second; + SubscriberInfoList::iterator it2; + for (it2 = subscribers.begin(); it2 != subscribers.end(); it2++) { + if ((*it2)->getID() == subscriberID) { + MessageID messageID = it->first; + unsubscribeIterator(messageID, it2); + return; + } + } + } + throw Exception(AVG_ERR_INVALID_ARGS, + "Subscriber with ID "+toString(subscriberID)+" not found."); +} + +void Publisher::unsubscribeCallable(MessageID messageID, const py::object& callable) +{ + SubscriberInfoList& subscribers = safeFindSubscribers(messageID); + SubscriberInfoList::iterator it; + for (it = subscribers.begin(); it != subscribers.end(); it++) { + if ((*it)->isCallable(callable)) { + unsubscribeIterator(messageID, it); + return; + } + } + throwSubscriberNotFound(messageID, -1); +} + +int Publisher::getNumSubscribers(MessageID messageID) +{ + SubscriberInfoList& subscribers = safeFindSubscribers(messageID); + return subscribers.size(); +} + +bool Publisher::isSubscribed(MessageID messageID, int subscriberID) +{ + SubscriberInfoList& subscribers = safeFindSubscribers(messageID); + SubscriberInfoList::iterator it; + for (it = subscribers.begin(); it != subscribers.end(); it++) { + if ((*it)->getID() == subscriberID) { + return true; + } + } + return false; +} + +bool Publisher::isSubscribedCallable(MessageID messageID, const py::object& callable) +{ + SubscriberInfoList& subscribers = safeFindSubscribers(messageID); + SubscriberInfoList::iterator it; + for (it = subscribers.begin(); it != subscribers.end(); it++) { + if ((*it)->isCallable(callable)) { + return true; + } + } + return false; +} + +void Publisher::publish(MessageID messageID) +{ + if (m_SignalMap.find(messageID) != m_SignalMap.end()) { + throw Exception(AVG_ERR_INVALID_ARGS, "Signal with ID "+toString(messageID)+ + "already registered."); + } + m_SignalMap[messageID] = SubscriberInfoList(); +} + +void Publisher::removeSubscribers() +{ + SignalMap::iterator it; + for (it = m_SignalMap.begin(); it != m_SignalMap.end(); ++it) { + it->second = SubscriberInfoList(); + } +} + +void Publisher::notifySubscribers(MessageID messageID) +{ + SubscriberInfoList& subscribers = safeFindSubscribers(messageID); + if (!subscribers.empty()) { + py::list args; + notifySubscribersPy(messageID, args); + } +} + +void Publisher::notifySubscribers(const string& sMsgName) +{ + MessageID messageID = m_pPublisherDef->getMessageID(sMsgName); + notifySubscribers(messageID); +} + +void Publisher::notifySubscribersPy(MessageID messageID, const py::list& args) +{ +// cerr << this << " notifySubscribers " << messageID << endl; +// cerr << " "; +// dumpSubscribers(messageID); + AVG_ASSERT(!(Player::get()->isTraversingTree())); + SubscriberInfoList& subscribers = safeFindSubscribers(messageID); + WeakSubscriberInfoList subRefs; + for (SubscriberInfoList::iterator it = subscribers.begin(); it != subscribers.end(); + ++it) + { + subRefs.push_back(*it); + } + WeakSubscriberInfoList::iterator it; + for (it = subRefs.begin(); it != subRefs.end(); ++it) { +// cerr << " next" << endl; + if (!(*it).expired()) { + SubscriberInfoPtr pSub = (*it).lock(); + if (pSub->hasExpired()) { + // Python subscriber doesn't exist anymore -> auto-unsubscribe. + unsubscribe(messageID, pSub->getID()); + } else { +// cerr << " invoke: " << (*it)->getID() << endl; + pSub->invoke(args); + } + } + } +// cerr << " end notify" << endl; +} + +MessageID Publisher::genMessageID() +{ + return PublisherDefinitionRegistry::get()->genMessageID(); +} + +void Publisher::unsubscribeIterator(MessageID messageID, SubscriberInfoList::iterator it) +{ + m_SignalMap[messageID].erase(it); +} + + +Publisher::SubscriberInfoList& Publisher::safeFindSubscribers(MessageID messageID) +{ + if (m_SignalMap.find(messageID) == m_SignalMap.end()) { + throw Exception(AVG_ERR_INVALID_ARGS, "No signal with ID "+toString(messageID)); + } + SubscriberInfoList& subscribers = m_SignalMap[messageID]; + return subscribers; +} + +void Publisher::throwSubscriberNotFound(MessageID messageID, int subscriberID) +{ + if (subscriberID == -1) { + throw Exception(AVG_ERR_INVALID_ARGS, "Signal with ID "+toString(messageID)+ + " doesn't have a subscriber with the given callable."); + } else { + throw Exception(AVG_ERR_INVALID_ARGS, "Signal with ID "+toString(messageID)+ + " doesn't have a subscriber with ID "+toString(subscriberID)); + } +} + +void Publisher::dumpSubscribers(MessageID messageID) +{ + SubscriberInfoList& subscribers = safeFindSubscribers(messageID); + SubscriberInfoList::iterator it; + for (it = subscribers.begin(); it != subscribers.end(); it++) { + cerr << (*it)->getID() << " "; + } + cerr << endl; +} + + +} diff --git a/src/player/Publisher.h b/src/player/Publisher.h new file mode 100644 index 0000000..1270544 --- /dev/null +++ b/src/player/Publisher.h @@ -0,0 +1,113 @@ +// +// libavg - Media Playback Engine. +// Copyright (C) 2003-2014 Ulrich von Zadow +// +// This library is free software; you can redistribute it and/or +// modify it under the terms of the GNU Lesser General Public +// License as published by the Free Software Foundation; either +// version 2 of the License, or (at your option) any later version. +// +// This library 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 +// Lesser General Public License for more details. +// +// You should have received a copy of the GNU Lesser General Public +// License along with this library; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +// +// Current versions can be found at www.libavg.de +// + +#ifndef _Publisher_H_ +#define _Publisher_H_ + +#include "../api.h" + +#include "ExportedObject.h" +#include "BoostPython.h" +#include "PublisherDefinition.h" +#include "MessageID.h" + +#include <boost/shared_ptr.hpp> + +// Python docs say python.h should be included before any standard headers (!) +#include "WrapPython.h" + +#include <list> +#include <map> + +namespace avg { + +class SubscriberInfo; +typedef boost::shared_ptr<SubscriberInfo> SubscriberInfoPtr; +typedef boost::weak_ptr<SubscriberInfo> SubscriberInfoWeakPtr; + +class Publisher; +typedef boost::shared_ptr<Publisher> PublisherPtr; + +class AVG_API Publisher: public ExportedObject +{ +public: + Publisher(); + Publisher(const std::string& sTypeName); + virtual ~Publisher(); + + int subscribe(MessageID messageID, const py::object& callable); + void unsubscribe(MessageID messageID, int subscriberID); + void unsubscribe1(int subscriberID); + void unsubscribeCallable(MessageID messageID, const py::object& callable); + int getNumSubscribers(MessageID messageID); + bool isSubscribed(MessageID messageID, int subscriberID); + bool isSubscribedCallable(MessageID messageID, const py::object& callable); + + // The following methods should really be protected, but python derived classes need + // to call them too. + void publish(MessageID messageID); + + void notifySubscribers(MessageID messageID); + void notifySubscribers(const std::string& sMsgName); + template<class ARG_TYPE> + void notifySubscribers(const std::string& sMsgName, const ARG_TYPE& arg); + void notifySubscribersPy(MessageID messageID, const py::list& args); + + static MessageID genMessageID(); + +protected: + void removeSubscribers(); + +private: + typedef std::list<SubscriberInfoWeakPtr> WeakSubscriberInfoList; + typedef std::list<SubscriberInfoPtr> SubscriberInfoList; + typedef std::map<MessageID, SubscriberInfoList> SignalMap; + + void unsubscribeIterator(MessageID messageID, SubscriberInfoList::iterator it); + SubscriberInfoList& safeFindSubscribers(MessageID messageID); + void throwSubscriberNotFound(MessageID messageID, int subscriberID); + void dumpSubscribers(MessageID messageID); + + PublisherDefinitionPtr m_pPublisherDef; + SignalMap m_SignalMap; + static int s_LastSubscriberID; + + typedef std::pair<MessageID, int> UnsubscribeDescription; +}; + +template<class ARG_TYPE> +void Publisher::notifySubscribers(const std::string& sMsgName, const ARG_TYPE& arg) +{ + MessageID messageID = m_pPublisherDef->getMessageID(sMsgName); + SubscriberInfoList& subscribers = safeFindSubscribers(messageID); + if (!subscribers.empty()) { + py::list args; + py::object pyArg(arg); + args.append(pyArg); + notifySubscribersPy(messageID, args); + } +} + + +} + +#endif + diff --git a/src/player/PublisherDefinition.cpp b/src/player/PublisherDefinition.cpp new file mode 100644 index 0000000..33fddf0 --- /dev/null +++ b/src/player/PublisherDefinition.cpp @@ -0,0 +1,90 @@ +// +// libavg - Media Playback Engine. +// Copyright (C) 2003-2014 Ulrich von Zadow +// +// This library is free software; you can redistribute it and/or +// modify it under the terms of the GNU Lesser General Public +// License as published by the Free Software Foundation; either +// version 2 of the License, or (at your option) any later version. +// +// This library 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 +// Lesser General Public License for more details. +// +// You should have received a copy of the GNU Lesser General Public +// License along with this library; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +// +// Current versions can be found at www.libavg.de +// + +#include "PublisherDefinition.h" + +#include "PublisherDefinitionRegistry.h" + +#include "../base/Exception.h" + +using namespace std; + +namespace avg { + +PublisherDefinition::PublisherDefinition(const string& sName, const string& sBaseName) + : m_sName(sName) +{ + if (sBaseName != "") { + PublisherDefinitionPtr pBaseDef = + PublisherDefinitionRegistry::get()->getDefinition(sBaseName); + m_MessageIDs = pBaseDef->m_MessageIDs; + } +} + +PublisherDefinition::~PublisherDefinition() +{ +} + +PublisherDefinitionPtr PublisherDefinition::create(const std::string& sName, + const std::string& sBaseName) +{ + PublisherDefinitionPtr pDef(new PublisherDefinition(sName, sBaseName)); + PublisherDefinitionRegistry::get()->registerDefinition(pDef); + return pDef; +} + +void PublisherDefinition::addMessage(const std::string& sName) +{ + m_MessageIDs.push_back(PublisherDefinitionRegistry::get()->genMessageID(sName)); +} + +const MessageID& PublisherDefinition::getMessageID(const std::string& sName) const +{ + for (unsigned i=0; i<m_MessageIDs.size(); ++i) { + if (m_MessageIDs[i].m_sName == sName) { + return m_MessageIDs[i]; + } + } + AVG_ASSERT_MSG(false, (string("Message named '")+sName+("' unknown.")).c_str()); + // Avoid compiler warning. + static MessageID nullMsg("", -1); + return nullMsg; +} + +const std::vector<MessageID>& PublisherDefinition::getMessageIDs() const +{ + return m_MessageIDs; +} + +const std::string& PublisherDefinition::getName() const +{ + return m_sName; +} + +void PublisherDefinition::dump() const +{ + cerr << m_sName << endl; + for (unsigned i=0; i<m_MessageIDs.size(); ++i) { + cerr << " " << m_MessageIDs[i].m_sName << ": " << m_MessageIDs[i].m_ID << endl; + } +} + +} diff --git a/src/player/PublisherDefinition.h b/src/player/PublisherDefinition.h new file mode 100644 index 0000000..a8d5e7e --- /dev/null +++ b/src/player/PublisherDefinition.h @@ -0,0 +1,62 @@ +// +// libavg - Media Playback Engine. +// Copyright (C) 2003-2014 Ulrich von Zadow +// +// This library is free software; you can redistribute it and/or +// modify it under the terms of the GNU Lesser General Public +// License as published by the Free Software Foundation; either +// version 2 of the License, or (at your option) any later version. +// +// This library 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 +// Lesser General Public License for more details. +// +// You should have received a copy of the GNU Lesser General Public +// License along with this library; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +// +// Current versions can be found at www.libavg.de +// + +#ifndef _PublisherDefinition_H_ +#define _PublisherDefinition_H_ + +#include "../api.h" + +#include "MessageID.h" + +#include <boost/shared_ptr.hpp> +#include <vector> +#include <string> + +namespace avg { + +class PublisherDefinition; +typedef boost::shared_ptr<PublisherDefinition> PublisherDefinitionPtr; + +class AVG_API PublisherDefinition +{ +public: + virtual ~PublisherDefinition(); + static PublisherDefinitionPtr create(const std::string& sName, + const std::string& sBaseName=""); + + void addMessage(const std::string& sName); + const MessageID& getMessageID(const std::string& sName) const; + const std::vector<MessageID> & getMessageIDs() const; + + const std::string& getName() const; + void dump() const; + +private: + PublisherDefinition(const std::string& sName, const std::string& sBaseName); + + std::string m_sName; + std::vector<MessageID> m_MessageIDs; +}; + +} + +#endif + diff --git a/src/player/PublisherDefinitionRegistry.cpp b/src/player/PublisherDefinitionRegistry.cpp new file mode 100644 index 0000000..3972a32 --- /dev/null +++ b/src/player/PublisherDefinitionRegistry.cpp @@ -0,0 +1,90 @@ +// +// libavg - Media Playback Engine. +// Copyright (C) 2003-2014 Ulrich von Zadow +// +// This library is free software; you can redistribute it and/or +// modify it under the terms of the GNU Lesser General Public +// License as published by the Free Software Foundation; either +// version 2 of the License, or (at your option) any later version. +// +// This library 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 +// Lesser General Public License for more details. +// +// You should have received a copy of the GNU Lesser General Public +// License along with this library; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +// +// Current versions can be found at www.libavg.de +// + +#include "PublisherDefinitionRegistry.h" + +#include "PublisherDefinition.h" + +#include "../base/Exception.h" + +using namespace std; + + +namespace avg { + +PublisherDefinitionRegistry* PublisherDefinitionRegistry::s_pInstance = 0; + +PublisherDefinitionRegistry::PublisherDefinitionRegistry() + : m_LastMessageID(-1) +{ + s_pInstance = this; + // The following should really happen in the player constructor, but the entries + // need to exist for the player to be constructed. + PublisherDefinitionPtr pPlayerDef = PublisherDefinition::create("Player"); + pPlayerDef->addMessage("KEY_DOWN"); + pPlayerDef->addMessage("KEY_UP"); + pPlayerDef->addMessage("PLAYBACK_START"); + pPlayerDef->addMessage("PLAYBACK_END"); + pPlayerDef->addMessage("ON_FRAME"); +} + +PublisherDefinitionRegistry::~PublisherDefinitionRegistry() +{ +} + +PublisherDefinitionRegistry* PublisherDefinitionRegistry::get() +{ + if (!s_pInstance) { + new PublisherDefinitionRegistry(); + } + return s_pInstance; +} + +void PublisherDefinitionRegistry::registerDefinition(PublisherDefinitionPtr def) +{ + m_Definitions.push_back(def); +} + +PublisherDefinitionPtr PublisherDefinitionRegistry::getDefinition(const string& sName) + const +{ + for (unsigned i=0; i<m_Definitions.size(); ++i) { + if (m_Definitions[i]->getName() == sName) { + return m_Definitions[i]; + } + } + AVG_ASSERT_MSG(false, (string("Can't find PublisherDefinition ")+sName).c_str()); + return PublisherDefinitionPtr(); +} + +void PublisherDefinitionRegistry::dump() const +{ + for (unsigned i=0; i<m_Definitions.size(); ++i) { + m_Definitions[i]->dump(); + } +} + +MessageID PublisherDefinitionRegistry::genMessageID(const string& sName) +{ + return MessageID(sName, ++m_LastMessageID); +} + +} diff --git a/src/player/PublisherDefinitionRegistry.h b/src/player/PublisherDefinitionRegistry.h new file mode 100644 index 0000000..8d3acac --- /dev/null +++ b/src/player/PublisherDefinitionRegistry.h @@ -0,0 +1,63 @@ +// +// libavg - Media Playback Engine. +// Copyright (C) 2003-2014 Ulrich von Zadow +// +// This library is free software; you can redistribute it and/or +// modify it under the terms of the GNU Lesser General Public +// License as published by the Free Software Foundation; either +// version 2 of the License, or (at your option) any later version. +// +// This library 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 +// Lesser General Public License for more details. +// +// You should have received a copy of the GNU Lesser General Public +// License along with this library; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +// +// Current versions can be found at www.libavg.de +// + +#ifndef _PublisherDefinitionRegistry_H_ +#define _PublisherDefinitionRegistry_H_ + +#include "../api.h" + +#include "MessageID.h" + +#include <boost/shared_ptr.hpp> +#include <vector> +#include <string> + +namespace avg { + +class PublisherDefinition; +typedef boost::shared_ptr<PublisherDefinition> PublisherDefinitionPtr; + +class AVG_API PublisherDefinitionRegistry +{ +public: + static PublisherDefinitionRegistry* get(); + virtual ~PublisherDefinitionRegistry(); + + void registerDefinition(PublisherDefinitionPtr def); + PublisherDefinitionPtr getDefinition(const std::string& sName) const; + + void dump() const; + + MessageID genMessageID(const std::string& sName=""); + +private: + PublisherDefinitionRegistry(); + std::vector<PublisherDefinitionPtr> m_Definitions; + int m_LastMessageID; + + static PublisherDefinitionRegistry* s_pInstance; +}; + +} + +#endif + + diff --git a/src/player/PythonLogSink.cpp b/src/player/PythonLogSink.cpp new file mode 100644 index 0000000..5da5829 --- /dev/null +++ b/src/player/PythonLogSink.cpp @@ -0,0 +1,90 @@ +// +// libavg - Media Playback Engine. +// Copyright (C) 2003-2014 Ulrich von Zadow +// +// This library is free software; you can redistribute it and/or +// modify it under the terms of the GNU Lesser General Public +// License as published by the Free Software Foundation; either +// version 2 of the License, or (at your option) any later version. +// +// This library 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 +// Lesser General Public License for more details. +// +// You should have received a copy of the GNU Lesser General Public +// License along with this library; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +// +// Current versions can be found at www.libavg.de + +#include "PythonLogSink.h" +#include "WrapPython.h" +#include "../base/Logger.h" + +#include <iostream> +#include <boost/algorithm/string.hpp> +#include <boost/python/errors.hpp> + +namespace avg +{ + +PythonLogSink::PythonLogSink(PyObject *pyLogger): + m_pyLogger(pyLogger) +{ + Py_INCREF(pyLogger); + assert(pyLogger); +} + +PythonLogSink::~PythonLogSink() +{ + Py_DecRef(m_pyLogger); +} + +const char * PythonLogSink::LogSeverityToPythonString(severity_t severity) +{ + if(severity == Logger::severity::CRITICAL) { + return "critical"; + } else if(severity == Logger::severity::ERROR) { + return "error"; + } else if(severity == Logger::severity::WARNING) { + return "warning"; + } else if(severity == Logger::severity::INFO) { + return "info"; + } else if(severity == Logger::severity::DEBUG) { + return "debug"; + } + throw Exception(AVG_ERR_UNKNOWN, "Unkown log severity"); +} + +void PythonLogSink::logMessage(const tm* pTime, unsigned millis, + const category_t& category, severity_t severity, const UTF8String& sMsg) +{ + try { + aquirePyGIL aquireGil; + PyObject * extra = PyDict_New(); + PyObject * pyCat = PyString_FromString(category.c_str()); + + PyDict_SetItemString(extra, "category", pyCat); + + PyObject * pyMsg = PyString_FromString(sMsg.c_str()); + PyObject * args = PyTuple_New(1); + PyObject * kwargs = PyDict_New(); + PyDict_SetItemString(kwargs, "extra", extra); + PyTuple_SetItem(args, 0, pyMsg); + + PyObject_Call(PyObject_GetAttrString(m_pyLogger, + LogSeverityToPythonString(severity)), args, kwargs); + + Py_DECREF(extra); + Py_DECREF(pyCat); + Py_DECREF(args); + Py_DECREF(kwargs); + } catch (const boost::python::error_already_set &) { + std::cerr << "PythonLogSink: Python raised exception\n"; + } catch (const exception &) { + std::cerr << "PythonLogSink: Couldn't log to python logger.\n"; + } +} + +} diff --git a/src/player/PythonLogSink.h b/src/player/PythonLogSink.h new file mode 100644 index 0000000..045eb4e --- /dev/null +++ b/src/player/PythonLogSink.h @@ -0,0 +1,46 @@ +// +// libavg - Media Playback Engine. +// Copyright (C) 2003-2014 Ulrich von Zadow +// +// This library is free software; you can redistribute it and/or +// modify it under the terms of the GNU Lesser General Public +// License as published by the Free Software Foundation; either +// version 2 of the License, or (at your option) any later version. +// +// This library 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 +// Lesser General Public License for more details. +// +// You should have received a copy of the GNU Lesser General Public +// License along with this library; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +// +// Current versions can be found at www.libavg.de + +#ifndef _PYTHONLOGHANDLER_H_ +#define _PYTHONLOGHANDLER_H_ + +#include "../base/ILogSink.h" +#include "../player/WrapPython.h" + +namespace avg +{ +class PythonLogSink: public ILogSink +{ +public: + PythonLogSink(PyObject *pyLogger); + virtual ~PythonLogSink (); + + virtual void logMessage(const tm* pTime, unsigned millis, const category_t& category, + severity_t severity, const UTF8String& sMsg); + +private: + + PyObject *m_pyLogger; + static const char * LogSeverityToPythonString(severity_t severity); +}; + +} + +#endif diff --git a/src/player/RasterNode.cpp b/src/player/RasterNode.cpp index 0bf304c..daace6b 100644 --- a/src/player/RasterNode.cpp +++ b/src/player/RasterNode.cpp @@ -1,6 +1,6 @@ // // libavg - Media Playback Engine. -// Copyright (C) 2003-2011 Ulrich von Zadow +// Copyright (C) 2003-2014 Ulrich von Zadow // // This library is free software; you can redistribute it and/or // modify it under the terms of the GNU Lesser General Public @@ -21,11 +21,13 @@ #include "RasterNode.h" -#include "NodeDefinition.h" +#include "TypeDefinition.h" #include "OGLSurface.h" #include "FXNode.h" #include "../graphics/ImagingProjection.h" +#include "../graphics/ShaderRegistry.h" +#include "../graphics/BitmapLoader.h" #include "../base/MathHelper.h" #include "../base/Logger.h" @@ -37,10 +39,9 @@ using namespace std; namespace avg { -NodeDefinition RasterNode::createDefinition() +void RasterNode::registerType() { - return NodeDefinition("rasternode") - .extendDefinition(AreaNode::createDefinition()) + TypeDefinition def = TypeDefinition("rasternode", "areanode") .addArg(Arg<int>("maxtilewidth", -1, false, offsetof(RasterNode, m_MaxTileSize.x))) .addArg(Arg<int>("maxtileheight", -1, false, @@ -49,24 +50,23 @@ NodeDefinition RasterNode::createDefinition() offsetof(RasterNode, m_sBlendMode))) .addArg(Arg<bool>("mipmap", false)) .addArg(Arg<UTF8String>("maskhref", "", false, offsetof(RasterNode, m_sMaskHref))) - .addArg(Arg<DPoint>("maskpos", DPoint(0,0), false, + .addArg(Arg<glm::vec2>("maskpos", glm::vec2(0,0), false, offsetof(RasterNode, m_MaskPos))) - .addArg(Arg<DPoint>("masksize", DPoint(0,0), false, + .addArg(Arg<glm::vec2>("masksize", glm::vec2(0,0), false, offsetof(RasterNode, m_MaskSize))) - .addArg(Arg<DTriple>("gamma", DTriple(1.0,1.0,1.0), false, + .addArg(Arg<glm::vec3>("gamma", glm::vec3(1.0f,1.0f,1.0f), false, offsetof(RasterNode, m_Gamma))) - .addArg(Arg<DTriple>("contrast", DTriple(1.0,1.0,1.0), false, + .addArg(Arg<glm::vec3>("contrast", glm::vec3(1.0f,1.0f,1.0f), false, offsetof(RasterNode, m_Contrast))) - .addArg(Arg<DTriple>("intensity", DTriple(1.0,1.0,1.0), false, + .addArg(Arg<glm::vec3>("intensity", glm::vec3(1.0f,1.0f,1.0f), false, offsetof(RasterNode, m_Intensity))); + TypeRegistry::get()->registerType(def); } RasterNode::RasterNode() : m_pSurface(0), m_Material(GL_CLAMP_TO_EDGE, GL_CLAMP_TO_EDGE, false), - m_bBound(false), m_TileSize(-1,-1), - m_pVertexes(0), m_bFXDirty(true) { } @@ -95,15 +95,12 @@ void RasterNode::setArgs(const ArgList& args) void RasterNode::connectDisplay() { - checkMaskSupport(m_sMaskHref); AreaNode::connectDisplay(); - m_pSurface->attach(); - m_bBound = false; if (m_MaxTileSize != IntPoint(-1, -1)) { m_TileSize = m_MaxTileSize; } - calcVertexGrid(m_TileVertices); + newSurface(); setBlendModeStr(m_sBlendMode); if (m_pMaskBmp) { downloadMask(); @@ -115,10 +112,6 @@ void RasterNode::connectDisplay() void RasterNode::disconnect(bool bKill) { - if (m_pVertexes) { - delete m_pVertexes; - m_pVertexes = 0; - } if (m_pSurface) { m_pSurface->destroy(); } @@ -143,13 +136,9 @@ void RasterNode::checkReload() m_sMaskFilename = sMaskFilename; try { if (m_sMaskFilename != "") { - AVG_TRACE(Logger::MEMORY, "Loading " << m_sMaskFilename); - m_pMaskBmp = BitmapPtr(new Bitmap(m_sMaskFilename)); - if (m_pMaskBmp->getPixelFormat() != I8) { - BitmapPtr pTempBmp = m_pMaskBmp; - m_pMaskBmp = BitmapPtr(new Bitmap(m_pMaskBmp->getSize(), I8)); - m_pMaskBmp->copyPixels(*pTempBmp); - } + AVG_TRACE(Logger::category::MEMORY, Logger::severity::INFO, + "Loading " << m_sMaskFilename); + m_pMaskBmp = loadBitmap(m_sMaskFilename, I8); setMaskCoords(); } } catch (Exception & ex) { @@ -158,9 +147,9 @@ void RasterNode::checkReload() } m_sMaskFilename = ""; if (getState() != Node::NS_UNCONNECTED) { - AVG_TRACE(Logger::ERROR, ex.getStr()); + AVG_LOG_ERROR(ex.getStr()); } else { - AVG_TRACE(Logger::MEMORY, ex.getStr()); + AVG_TRACE(Logger::category::MEMORY, Logger::severity::ERROR, ex.getStr()); } } if (m_sMaskFilename == "") { @@ -178,9 +167,6 @@ void RasterNode::checkReload() VertexGrid RasterNode::getOrigVertexCoords() { checkDisplayAvailable("getOrigVertexCoords"); - if (!m_bBound) { - bind(); - } VertexGrid grid; calcVertexGrid(grid); return grid; @@ -189,18 +175,12 @@ VertexGrid RasterNode::getOrigVertexCoords() VertexGrid RasterNode::getWarpedVertexCoords() { checkDisplayAvailable("getWarpedVertexCoords"); - if (!m_bBound) { - bind(); - } return m_TileVertices; } void RasterNode::setWarpedVertexCoords(const VertexGrid& grid) { checkDisplayAvailable("setWarpedVertexCoords"); - if (!m_bBound) { - bind(); - } bool bGridOK = true; IntPoint numTiles = getNumTiles(); if (grid.size() != (unsigned)(numTiles.y+1)) { @@ -216,7 +196,6 @@ void RasterNode::setWarpedVertexCoords(const VertexGrid& grid) "setWarpedVertexCoords() called with incorrect grid size."); } m_TileVertices = grid; - m_bVertexArrayDirty = true; } int RasterNode::getMaxTileWidth() const @@ -241,8 +220,15 @@ const std::string& RasterNode::getBlendModeStr() const void RasterNode::setBlendModeStr(const string& sBlendMode) { + GLContext::BlendMode blendMode = GLContext::stringToBlendMode(sBlendMode); + if (!GLContext::getMain()->isBlendModeSupported(blendMode)) { + m_sBlendMode = "blend"; + m_BlendMode = GLContext::BLEND_BLEND; + throw Exception(AVG_ERR_UNSUPPORTED, + "Min and max blend modes are not supported in this OpenGL configuration."); + } m_sBlendMode = sBlendMode; - m_BlendMode = GLContext::stringToBlendMode(sBlendMode); + m_BlendMode = blendMode; } const UTF8String& RasterNode::getMaskHRef() const @@ -252,36 +238,33 @@ const UTF8String& RasterNode::getMaskHRef() const void RasterNode::setMaskHRef(const UTF8String& sHref) { - if (GLContext::getCurrent()) { - checkMaskSupport(sHref); - } m_sMaskHref = sHref; checkReload(); } -const DPoint& RasterNode::getMaskPos() const +const glm::vec2& RasterNode::getMaskPos() const { return m_MaskPos; } -void RasterNode::setMaskPos(const DPoint& pos) +void RasterNode::setMaskPos(const glm::vec2& pos) { m_MaskPos = pos; setMaskCoords(); } -const DPoint& RasterNode::getMaskSize() const +const glm::vec2& RasterNode::getMaskSize() const { return m_MaskSize; } -void RasterNode::setMaskSize(const DPoint& size) +void RasterNode::setMaskSize(const glm::vec2& size) { m_MaskSize = size; setMaskCoords(); } -void RasterNode::getElementsByPos(const DPoint& pos, vector<NodeWeakPtr>& pElements) +void RasterNode::getElementsByPos(const glm::vec2& pos, vector<NodePtr>& pElements) { // Node isn't pickable if it's warped. if (m_MaxTileSize == IntPoint(-1, -1)) { @@ -289,12 +272,12 @@ void RasterNode::getElementsByPos(const DPoint& pos, vector<NodeWeakPtr>& pEleme } } -DTriple RasterNode::getGamma() const +glm::vec3 RasterNode::getGamma() const { return m_Gamma; } -void RasterNode::setGamma(const DTriple& gamma) +void RasterNode::setGamma(const glm::vec3& gamma) { m_Gamma = gamma; if (getState() == Node::NS_CANRENDER) { @@ -302,12 +285,12 @@ void RasterNode::setGamma(const DTriple& gamma) } } -DTriple RasterNode::getIntensity() const +glm::vec3 RasterNode::getIntensity() const { return m_Intensity; } -void RasterNode::setIntensity(const DTriple& intensity) +void RasterNode::setIntensity(const glm::vec3& intensity) { m_Intensity = intensity; if (getState() == Node::NS_CANRENDER) { @@ -315,12 +298,12 @@ void RasterNode::setIntensity(const DTriple& intensity) } } -DTriple RasterNode::getContrast() const +glm::vec3 RasterNode::getContrast() const { return m_Contrast; } -void RasterNode::setContrast(const DTriple& contrast) +void RasterNode::setContrast(const glm::vec3& contrast) { m_Contrast = contrast; if (getState() == Node::NS_CANRENDER) { @@ -342,16 +325,35 @@ void RasterNode::setEffect(FXNodePtr pFXNode) } } -void RasterNode::blt32(const DPoint& destSize, double opacity, - GLContext::BlendMode mode, bool bPremultipliedAlpha) +void RasterNode::calcVertexArray(const VertexArrayPtr& pVA, const Pixel32& color) +{ + if (isVisible() && m_pSurface->isCreated()) { + pVA->startSubVA(m_SubVA); + for (unsigned y = 0; y < m_TileVertices.size()-1; y++) { + for (unsigned x = 0; x < m_TileVertices[0].size()-1; x++) { + int curVertex = m_SubVA.getNumVerts(); + m_SubVA.appendPos(m_TileVertices[y][x], m_TexCoords[y][x], color); + m_SubVA.appendPos(m_TileVertices[y][x+1], m_TexCoords[y][x+1], color); + m_SubVA.appendPos(m_TileVertices[y+1][x+1], m_TexCoords[y+1][x+1], color); + m_SubVA.appendPos(m_TileVertices[y+1][x], m_TexCoords[y+1][x], color); + m_SubVA.appendQuadIndexes( + curVertex+1, curVertex, curVertex+2, curVertex+3); + } + } + } +} + +void RasterNode::blt32(const glm::mat4& transform, const glm::vec2& destSize, + float opacity, GLContext::BlendMode mode, bool bPremultipliedAlpha) { - blt(destSize, mode, opacity, Pixel32(255, 255, 255, 255), bPremultipliedAlpha); + blt(transform, destSize, mode, opacity, Pixel32(255, 255, 255, 255), + bPremultipliedAlpha); } -void RasterNode::blta8(const DPoint& destSize, double opacity, - const Pixel32& color, GLContext::BlendMode mode) +void RasterNode::blta8(const glm::mat4& transform, const glm::vec2& destSize, + float opacity, const Pixel32& color, GLContext::BlendMode mode) { - blt(destSize, mode, opacity, color, false); + blt(transform, destSize, mode, opacity, color, false); } GLContext::BlendMode RasterNode::getBlendMode() const @@ -383,25 +385,17 @@ void RasterNode::setMaskCoords() void RasterNode::calcMaskCoords() { - DPoint maskSize; - DPoint mediaSize = DPoint(getMediaSize()); - if (m_MaskSize == DPoint(0,0)) { - maskSize = DPoint(1,1); + glm::vec2 maskSize; + glm::vec2 mediaSize = glm::vec2(getMediaSize()); + if (m_MaskSize == glm::vec2(0,0)) { + maskSize = glm::vec2(1,1); } else { - maskSize = DPoint(m_MaskSize.x/mediaSize.x, m_MaskSize.y/mediaSize.y); + maskSize = glm::vec2(m_MaskSize.x/mediaSize.x, m_MaskSize.y/mediaSize.y); } - DPoint maskPos = DPoint(m_MaskPos.x/mediaSize.x, m_MaskPos.y/mediaSize.y); + glm::vec2 maskPos = glm::vec2(m_MaskPos.x/mediaSize.x, m_MaskPos.y/mediaSize.y); m_pSurface->setMaskCoords(maskPos, maskSize); } -void RasterNode::checkMaskSupport(const string& sHref) -{ - if (!(GLContext::getCurrent()->isUsingShaders()) && sHref != "") { - throw Exception(AVG_ERR_UNSUPPORTED, - "Can't use masks - unsupported on this hardware/driver combination."); - } -} - void RasterNode::downloadMask() { GLTexturePtr pTex(new GLTexture(m_pMaskBmp->getSize(), I8, @@ -410,64 +404,45 @@ void RasterNode::downloadMask() m_pSurface->setMask(pTex); } -void RasterNode::bind() -{ - if (!m_bBound) { - calcTexCoords(); - } - m_bBound = true; -} - static ProfilingZoneID FXProfilingZone("RasterNode::renderFX"); -void RasterNode::renderFX(const DPoint& destSize, const Pixel32& color, - bool bPremultipliedAlpha) +void RasterNode::renderFX(const glm::vec2& destSize, const Pixel32& color, + bool bPremultipliedAlpha, bool bForceRender) { - ScopeTimer Timer(FXProfilingZone); setupFX(false); - GLContext* pContext = GLContext::getCurrent(); - pContext->enableGLColorArray(false); - pContext->enableTexture(true); - if (m_pFXNode && (m_bFXDirty || m_pSurface->isDirty() || m_pFXNode->isDirty())) { - if (!m_bBound) { - bind(); - } + if (m_pFXNode && (m_bFXDirty || m_pSurface->isDirty() || m_pFXNode->isDirty() || + bForceRender)) + { + ScopeTimer Timer(FXProfilingZone); + GLContext* pContext = GLContext::getMain(); + StandardShader::get()->setAlpha(1.0f); m_pSurface->activate(getMediaSize()); m_pFBO->activate(); - clearGLBuffers(GL_COLOR_BUFFER_BIT); + clearGLBuffers(GL_COLOR_BUFFER_BIT, false); - glColor4d(double(color.getR())/256, double(color.getG())/256, - double(color.getB())/256, 1); if (bPremultipliedAlpha) { glproc::BlendColor(1.0f, 1.0f, 1.0f, 1.0f); } pContext->setBlendMode(GLContext::BLEND_BLEND, bPremultipliedAlpha); - - glMatrixMode(GL_MODELVIEW); - glPushMatrix(); - - m_pImagingProjection->activate(); - m_pImagingProjection->draw(); + m_pImagingProjection->setColor(color); + m_pImagingProjection->draw(StandardShader::get()->getShader()); /* static int i=0; stringstream ss; - ss << "foo" << i << ".png"; + ss << "node" << i << ".png"; BitmapPtr pBmp = m_pFBO->getImage(0); pBmp->save(ss.str()); - */ +*/ m_pFXNode->apply(m_pFBO->getTex()); - glPopMatrix(); - OGLErrorCheck(AVG_ERR_VIDEO_GENERAL, "RasterNode::renderFX(): glPopMatrix"); /* stringstream ss1; - ss1 << "bar" << ".png"; + ss1 << "nodefx" << i << ".png"; i++; m_pFXNode->getImage()->save(ss1.str()); */ - glproc::UseProgramObject(0); m_bFXDirty = false; m_pSurface->resetDirty(); m_pFXNode->resetDirty(); @@ -486,83 +461,71 @@ void RasterNode::checkDisplayAvailable(std::string sMsg) } } +void RasterNode::newSurface() +{ + if (m_pSurface->isCreated()) { + calcVertexGrid(m_TileVertices); + calcTexCoords(); + } +} + void RasterNode::setupFX(bool bNewFX) { if (m_pSurface && m_pSurface->getSize() != IntPoint(-1, -1) && m_pFXNode) { - if (!GLContext::getCurrent()->isUsingShaders()) { - throw Exception(AVG_ERR_UNSUPPORTED, - "Can't use FX - unsupported on this hardware/driver combination."); - } if (bNewFX || !m_pFBO || m_pFBO->getSize() != m_pSurface->getSize()) { m_pFXNode->setSize(m_pSurface->getSize()); m_pFXNode->connect(); m_bFXDirty = true; } if (!m_pFBO || m_pFBO->getSize() != m_pSurface->getSize()) { - m_pFBO = FBOPtr(new FBO(IntPoint(m_pSurface->getSize()), B8G8R8A8, 1, 1, - false, getMipmap())); + PixelFormat pf = BitmapLoader::get()->getDefaultPixelFormat(true); + m_pFBO = FBOPtr(new FBO(IntPoint(m_pSurface->getSize()), pf, 1, 1, false, + getMipmap())); GLTexturePtr pTex = m_pFBO->getTex(); + #ifndef AVG_ENABLE_EGL pTex->setWrapMode(GL_CLAMP_TO_BORDER, GL_CLAMP_TO_BORDER); + #endif m_pImagingProjection = ImagingProjectionPtr(new ImagingProjection( m_pSurface->getSize())); } } } -void RasterNode::blt(const DPoint& destSize, GLContext::BlendMode mode, - double opacity, const Pixel32& color, bool bPremultipliedAlpha) +void RasterNode::blt(const glm::mat4& transform, const glm::vec2& destSize, + GLContext::BlendMode mode, float opacity, const Pixel32& color, + bool bPremultipliedAlpha) { - if (!m_bBound) { - bind(); - } - GLContext* pContext = GLContext::getCurrent(); - pContext->enableGLColorArray(false); - pContext->enableTexture(true); - DRect destRect; + GLContext* pContext = GLContext::getMain(); + FRect destRect; + + StandardShaderPtr pShader = pContext->getStandardShader(); + pContext->setBlendColor(glm::vec4(1.0f, 1.0f, 1.0f, opacity)); + pShader->setAlpha(opacity); if (m_pFXNode) { - m_pFXNode->getTex()->activate(GL_TEXTURE0); - pContext->setBlendMode(mode, true); - glColor4d(1.0, 1.0, 1.0, opacity); - DRect relDestRect = m_pFXNode->getRelDestRect(); - destRect = DRect(relDestRect.tl.x*destSize.x, relDestRect.tl.y*destSize.y, + m_pFXNode->getTex()->activate(GL_TEXTURE0); + pShader->setColorModel(0); + pShader->disableColorspaceMatrix(); + pShader->setGamma(glm::vec4(1.0f, 1.0f, 1.0f, 1.0f)); + pShader->setPremultipliedAlpha(true); + pShader->setMask(false); + + FRect relDestRect = m_pFXNode->getRelDestRect(); + destRect = FRect(relDestRect.tl.x*destSize.x, relDestRect.tl.y*destSize.y, relDestRect.br.x*destSize.x, relDestRect.br.y*destSize.y); } else { m_pSurface->activate(getMediaSize(), bPremultipliedAlpha); pContext->setBlendMode(mode, bPremultipliedAlpha); - glColor4d(double(color.getR())/256, double(color.getG())/256, - double(color.getB())/256, opacity); - destRect = DRect(DPoint(0,0), destSize); - } - glproc::BlendColor(1.0f, 1.0f, 1.0f, float(opacity)); - glPushMatrix(); - glTranslated(destRect.tl.x, destRect.tl.y, 1); - glScaled(destRect.size().x, destRect.size().y, 1); - - if (m_bVertexArrayDirty) { - m_pVertexes->reset(); - for (unsigned y = 0; y < m_TileVertices.size()-1; y++) { - for (unsigned x = 0; x < m_TileVertices[0].size()-1; x++) { - int curVertex = m_pVertexes->getCurVert(); - m_pVertexes->appendPos(m_TileVertices[y][x], m_TexCoords[y][x]); - m_pVertexes->appendPos(m_TileVertices[y][x+1], m_TexCoords[y][x+1]); - m_pVertexes->appendPos(m_TileVertices[y+1][x+1], m_TexCoords[y+1][x+1]); - m_pVertexes->appendPos(m_TileVertices[y+1][x], m_TexCoords[y+1][x]); - m_pVertexes->appendQuadIndexes( - curVertex+1, curVertex, curVertex+2, curVertex+3); - } - } - m_bVertexArrayDirty = false; + destRect = FRect(glm::vec2(0,0), destSize); } + glm::vec3 pos(destRect.tl.x, destRect.tl.y, 0); + glm::vec3 scaleVec(destRect.size().x, destRect.size().y, 1); + glm::mat4 localTransform = glm::translate(transform, pos); + localTransform = glm::scale(localTransform, scaleVec); + pShader->setTransform(localTransform); + pShader->activate(); - m_pVertexes->draw(); - - glPopMatrix(); - OGLErrorCheck(AVG_ERR_VIDEO_GENERAL, "RasterNode::blt(): glPopMatrix 2"); - - PixelFormat pf = m_pSurface->getPixelFormat(); - AVG_TRACE(Logger::BLTS, "(" << destSize.x << ", " << destSize.y << ")" - << ", m_pf: " << pf); + m_SubVA.draw(); } IntPoint RasterNode::getNumTiles() @@ -571,38 +534,33 @@ IntPoint RasterNode::getNumTiles() if (m_TileSize.x == -1) { return IntPoint(1,1); } else { - return IntPoint(safeCeil(double(size.x)/m_TileSize.x), - safeCeil(double(size.y)/m_TileSize.y)); + return IntPoint(safeCeil(float(size.x)/m_TileSize.x), + safeCeil(float(size.y)/m_TileSize.y)); } } void RasterNode::calcVertexGrid(VertexGrid& grid) { IntPoint numTiles = getNumTiles(); - std::vector<DPoint> TileVerticesLine(numTiles.x+1); - grid = std::vector<std::vector<DPoint> > (numTiles.y+1, TileVerticesLine); + std::vector<glm::vec2> TileVerticesLine(numTiles.x+1); + grid = std::vector<std::vector<glm::vec2> > (numTiles.y+1, TileVerticesLine); for (unsigned y = 0; y < grid.size(); y++) { for (unsigned x = 0; x < grid[y].size(); x++) { calcTileVertex(x, y, grid[y][x]); } } - if (m_pVertexes) { - delete m_pVertexes; - } - m_bVertexArrayDirty = true; - m_pVertexes = new VertexArray(numTiles.x*numTiles.y*4, numTiles.x*numTiles.y*6); } -void RasterNode::calcTileVertex(int x, int y, DPoint& Vertex) +void RasterNode::calcTileVertex(int x, int y, glm::vec2& Vertex) { IntPoint numTiles = getNumTiles(); if (x < numTiles.x) { - Vertex.x = double(m_TileSize.x*x) / m_pSurface->getSize().x; + Vertex.x = float(m_TileSize.x*x) / m_pSurface->getSize().x; } else { Vertex.x = 1; } if (y < numTiles.y) { - Vertex.y = double(m_TileSize.y*y) / m_pSurface->getSize().y; + Vertex.y = float(m_TileSize.y*y) / m_pSurface->getSize().y; } else { Vertex.y = 1; } @@ -610,22 +568,22 @@ void RasterNode::calcTileVertex(int x, int y, DPoint& Vertex) void RasterNode::calcTexCoords() { - DPoint textureSize = DPoint(m_pSurface->getTextureSize()); - DPoint imageSize = DPoint(m_pSurface->getSize()); - DPoint texCoordExtents = DPoint(imageSize.x/textureSize.x, + glm::vec2 textureSize = glm::vec2(m_pSurface->getTextureSize()); + glm::vec2 imageSize = glm::vec2(m_pSurface->getSize()); + glm::vec2 texCoordExtents = glm::vec2(imageSize.x/textureSize.x, imageSize.y/textureSize.y); - DPoint texSizePerTile; + glm::vec2 texSizePerTile; if (m_TileSize.x == -1) { texSizePerTile = texCoordExtents; } else { - texSizePerTile = DPoint(double(m_TileSize.x)/imageSize.x*texCoordExtents.x, - double(m_TileSize.y)/imageSize.y*texCoordExtents.y); + texSizePerTile = glm::vec2(float(m_TileSize.x)/imageSize.x*texCoordExtents.x, + float(m_TileSize.y)/imageSize.y*texCoordExtents.y); } IntPoint numTiles = getNumTiles(); - vector<DPoint> texCoordLine(numTiles.x+1); - m_TexCoords = std::vector<std::vector<DPoint> > + vector<glm::vec2> texCoordLine(numTiles.x+1); + m_TexCoords = std::vector<std::vector<glm::vec2> > (numTiles.y+1, texCoordLine); for (unsigned y = 0; y < m_TexCoords.size(); y++) { for (unsigned x = 0; x < m_TexCoords[y].size(); x++) { @@ -641,6 +599,5 @@ void RasterNode::calcTexCoords() } } } - m_bVertexArrayDirty = true; } } diff --git a/src/player/RasterNode.h b/src/player/RasterNode.h index 92d9ac4..1e86e17 100644 --- a/src/player/RasterNode.h +++ b/src/player/RasterNode.h @@ -1,6 +1,6 @@ // // libavg - Media Playback Engine. -// Copyright (C) 2003-2011 Ulrich von Zadow +// Copyright (C) 2003-2014 Ulrich von Zadow // // This library is free software; you can redistribute it and/or // modify it under the terms of the GNU Lesser General Public @@ -27,10 +27,10 @@ #include "MaterialInfo.h" #include "../avgconfigwrapper.h" -#include "../base/Point.h" -#include "../base/Triple.h" +#include "../base/GLMHelper.h" #include "../base/UTF8String.h" #include "../graphics/GLContext.h" +#include "../graphics/SubVertexArray.h" #include <string> @@ -46,19 +46,19 @@ typedef boost::shared_ptr<GLTexture> GLTexturePtr; class FXNode; typedef boost::shared_ptr<FXNode> FXNodePtr; -typedef std::vector<std::vector<DPoint> > VertexGrid; +typedef std::vector<std::vector<glm::vec2> > VertexGrid; class AVG_API RasterNode: public AreaNode { public: - static NodeDefinition createDefinition(); + static void registerType(); virtual ~RasterNode (); virtual void connectDisplay(); virtual void setArgs(const ArgList& args); virtual void disconnect(bool bKill); virtual void checkReload(); - + // Warping support. VertexGrid getOrigVertexCoords(); VertexGrid getWarpedVertexCoords(); @@ -75,50 +75,55 @@ class AVG_API RasterNode: public AreaNode const UTF8String& getMaskHRef() const; void setMaskHRef(const UTF8String& sHref); - const DPoint& getMaskPos() const; - void setMaskPos(const DPoint& pos); + const glm::vec2& getMaskPos() const; + void setMaskPos(const glm::vec2& pos); - const DPoint& getMaskSize() const; - void setMaskSize(const DPoint& size); + const glm::vec2& getMaskSize() const; + void setMaskSize(const glm::vec2& size); - void getElementsByPos(const DPoint& pos, std::vector<NodeWeakPtr>& pElements); + void getElementsByPos(const glm::vec2& pos, std::vector<NodePtr>& pElements); - DTriple getGamma() const; - void setGamma(const DTriple& gamma); - DTriple getIntensity() const; - void setIntensity(const DTriple& intensity); - DTriple getContrast() const; - void setContrast(const DTriple& contrast); + glm::vec3 getGamma() const; + void setGamma(const glm::vec3& gamma); + glm::vec3 getIntensity() const; + void setIntensity(const glm::vec3& intensity); + glm::vec3 getContrast() const; + void setContrast(const glm::vec3& contrast); void setEffect(FXNodePtr pFXNode); protected: RasterNode(); - void blt32(const DPoint& destSize, double opacity, GLContext::BlendMode mode, - bool bPremultipliedAlpha = false); - void blta8(const DPoint& destSize, double opacity, + + void calcVertexArray(const VertexArrayPtr& pVA, + const Pixel32& color = Pixel32(0,0,0,0)); + void blt32(const glm::mat4& transform, const glm::vec2& destSize, float opacity, + GLContext::BlendMode mode, bool bPremultipliedAlpha = false); + void blta8(const glm::mat4& transform, const glm::vec2& destSize, float opacity, const Pixel32& color, GLContext::BlendMode mode); virtual OGLSurface * getSurface(); const MaterialInfo& getMaterial() const; bool hasMask() const; void setMaskCoords(); - void bind(); - void renderFX(const DPoint& destSize, const Pixel32& color, - bool bPremultipliedAlpha); + void renderFX(const glm::vec2& destSize, const Pixel32& color, + bool bPremultipliedAlpha, bool bForceRender=false); + + protected: + void newSurface(); + void setupFX(bool bNewFX); private: void downloadMask(); virtual void calcMaskCoords(); - void checkMaskSupport(const std::string& sHref); void checkDisplayAvailable(std::string sMsg); - void setupFX(bool bNewFX); - void blt(const DPoint& destSize, GLContext::BlendMode mode, - double opacity, const Pixel32& color, bool bPremultipliedAlpha); + void blt(const glm::mat4& transform, const glm::vec2& destSize, + GLContext::BlendMode mode, float opacity, const Pixel32& color, + bool bPremultipliedAlpha); IntPoint getNumTiles(); void calcVertexGrid(VertexGrid& grid); - void calcTileVertex(int x, int y, DPoint& Vertex); + void calcTileVertex(int x, int y, glm::vec2& Vertex); void calcTexCoords(); OGLSurface * m_pSurface; @@ -131,20 +136,17 @@ class AVG_API RasterNode: public AreaNode UTF8String m_sMaskHref; std::string m_sMaskFilename; BitmapPtr m_pMaskBmp; - DPoint m_MaskPos; - DPoint m_MaskSize; + glm::vec2 m_MaskPos; + glm::vec2 m_MaskSize; - bool m_bBound; - IntPoint m_TileSize; VertexGrid m_TileVertices; - bool m_bVertexArrayDirty; - VertexArray * m_pVertexes; - std::vector<std::vector<DPoint> > m_TexCoords; + SubVertexArray m_SubVA; + std::vector<std::vector<glm::vec2> > m_TexCoords; - DTriple m_Gamma; - DTriple m_Intensity; - DTriple m_Contrast; + glm::vec3 m_Gamma; + glm::vec3 m_Intensity; + glm::vec3 m_Contrast; FBOPtr m_pFBO; FXNodePtr m_pFXNode; diff --git a/src/player/RectNode.cpp b/src/player/RectNode.cpp index d7387df..980a957 100644 --- a/src/player/RectNode.cpp +++ b/src/player/RectNode.cpp @@ -1,6 +1,6 @@ // // libavg - Media Playback Engine. -// Copyright (C) 2003-2011 Ulrich von Zadow +// Copyright (C) 2003-2014 Ulrich von Zadow // // This library is free software; you can redistribute it and/or // modify it under the terms of the GNU Lesser General Public @@ -21,7 +21,7 @@ #include "RectNode.h" -#include "NodeDefinition.h" +#include "TypeDefinition.h" #include "../graphics/VertexArray.h" #include "../base/Exception.h" @@ -34,63 +34,66 @@ using namespace std; namespace avg { -NodeDefinition RectNode::createDefinition() +void RectNode::registerType() { - double texCoords[] = {0, 0.25, 0.5, 0.75, 1}; - return NodeDefinition("rect", Node::buildNode<RectNode>) - .extendDefinition(FilledVectorNode::createDefinition()) - .addArg(Arg<DPoint>("pos", DPoint(0,0), false, offsetof(RectNode, m_Rect.tl))) - .addArg(Arg<DPoint>("size", DPoint(0,0))) - .addArg(Arg<double>("angle", 0.0, false, offsetof(RectNode, m_Angle))) - .addArg(Arg<vector<double> >("texcoords", vectorFromCArray(5, texCoords), false, + float texCoords[] = {0, 0.25f, 0.5f, 0.75f, 1}; + TypeDefinition def = TypeDefinition("rect", "filledvectornode", + ExportedObject::buildObject<RectNode>) + .addArg(Arg<glm::vec2>("pos", glm::vec2(0,0), false, + offsetof(RectNode, m_Rect.tl))) + .addArg(Arg<glm::vec2>("size", glm::vec2(0,0))) + .addArg(Arg<float>("angle", 0.0f, false, offsetof(RectNode, m_Angle))) + .addArg(Arg<vector<float> >("texcoords", vectorFromCArray(5, texCoords), false, offsetof(RectNode, m_TexCoords))) ; + TypeRegistry::get()->registerType(def); } RectNode::RectNode(const ArgList& args) : FilledVectorNode(args) { args.setMembers(this); - setSize(args.getArgVal<DPoint>("size")); + setSize(args.getArgVal<glm::vec2>("size")); } RectNode::~RectNode() { } -const DPoint& RectNode::getPos() const +const glm::vec2& RectNode::getPos() const { return m_Rect.tl; } -void RectNode::setPos(const DPoint& pt) +void RectNode::setPos(const glm::vec2& pt) { - double w = m_Rect.width(); - double h = m_Rect.height(); + float w = m_Rect.width(); + float h = m_Rect.height(); m_Rect.tl = pt; m_Rect.setWidth(w); m_Rect.setHeight(h); setDrawNeeded(); } -DPoint RectNode::getSize() const +glm::vec2 RectNode::getSize() const { return m_Rect.size(); } -void RectNode::setSize(const DPoint& pt) +void RectNode::setSize(const glm::vec2& pt) { m_Rect.setWidth(pt.x); m_Rect.setHeight(pt.y); + notifySubscribers("SIZE_CHANGED", m_Rect.size()); setDrawNeeded(); } -const vector<double>& RectNode::getTexCoords() const +const vector<float>& RectNode::getTexCoords() const { return m_TexCoords; } -void RectNode::setTexCoords(const vector<double>& coords) +void RectNode::setTexCoords(const vector<float>& coords) { if (coords.size() != 5) { throw(Exception(AVG_ERR_OUT_OF_RANGE, @@ -100,64 +103,76 @@ void RectNode::setTexCoords(const vector<double>& coords) setDrawNeeded(); } -double RectNode::getAngle() const +float RectNode::getAngle() const { return m_Angle; } -void RectNode::setAngle(double angle) +void RectNode::setAngle(float angle) { - m_Angle = fmod(angle, 2*M_PI); + m_Angle = fmod(angle, 2*PI); setDrawNeeded(); } -void RectNode::getElementsByPos(const DPoint& pos, vector<NodeWeakPtr>& pElements) +glm::vec2 RectNode::toLocal(const glm::vec2& globalPos) const { - DPoint pivot = m_Rect.tl+m_Rect.size()/2; - DPoint rpos = pos.getRotatedPivot(m_Angle, pivot); - if (rpos.x >= m_Rect.tl.x && rpos.y >= m_Rect.tl.y && rpos.x < m_Rect.br.x && - rpos.y < m_Rect.br.y && reactsToMouseEvents()) + glm::vec2 localPos = globalPos - m_Rect.tl; + glm::vec2 pivot = m_Rect.size()/2.f; + return getRotatedPivot(localPos, -m_Angle, pivot); +} + +glm::vec2 RectNode::toGlobal(const glm::vec2& localPos) const +{ + glm::vec2 pivot = m_Rect.tl + m_Rect.size()/2.f; + glm::vec2 globalPos = getRotatedPivot(localPos, m_Angle, pivot); + return globalPos + m_Rect.tl; +} + +void RectNode::getElementsByPos(const glm::vec2& pos, vector<NodePtr>& pElements) +{ + if (pos.x >= 0 && pos.y >= 0 && pos.x < m_Rect.size().x && pos.y < m_Rect.size().y + && reactsToMouseEvents()) { - pElements.push_back(shared_from_this()); + pElements.push_back(getSharedThis()); } } -void RectNode::calcVertexes(VertexArrayPtr& pVertexArray, Pixel32 color) +void RectNode::calcVertexes(const VertexDataPtr& pVertexData, Pixel32 color) { - DPoint pivot = m_Rect.tl+m_Rect.size()/2; + glm::vec2 pivot = m_Rect.tl+m_Rect.size()/2.f; - DPoint p1 = m_Rect.tl; - DPoint p2(m_Rect.tl.x, m_Rect.br.y); - DPoint p3 = m_Rect.br; - DPoint p4(m_Rect.br.x, m_Rect.tl.y); + glm::vec2 p1 = m_Rect.tl; + glm::vec2 p2(m_Rect.tl.x, m_Rect.br.y); + glm::vec2 p3 = m_Rect.br; + glm::vec2 p4(m_Rect.br.x, m_Rect.tl.y); - vector<DPoint> pts; - pts.push_back(p1.getRotatedPivot(m_Angle, pivot)); - pts.push_back(p2.getRotatedPivot(m_Angle, pivot)); - pts.push_back(p3.getRotatedPivot(m_Angle, pivot)); - pts.push_back(p4.getRotatedPivot(m_Angle, pivot)); - calcPolyLine(pts, m_TexCoords, true, LJ_MITER, pVertexArray, color); -} - -void RectNode::calcFillVertexes(VertexArrayPtr& pVertexArray, Pixel32 color) -{ - DPoint pivot = m_Rect.tl+m_Rect.size()/2; - - DPoint p1 = m_Rect.tl; - DPoint p2(m_Rect.tl.x, m_Rect.br.y); - DPoint p3 = m_Rect.br; - DPoint p4(m_Rect.br.x, m_Rect.tl.y); - DPoint rp1 = p1.getRotatedPivot(m_Angle, pivot); - DPoint rp2 = p2.getRotatedPivot(m_Angle, pivot); - DPoint rp3 = p3.getRotatedPivot(m_Angle, pivot); - DPoint rp4 = p4.getRotatedPivot(m_Angle, pivot); - pVertexArray->appendPos(rp1, getFillTexCoord1(), color); - DPoint blTexCoord = DPoint(getFillTexCoord1().x, getFillTexCoord2().y); - pVertexArray->appendPos(rp2, blTexCoord, color); - pVertexArray->appendPos(rp3, getFillTexCoord2(), color); - DPoint trTexCoord = DPoint(getFillTexCoord2().x, getFillTexCoord1().y); - pVertexArray->appendPos(rp4, trTexCoord, color); - pVertexArray->appendQuadIndexes(1, 0, 2, 3); + vector<glm::vec2> pts; + pts.push_back(getRotatedPivot(p1, m_Angle, pivot)); + pts.push_back(getRotatedPivot(p2, m_Angle, pivot)); + pts.push_back(getRotatedPivot(p3, m_Angle, pivot)); + pts.push_back(getRotatedPivot(p4, m_Angle, pivot)); + calcPolyLine(pts, m_TexCoords, true, LJ_MITER, pVertexData, color); +} + +void RectNode::calcFillVertexes(const VertexDataPtr& pVertexData, Pixel32 color) +{ + glm::vec2 pivot = m_Rect.tl+m_Rect.size()/2.f; + + glm::vec2 p1 = m_Rect.tl; + glm::vec2 p2(m_Rect.tl.x, m_Rect.br.y); + glm::vec2 p3 = m_Rect.br; + glm::vec2 p4(m_Rect.br.x, m_Rect.tl.y); + glm::vec2 rp1 = getRotatedPivot(p1, m_Angle, pivot); + glm::vec2 rp2 = getRotatedPivot(p2, m_Angle, pivot); + glm::vec2 rp3 = getRotatedPivot(p3, m_Angle, pivot); + glm::vec2 rp4 = getRotatedPivot(p4, m_Angle, pivot); + pVertexData->appendPos(rp1, getFillTexCoord1(), color); + glm::vec2 blTexCoord = glm::vec2(getFillTexCoord1().x, getFillTexCoord2().y); + pVertexData->appendPos(rp2, blTexCoord, color); + pVertexData->appendPos(rp3, getFillTexCoord2(), color); + glm::vec2 trTexCoord = glm::vec2(getFillTexCoord2().x, getFillTexCoord1().y); + pVertexData->appendPos(rp4, trTexCoord, color); + pVertexData->appendQuadIndexes(1, 0, 2, 3); } } diff --git a/src/player/RectNode.h b/src/player/RectNode.h index 842bf35..f1a3c4e 100644 --- a/src/player/RectNode.h +++ b/src/player/RectNode.h @@ -1,6 +1,6 @@ // // libavg - Media Playback Engine. -// Copyright (C) 2003-2011 Ulrich von Zadow +// Copyright (C) 2003-2014 Ulrich von Zadow // // This library is free software; you can redistribute it and/or // modify it under the terms of the GNU Lesser General Public @@ -32,33 +32,35 @@ namespace avg { class AVG_API RectNode : public FilledVectorNode { public: - static NodeDefinition createDefinition(); + static void registerType(); RectNode(const ArgList& args); virtual ~RectNode(); - const DPoint& getPos() const; - void setPos(const DPoint& pt); + const glm::vec2& getPos() const; + void setPos(const glm::vec2& pt); - DPoint getSize() const; - void setSize(const DPoint& pt); + glm::vec2 getSize() const; + void setSize(const glm::vec2& pt); - const std::vector<double>& getTexCoords() const; - void setTexCoords(const std::vector<double>& coords); + const std::vector<float>& getTexCoords() const; + void setTexCoords(const std::vector<float>& coords); - double getAngle() const; - void setAngle(double angle); + float getAngle() const; + void setAngle(float angle); - void getElementsByPos(const DPoint& pos, std::vector<NodeWeakPtr>& pElements); + glm::vec2 toLocal(const glm::vec2& globalPos) const; + glm::vec2 toGlobal(const glm::vec2& localPos) const; + void getElementsByPos(const glm::vec2& pos, std::vector<NodePtr>& pElements); - virtual void calcVertexes(VertexArrayPtr& pVertexArray, Pixel32 color); - virtual void calcFillVertexes(VertexArrayPtr& pVertexArray, Pixel32 color); + virtual void calcVertexes(const VertexDataPtr& pVertexData, Pixel32 color); + virtual void calcFillVertexes(const VertexDataPtr& pVertexData, Pixel32 color); private: - DRect m_Rect; - std::vector<double> m_TexCoords; + FRect m_Rect; + std::vector<float> m_TexCoords; - double m_Angle; + float m_Angle; }; } diff --git a/src/player/SDLDisplayEngine.cpp b/src/player/SDLDisplayEngine.cpp index 0b6293f..74a3698 100644 --- a/src/player/SDLDisplayEngine.cpp +++ b/src/player/SDLDisplayEngine.cpp @@ -1,6 +1,6 @@ // libavg - Media Playback Engine. -// Copyright (C) 2003-2011 Ulrich von Zadow +// Copyright (C) 2003-2014 Ulrich von Zadow // // This library is free software; you can redistribute it and/or // modify it under the terms of the GNU Lesser General Public @@ -45,20 +45,19 @@ #include "../graphics/GLContext.h" #include "../graphics/Filterflip.h" #include "../graphics/Filterfliprgb.h" -#include "../graphics/ShaderRegistry.h" +#include "../graphics/Display.h" + +#include "../video/VideoDecoder.h" #include "OGLSurface.h" #include "OffscreenCanvas.h" -#include <SDL/SDL.h> - #ifdef __APPLE__ #include <ApplicationServices/ApplicationServices.h> #endif -#ifdef linux + +#include <SDL/SDL.h> #include <SDL/SDL_syswm.h> -#include <X11/extensions/xf86vmode.h> -#endif #ifdef __APPLE__ #include <OpenGL/OpenGL.h> @@ -68,6 +67,9 @@ #include <sys/ioctl.h> #include <sys/fcntl.h> #endif +#ifdef AVG_ENABLE_XINERAMA +#include <X11/extensions/Xinerama.h> +#endif #include <signal.h> #include <iostream> @@ -84,39 +86,43 @@ using namespace std; namespace avg { -double SDLDisplayEngine::s_RefreshRate = 0.0; - -void safeSetAttribute(SDL_GLattr attr, int value) +void SDLDisplayEngine::initSDL() { - int err = SDL_GL_SetAttribute(attr, value); +#ifdef __APPLE__ + static bool bSDLInitialized = false; + if (!bSDLInitialized) { + CustomSDLMain(); + bSDLInitialized = true; + } +#endif +#ifdef linux + // Disable all other video drivers (DirectFB, libcaca, ...) to avoid confusing + // error messages. + SDL_putenv((char*)"SDL_VIDEODRIVER=x11"); +#endif + int err = SDL_InitSubSystem(SDL_INIT_VIDEO); if (err == -1) { - throw Exception(AVG_ERR_VIDEO_GENERAL, SDL_GetError()); + throw Exception(AVG_ERR_VIDEO_INIT_FAILED, SDL_GetError()); } } +void SDLDisplayEngine::quitSDL() +{ +#ifndef _WIN32 + SDL_QuitSubSystem(SDL_INIT_VIDEO); +#endif +} + SDLDisplayEngine::SDLDisplayEngine() : IInputDevice(EXTRACT_INPUTDEVICE_CLASSNAME(SDLDisplayEngine)), m_WindowSize(0,0), - m_PPMM(0), m_pScreen(0), - m_VBMethod(VB_NONE), - m_VBMod(0), - m_bMouseOverApp(true), - m_pLastMouseEvent(new MouseEvent(Event::CURSORMOTION, false, false, false, - IntPoint(-1, -1), MouseEvent::NO_BUTTON, DPoint(-1, -1), 0)), - m_NumMouseButtonsDown(0) + m_pLastMouseEvent(new MouseEvent(Event::CURSOR_MOTION, false, false, false, + IntPoint(-1, -1), MouseEvent::NO_BUTTON, glm::vec2(-1, -1), 0)), + m_pGLContext(0) { -#ifdef __APPLE__ - static bool bSDLInitialized = false; - if (!bSDLInitialized) { - CustomSDLMain(); - bSDLInitialized = true; - } -#endif - if (SDL_InitSubSystem(SDL_INIT_VIDEO)==-1) { - AVG_TRACE(Logger::ERROR, "Can't init SDL display subsystem."); - exit(-1); - } + initSDL(); + m_Gamma[0] = 1.0; m_Gamma[1] = 1.0; m_Gamma[2] = 1.0; @@ -125,144 +131,102 @@ SDLDisplayEngine::SDLDisplayEngine() SDLDisplayEngine::~SDLDisplayEngine() { -#ifndef _WIN32 - SDL_QuitSubSystem(SDL_INIT_VIDEO); -#endif } void SDLDisplayEngine::init(const DisplayParams& dp, GLConfig glConfig) { - calcScreenDimensions(dp.m_DotsPerMM); + // This "fixes" the default behaviour of SDL under x11, avoiding it + // to report relative mouse coordinates when going fullscreen and + // the mouse cursor is hidden (grabbed). So far libavg and apps based + // on it don't use relative coordinates. + setEnv("SDL_MOUSE_RELATIVE", "0"); + + if (m_Gamma[0] != 1.0f || m_Gamma[1] != 1.0f || m_Gamma[2] != 1.0f) { + internalSetGamma(1.0f, 1.0f, 1.0f); + } stringstream ss; if (dp.m_Pos.x != -1) { ss << dp.m_Pos.x << "," << dp.m_Pos.y; setEnv("SDL_VIDEO_WINDOW_POS", ss.str().c_str()); } -#ifdef linux - IntPoint oldWindowSize = m_WindowSize; -#endif - double aspectRatio = double(dp.m_Size.x)/double(dp.m_Size.y); - if (dp.m_WindowSize == IntPoint(0, 0)) { - m_WindowSize = dp.m_Size; - } else if (dp.m_WindowSize.x == 0) { - m_WindowSize.x = int(dp.m_WindowSize.y*aspectRatio); - m_WindowSize.y = dp.m_WindowSize.y; - } else { - m_WindowSize.x = dp.m_WindowSize.x; - m_WindowSize.y = int(dp.m_WindowSize.x/aspectRatio); + m_WindowSize = dp.m_WindowSize; + unsigned int Flags = 0; + if (dp.m_bFullscreen) { + Flags |= SDL_FULLSCREEN; } + m_bIsFullscreen = dp.m_bFullscreen; + if (!dp.m_bHasWindowFrame) { + Flags |= SDL_NOFRAME; + } + +#ifndef linux + if (glConfig.m_bUseDebugContext) { + glConfig.m_bUseDebugContext = false; + } switch (dp.m_BPP) { - case 32: - safeSetAttribute(SDL_GL_RED_SIZE, 8); - safeSetAttribute(SDL_GL_GREEN_SIZE, 8); - safeSetAttribute(SDL_GL_BLUE_SIZE, 8); - safeSetAttribute(SDL_GL_BUFFER_SIZE, 32); - break; case 24: - safeSetAttribute(SDL_GL_RED_SIZE, 8); - safeSetAttribute(SDL_GL_GREEN_SIZE, 8); - safeSetAttribute(SDL_GL_BLUE_SIZE, 8); - safeSetAttribute(SDL_GL_BUFFER_SIZE, 24); + SDL_GL_SetAttribute(SDL_GL_RED_SIZE, 8); + SDL_GL_SetAttribute(SDL_GL_GREEN_SIZE, 8); + SDL_GL_SetAttribute(SDL_GL_BLUE_SIZE, 8); + SDL_GL_SetAttribute(SDL_GL_BUFFER_SIZE, 24); break; case 16: - safeSetAttribute(SDL_GL_RED_SIZE, 5); - safeSetAttribute(SDL_GL_GREEN_SIZE, 6); - safeSetAttribute(SDL_GL_BLUE_SIZE, 5); - safeSetAttribute(SDL_GL_BUFFER_SIZE, 16); - break; - case 15: - safeSetAttribute(SDL_GL_RED_SIZE, 5); - safeSetAttribute(SDL_GL_GREEN_SIZE, 5); - safeSetAttribute(SDL_GL_BLUE_SIZE, 5); - safeSetAttribute(SDL_GL_BUFFER_SIZE, 15); + SDL_GL_SetAttribute(SDL_GL_RED_SIZE, 5); + SDL_GL_SetAttribute(SDL_GL_GREEN_SIZE, 6); + SDL_GL_SetAttribute(SDL_GL_BLUE_SIZE, 5); + SDL_GL_SetAttribute(SDL_GL_BUFFER_SIZE, 16); break; default: - AVG_TRACE(Logger::ERROR, "Unsupported bpp " << dp.m_BPP << + AVG_LOG_ERROR("Unsupported bpp " << dp.m_BPP << "in SDLDisplayEngine::init()"); exit(-1); } - safeSetAttribute(SDL_GL_DEPTH_SIZE, 24); - safeSetAttribute(SDL_GL_STENCIL_SIZE, 8); - safeSetAttribute(SDL_GL_DOUBLEBUFFER, 1); + SDL_GL_SetAttribute(SDL_GL_DEPTH_SIZE, 0); + SDL_GL_SetAttribute(SDL_GL_STENCIL_SIZE, 8); + SDL_GL_SetAttribute(SDL_GL_DOUBLEBUFFER, 1); + SDL_GL_SetAttribute(SDL_GL_SWAP_CONTROL , 0); + Flags |= SDL_OPENGL; - unsigned int Flags = SDL_OPENGL; - if (dp.m_bFullscreen) { - Flags |= SDL_FULLSCREEN; - } - m_bIsFullscreen = dp.m_bFullscreen; - - if (!dp.m_bHasWindowFrame) { - Flags |= SDL_NOFRAME; - } - - bool bAllMultisampleValuesTested = false; m_pScreen = 0; - while (!bAllMultisampleValuesTested && !m_pScreen) { + while (glConfig.m_MultiSampleSamples && !m_pScreen) { if (glConfig.m_MultiSampleSamples > 1) { - safeSetAttribute(SDL_GL_MULTISAMPLEBUFFERS, 1); - safeSetAttribute(SDL_GL_MULTISAMPLESAMPLES, glConfig.m_MultiSampleSamples); + SDL_GL_SetAttribute(SDL_GL_MULTISAMPLEBUFFERS, 1); + SDL_GL_SetAttribute(SDL_GL_MULTISAMPLESAMPLES, + glConfig.m_MultiSampleSamples); } else { - safeSetAttribute(SDL_GL_MULTISAMPLEBUFFERS, 0); - safeSetAttribute(SDL_GL_MULTISAMPLESAMPLES, 0); + SDL_GL_SetAttribute(SDL_GL_MULTISAMPLEBUFFERS, 0); + SDL_GL_SetAttribute(SDL_GL_MULTISAMPLESAMPLES, 0); } m_pScreen = SDL_SetVideoMode(m_WindowSize.x, m_WindowSize.y, dp.m_BPP, Flags); if (!m_pScreen) { - switch (glConfig.m_MultiSampleSamples) { - case 1: - bAllMultisampleValuesTested = true; - break; - case 2: - glConfig.m_MultiSampleSamples = 1; - break; - case 4: - glConfig.m_MultiSampleSamples = 2; - break; - case 8: - glConfig.m_MultiSampleSamples = 4; - break; - default: - glConfig.m_MultiSampleSamples = 8; - break; - } + glConfig.m_MultiSampleSamples = GLContext::nextMultiSampleValue( + glConfig.m_MultiSampleSamples); } } +#else + // Linux version: Context created manually, not by SDL + m_pScreen = SDL_SetVideoMode(m_WindowSize.x, m_WindowSize.y, dp.m_BPP, Flags); +#endif if (!m_pScreen) { throw Exception(AVG_ERR_UNSUPPORTED, string("Setting SDL video mode failed: ") + SDL_GetError() + ". (size=" + toString(m_WindowSize) + ", bpp=" + - toString(dp.m_BPP) + ", multisamplesamples=" + - toString(glConfig.m_MultiSampleSamples) + ")."); + toString(dp.m_BPP) + ")."); } - m_pGLContext = GLContextPtr(new GLContext(true, glConfig)); + SDL_SysWMinfo info; + SDL_VERSION(&info.version); + int rc = SDL_GetWMInfo(&info); + AVG_ASSERT(rc != -1); + m_pGLContext = GLContext::create(glConfig, m_WindowSize, &info); + GLContext::setMain(m_pGLContext); #if defined(HAVE_XI2_1) || defined(HAVE_XI2_2) SDL_EventState(SDL_SYSWMEVENT, SDL_ENABLE); m_pXIMTInputDevice = 0; #endif SDL_WM_SetCaption("libavg", 0); - calcRefreshRate(); + Display::get()->getRefreshRate(); - glEnable(GL_BLEND); - OGLErrorCheck(AVG_ERR_VIDEO_GENERAL, "init: glEnable(GL_BLEND)"); - glShadeModel(GL_FLAT); - OGLErrorCheck(AVG_ERR_VIDEO_GENERAL, "init: glShadeModel(GL_FLAT)"); - glDisable(GL_DEPTH_TEST); - OGLErrorCheck(AVG_ERR_VIDEO_GENERAL, "init: glDisable(GL_DEPTH_TEST)"); - glEnable(GL_STENCIL_TEST); - OGLErrorCheck(AVG_ERR_VIDEO_GENERAL, "init: glEnable(GL_STENCIL_TEST)"); - glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE); - OGLErrorCheck(AVG_ERR_VIDEO_GENERAL, "init: glTexEnvf()"); - glPixelStorei(GL_UNPACK_ROW_LENGTH, 0); - glPixelStorei(GL_UNPACK_ALIGNMENT, 1); - glPixelStorei(GL_PACK_ROW_LENGTH, 0); - glPixelStorei(GL_PACK_ALIGNMENT, 1); - if (!queryOGLExtension("GL_ARB_vertex_buffer_object")) { - throw Exception(AVG_ERR_UNSUPPORTED, - "Graphics driver lacks vertex buffer support, unable to initialize graphics."); - } - - glEnableClientState(GL_VERTEX_ARRAY); - glEnableClientState(GL_TEXTURE_COORD_ARRAY); setGamma(dp.m_Gamma[0], dp.m_Gamma[1], dp.m_Gamma[2]); showCursor(dp.m_bShowCursor); if (dp.m_Framerate == 0) { @@ -275,11 +239,31 @@ void SDLDisplayEngine::init(const DisplayParams& dp, GLConfig glConfig) // SDL sets up a signal handler we really don't want. signal(SIGSEGV, SIG_DFL); m_pGLContext->logConfig(); + VideoDecoder::logConfig(); SDL_EnableUNICODE(1); - if (m_pGLContext->isUsingShaders()) { - OGLSurface::createShader(); +} + +IntPoint SDLDisplayEngine::calcWindowSize(const DisplayParams& dp) const +{ + float aspectRatio = float(dp.m_Size.x)/float(dp.m_Size.y); + IntPoint windowSize; + if (dp.m_WindowSize == IntPoint(0, 0)) { + windowSize = dp.m_Size; + } else if (dp.m_WindowSize.x == 0) { + windowSize.x = int(dp.m_WindowSize.y*aspectRatio); + windowSize.y = dp.m_WindowSize.y; + } else { + windowSize.x = dp.m_WindowSize.x; + windowSize.y = int(dp.m_WindowSize.x/aspectRatio); } + AVG_ASSERT(windowSize.x != 0 && windowSize.y != 0); + return windowSize; +} + +void SDLDisplayEngine::setWindowTitle(const string& sTitle) +{ + SDL_WM_SetCaption(sTitle.c_str(), 0); } #ifdef _WIN32 @@ -288,37 +272,28 @@ void SDLDisplayEngine::init(const DisplayParams& dp, GLConfig glConfig) void SDLDisplayEngine::teardown() { if (m_pScreen) { - if (m_Gamma[0] != 1.0 || m_Gamma[1] != 1.0 || m_Gamma[2] != 1.0) { - SDL_SetGamma(1.0, 1.0, 1.0); - } #ifdef linux // Workaround for broken mouse cursor on exit under Ubuntu 8.04. SDL_ShowCursor(SDL_ENABLE); -// SDL_SetVideoMode(m_WindowWidth, m_WindowHeight, 24, 0); #endif m_pScreen = 0; - m_pGLContext = GLContextPtr(); - } -} - -double SDLDisplayEngine::getRefreshRate() -{ - if (s_RefreshRate == 0.0) { - calcRefreshRate(); + if (m_pGLContext) { + delete m_pGLContext; + m_pGLContext = 0; + } + GLContext::setMain(0); } - return s_RefreshRate; } -void SDLDisplayEngine::setGamma(double red, double green, double blue) +void SDLDisplayEngine::setGamma(float red, float green, float blue) { if (red > 0) { - AVG_TRACE(Logger::CONFIG, "Setting gamma to " << red << ", " << green << ", " << blue); - int err = SDL_SetGamma(float(red), float(green), float(blue)); + bool bOk = internalSetGamma(red, green, blue); m_Gamma[0] = red; m_Gamma[1] = green; m_Gamma[2] = blue; - if (err == -1) { - AVG_TRACE(Logger::WARNING, "Unable to set display gamma."); + if (!bOk) { + AVG_LOG_WARNING("Unable to set display gamma."); } } } @@ -333,32 +308,17 @@ int SDLDisplayEngine::getKeyModifierState() const return SDL_GetModState(); } -void SDLDisplayEngine::calcScreenDimensions(double dotsPerMM) +bool SDLDisplayEngine::internalSetGamma(float red, float green, float blue) { - if (dotsPerMM != 0) { - const SDL_VideoInfo* pInfo = SDL_GetVideoInfo(); - m_ScreenResolution = IntPoint(pInfo->current_w, pInfo->current_h); - m_PPMM = dotsPerMM; - } - - if (m_PPMM == 0) { - const SDL_VideoInfo* pInfo = SDL_GetVideoInfo(); - m_ScreenResolution = IntPoint(pInfo->current_w, pInfo->current_h); -#ifdef WIN32 - HDC hdc = CreateDC("DISPLAY", NULL, NULL, NULL); - m_PPMM = GetDeviceCaps(hdc, LOGPIXELSX)/25.4; +#ifdef __APPLE__ + // Workaround for broken SDL_SetGamma for libSDL 1.2.15 under Lion + CGError err = CGSetDisplayTransferByFormula(kCGDirectMainDisplay, 0, 1, 1/red, + 0, 1, 1/green, 0, 1, 1/blue); + return (err == CGDisplayNoErr); #else - #ifdef linux - Display * pDisplay = XOpenDisplay(0); - DPoint displayMM(DisplayWidthMM(pDisplay,0), DisplayHeightMM(pDisplay,0)); - #elif defined __APPLE__ - CGSize size = CGDisplayScreenSize(CGMainDisplayID()); - DPoint displayMM(size.width, size.height); - #endif - // Non-Square pixels cause errors here. We'll fix that when it happens. - m_PPMM = m_ScreenResolution.x/displayMM.x; + int err = SDL_SetGamma(float(red), float(green), float(blue)); + return (err != -1); #endif - } } static ProfilingZoneID SwapBufferProfilingZone("Render - swap buffers"); @@ -366,9 +326,12 @@ static ProfilingZoneID SwapBufferProfilingZone("Render - swap buffers"); void SDLDisplayEngine::swapBuffers() { ScopeTimer timer(SwapBufferProfilingZone); +#ifdef linux + m_pGLContext->swapBuffers(); +#else SDL_GL_SwapBuffers(); - OGLErrorCheck(AVG_ERR_VIDEO_GENERAL, "swapBuffers()"); - AVG_TRACE(Logger::BLTS, "GL SwapBuffers"); +#endif + GLContext::checkError("swapBuffers()"); } void SDLDisplayEngine::showCursor(bool bShow) @@ -391,24 +354,35 @@ void SDLDisplayEngine::showCursor(bool bShow) BitmapPtr SDLDisplayEngine::screenshot(int buffer) { - BitmapPtr pBmp (new Bitmap(m_WindowSize, B8G8R8X8, "screenshot")); - string sTmp; - bool bBroken = getEnv("AVG_BROKEN_READBUFFER", sTmp); - GLenum buf = buffer; - if (!buffer) { - if (bBroken) { - // Workaround for buggy GL_FRONT on some machines. - buf = GL_BACK; - } else { - buf = GL_FRONT; + BitmapPtr pBmp; + glproc::BindFramebuffer(GL_FRAMEBUFFER, 0); + if (m_pGLContext->isGLES()) { + pBmp = BitmapPtr(new Bitmap(m_WindowSize, R8G8B8X8, "screenshot")); + glReadPixels(0, 0, m_WindowSize.x, m_WindowSize.y, GL_RGBA, GL_UNSIGNED_BYTE, + pBmp->getPixels()); + GLContext::checkError("SDLDisplayEngine::screenshot:glReadPixels()"); + } else { +#ifndef AVG_ENABLE_EGL + pBmp = BitmapPtr(new Bitmap(m_WindowSize, B8G8R8X8, "screenshot")); + string sTmp; + bool bBroken = getEnv("AVG_BROKEN_READBUFFER", sTmp); + GLenum buf = buffer; + if (!buffer) { + if (bBroken) { + // Workaround for buggy GL_FRONT on some machines. + buf = GL_BACK; + } else { + buf = GL_FRONT; + } } + glReadBuffer(buf); + GLContext::checkError("SDLDisplayEngine::screenshot:glReadBuffer()"); + glproc::BindBuffer(GL_PIXEL_PACK_BUFFER, 0); + glReadPixels(0, 0, m_WindowSize.x, m_WindowSize.y, GL_BGRA, GL_UNSIGNED_BYTE, + pBmp->getPixels()); + GLContext::checkError("SDLDisplayEngine::screenshot:glReadPixels()"); +#endif } - glReadBuffer(buf); - glproc::BindBuffer(GL_PIXEL_PACK_BUFFER_EXT, 0); - OGLErrorCheck(AVG_ERR_VIDEO_GENERAL, "SDLDisplayEngine::screenshot:glReadBuffer()"); - glReadPixels(0, 0, m_WindowSize.x, m_WindowSize.y, GL_BGRA, GL_UNSIGNED_BYTE, - pBmp->getPixels()); - OGLErrorCheck(AVG_ERR_VIDEO_GENERAL, "SDLDisplayEngine::screenshot:glReadPixels()"); FilterFlip().applyInPlace(pBmp); return pBmp; } @@ -418,172 +392,6 @@ IntPoint SDLDisplayEngine::getSize() return m_Size; } -void SDLDisplayEngine::initMacVBlank(int rate) -{ -#ifdef __APPLE__ - CGLContextObj context = CGLGetCurrentContext(); - AVG_ASSERT (context); -#if MAC_OS_X_VERSION_10_5 - GLint l = rate; -#else - long l = rate; -#endif - if (rate > 1) { - AVG_TRACE(Logger::WARNING, - "VBlank rate set to " << rate - << " but Mac OS X only supports 1. Assuming 1."); - l = 1; - } - CGLError err = CGLSetParameter(context, kCGLCPSwapInterval, &l); - AVG_ASSERT(!err); -#endif -} - -bool SDLDisplayEngine::initVBlank(int rate) -{ - if (rate > 0) { -#ifdef __APPLE__ - initMacVBlank(rate); - m_VBMethod = VB_APPLE; -#elif defined _WIN32 - if (queryOGLExtension("WGL_EXT_swap_control")) { - glproc::SwapIntervalEXT(rate); - m_VBMethod = VB_WIN; - } else { - AVG_TRACE(Logger::WARNING, - "Windows VBlank setup failed: OpenGL Extension not supported."); - m_VBMethod = VB_NONE; - } -#else - if (getenv("__GL_SYNC_TO_VBLANK") != 0) { - AVG_TRACE(Logger::WARNING, - "__GL_SYNC_TO_VBLANK set. This interferes with libavg vblank handling."); - m_VBMethod = VB_NONE; - } else { - if (queryGLXExtension("GLX_SGI_swap_control")) { - m_VBMethod = VB_SGI; - glproc::SwapIntervalSGI(rate); - - } else { - AVG_TRACE(Logger::WARNING, - "Linux VBlank setup failed: OpenGL Extension not supported."); - m_VBMethod = VB_NONE; - } - } -#endif - } else { - switch (m_VBMethod) { - case VB_APPLE: - initMacVBlank(0); - break; - case VB_WIN: -#ifdef _WIN32 - glproc::SwapIntervalEXT(0); -#endif - break; - case VB_SGI: -#ifdef linux - if (queryGLXExtension("GLX_SGI_swap_control")) { - glproc::SwapIntervalSGI(rate); - } -#endif - break; - default: - break; - } - m_VBMethod = VB_NONE; - } - switch(m_VBMethod) { - case VB_SGI: - AVG_TRACE(Logger::CONFIG, - " Using SGI OpenGL extension for vertical blank support."); - break; - case VB_APPLE: - AVG_TRACE(Logger::CONFIG, " Using Apple GL vertical blank support."); - break; - case VB_WIN: - AVG_TRACE(Logger::CONFIG, " Using Windows GL vertical blank support."); - break; - case VB_NONE: - AVG_TRACE(Logger::CONFIG, " Vertical blank support disabled."); - break; - default: - AVG_TRACE(Logger::WARNING, " Illegal vblank enum value."); - } - return m_VBMethod != VB_NONE; -} - -bool SDLDisplayEngine::vbWait(int rate) -{ - switch(m_VBMethod) { - case VB_SGI: - case VB_APPLE: - case VB_WIN: - return true; - case VB_NONE: - default: - AVG_ASSERT(false); - return false; - } -} - -void SDLDisplayEngine::calcRefreshRate() -{ - double lastRefreshRate = s_RefreshRate; - s_RefreshRate = 0; -#ifdef __APPLE__ - CFDictionaryRef modeInfo = CGDisplayCurrentMode(CGMainDisplayID()); - if (modeInfo) { - CFNumberRef value = (CFNumberRef) CFDictionaryGetValue(modeInfo, - kCGDisplayRefreshRate); - if (value) { - CFNumberGetValue(value, kCFNumberIntType, &s_RefreshRate); - if (s_RefreshRate < 1.0) { - AVG_TRACE(Logger::CONFIG, - "This seems to be a TFT screen, assuming 60 Hz refresh rate."); - s_RefreshRate = 60; - } - } else { - AVG_TRACE(Logger::WARNING, - "Apple refresh rate calculation (CFDictionaryGetValue) failed"); - } - } else { - AVG_TRACE(Logger::WARNING, - "Apple refresh rate calculation (CGDisplayCurrentMode) failed"); - } -#elif defined _WIN32 - // This isn't correct for multi-monitor systems. - HDC hDC = CreateDC("DISPLAY", NULL, NULL, NULL); - s_RefreshRate = GetDeviceCaps(hDC, VREFRESH); - if (s_RefreshRate < 2) { - s_RefreshRate = 60; - } - DeleteDC(hDC); -#else - Display * pDisplay = XOpenDisplay(0); - int pixelClock; - XF86VidModeModeLine modeLine; - bool bOK = XF86VidModeGetModeLine (pDisplay, DefaultScreen(pDisplay), - &pixelClock, &modeLine); - if (!bOK) { - AVG_TRACE (Logger::WARNING, - "Could not get current refresh rate (XF86VidModeGetModeLine failed)."); - AVG_TRACE (Logger::WARNING, - "Defaulting to 60 Hz refresh rate."); - } - double HSyncRate = pixelClock*1000.0/modeLine.htotal; - s_RefreshRate = HSyncRate/modeLine.vtotal; - XCloseDisplay(pDisplay); -#endif - if (s_RefreshRate == 0 || isnan(s_RefreshRate)) { - s_RefreshRate = 60; - } - if (lastRefreshRate != s_RefreshRate) { - AVG_TRACE(Logger::CONFIG, "Vertical Refresh Rate: " << s_RefreshRate); - } - -} - vector<long> SDLDisplayEngine::KeyCodeTranslationTable(SDLK_LAST, key::KEY_UNKNOWN); const char * getEventTypeName(unsigned char type) @@ -627,12 +435,14 @@ vector<EventPtr> SDLDisplayEngine::pollEvents() SDL_Event sdlEvent; vector<EventPtr> events; + int numEvents = 0; while (SDL_PollEvent(&sdlEvent)) { + numEvents++; EventPtr pNewEvent; switch (sdlEvent.type) { case SDL_MOUSEMOTION: - if (m_bMouseOverApp) { - pNewEvent = createMouseEvent(Event::CURSORMOTION, sdlEvent, + { + pNewEvent = createMouseEvent(Event::CURSOR_MOTION, sdlEvent, MouseEvent::NO_BUTTON); CursorEventPtr pNewCursorEvent = boost::dynamic_pointer_cast<CursorEvent>(pNewEvent); @@ -646,10 +456,10 @@ vector<EventPtr> SDLDisplayEngine::pollEvents() } break; case SDL_MOUSEBUTTONDOWN: - pNewEvent = createMouseButtonEvent(Event::CURSORDOWN, sdlEvent); + pNewEvent = createMouseButtonEvent(Event::CURSOR_DOWN, sdlEvent); break; case SDL_MOUSEBUTTONUP: - pNewEvent = createMouseButtonEvent(Event::CURSORUP, sdlEvent); + pNewEvent = createMouseButtonEvent(Event::CURSOR_UP, sdlEvent); break; case SDL_JOYAXISMOTION: // pNewEvent = createAxisEvent(sdlEvent)); @@ -661,10 +471,10 @@ vector<EventPtr> SDLDisplayEngine::pollEvents() // pNewEvent = createButtonEvent(Event::BUTTON_UP, sdlEvent)); break; case SDL_KEYDOWN: - pNewEvent = createKeyEvent(Event::KEYDOWN, sdlEvent); + pNewEvent = createKeyEvent(Event::KEY_DOWN, sdlEvent); break; case SDL_KEYUP: - pNewEvent = createKeyEvent(Event::KEYUP, sdlEvent); + pNewEvent = createKeyEvent(Event::KEY_UP, sdlEvent); break; case SDL_QUIT: pNewEvent = EventPtr(new Event(Event::QUIT, Event::NONE)); @@ -690,6 +500,10 @@ vector<EventPtr> SDLDisplayEngine::pollEvents() events.push_back(pNewEvent); } } + if (numEvents > 124) { + AVG_TRACE(Logger::category::EVENTS, Logger::severity::WARNING, + "SDL Event queue full, dropping events."); + } return events; } @@ -706,13 +520,13 @@ EventPtr SDLDisplayEngine::createMouseEvent(Event::Type type, const SDL_Event& s Uint8 buttonState = SDL_GetMouseState(&x, &y); x = int((x*m_Size.x)/m_WindowSize.x); y = int((y*m_Size.y)/m_WindowSize.y); - DPoint lastMousePos = m_pLastMouseEvent->getPos(); - DPoint speed; + glm::vec2 lastMousePos = m_pLastMouseEvent->getPos(); + glm::vec2 speed; if (lastMousePos.x == -1) { - speed = DPoint(0,0); + speed = glm::vec2(0,0); } else { - double lastFrameTime = 1000/getEffectiveFramerate(); - speed = DPoint(x-lastMousePos.x, y-lastMousePos.y)/lastFrameTime; + float lastFrameTime = 1000/getEffectiveFramerate(); + speed = glm::vec2(x-lastMousePos.x, y-lastMousePos.y)/lastFrameTime; } MouseEventPtr pEvent(new MouseEvent(type, (buttonState & SDL_BUTTON(1)) != 0, (buttonState & SDL_BUTTON(2)) != 0, (buttonState & SDL_BUTTON(3)) != 0, @@ -795,7 +609,8 @@ EventPtr SDLDisplayEngine::createKeyEvent(Event::Type type, const SDL_Event& sdl KeyEventPtr pEvent(new KeyEvent(type, sdlEvent.key.keysym.scancode, keyCode, - SDL_GetKeyName(sdlEvent.key.keysym.sym), sdlEvent.key.keysym.unicode, modifiers)); + SDL_GetKeyName(sdlEvent.key.keysym.sym), sdlEvent.key.keysym.unicode, + modifiers)); return pEvent; } @@ -1047,32 +862,4 @@ bool SDLDisplayEngine::isFullscreen() const return m_bIsFullscreen; } -IntPoint SDLDisplayEngine::getScreenResolution() -{ - calcScreenDimensions(); - return m_ScreenResolution; -} - -double SDLDisplayEngine::getPixelsPerMM() -{ - calcScreenDimensions(); - - return m_PPMM; -} - -DPoint SDLDisplayEngine::getPhysicalScreenDimensions() -{ - calcScreenDimensions(); - DPoint size; - DPoint screenRes = DPoint(getScreenResolution()); - size.x = screenRes.x/m_PPMM; - size.y = screenRes.y/m_PPMM; - return size; -} - -void SDLDisplayEngine::assumePixelsPerMM(double ppmm) -{ - m_PPMM = ppmm; -} - } diff --git a/src/player/SDLDisplayEngine.h b/src/player/SDLDisplayEngine.h index 7a824cb..90f31ed 100644 --- a/src/player/SDLDisplayEngine.h +++ b/src/player/SDLDisplayEngine.h @@ -1,6 +1,6 @@ // // libavg - Media Playback Engine. -// Copyright (C) 2003-2011 Ulrich von Zadow +// Copyright (C) 2003-2014 Ulrich von Zadow // // This library is free software; you can redistribute it and/or // modify it under the terms of the GNU Lesser General Public @@ -44,19 +44,22 @@ class XInputMTInputDevice; class MouseEvent; typedef boost::shared_ptr<class MouseEvent> MouseEventPtr; class GLContext; -typedef boost::shared_ptr<class GLContext> GLContextPtr; class AVG_API SDLDisplayEngine: public DisplayEngine, public IInputDevice { public: + static void initSDL(); + static void quitSDL(); SDLDisplayEngine(); virtual ~SDLDisplayEngine(); virtual void init(const DisplayParams& dp, GLConfig glConfig); + IntPoint calcWindowSize(const DisplayParams& dp) const; + + void setWindowTitle(const std::string& sTitle); // From DisplayEngine virtual void teardown(); - virtual double getRefreshRate(); - virtual void setGamma(double red, double green, double blue); + virtual void setGamma(float red, float green, float blue); virtual void setMousePos(const IntPoint& pos); virtual int getKeyModifierState() const; @@ -71,54 +74,32 @@ class AVG_API SDLDisplayEngine: public DisplayEngine, public IInputDevice const IntPoint& getWindowSize() const; bool isFullscreen() const; - IntPoint getScreenResolution(); - double getPixelsPerMM(); - DPoint getPhysicalScreenDimensions(); - void assumePixelsPerMM(double ppmm); virtual void swapBuffers(); private: - void initSDL(int width, int height, bool isFullscreen, int bpp); void initTranslationTable(); - void calcScreenDimensions(double dotsPerMM=0); + + bool internalSetGamma(float red, float green, float blue); EventPtr createMouseEvent (Event::Type Type, const SDL_Event & SDLEvent, long Button); - EventPtr createMouseButtonEvent - (Event::Type Type, const SDL_Event & SDLEvent); - EventPtr createKeyEvent - (Event::Type Type, const SDL_Event & SDLEvent); + EventPtr createMouseButtonEvent(Event::Type Type, const SDL_Event & SDLEvent); + EventPtr createKeyEvent(Event::Type Type, const SDL_Event & SDLEvent); IntPoint m_Size; bool m_bIsFullscreen; IntPoint m_WindowSize; - IntPoint m_ScreenResolution; - double m_PPMM; SDL_Surface * m_pScreen; - // Vertical blank stuff. - virtual bool initVBlank(int rate); - void initMacVBlank(int rate); - bool vbWait(int rate); - enum VBMethod {VB_SGI, VB_APPLE, VB_WIN, VB_NONE}; - VBMethod m_VBMethod; - int m_VBMod; - int m_LastVBCount; - - static void calcRefreshRate(); - static double s_RefreshRate; - // Event handling. - bool m_bMouseOverApp; MouseEventPtr m_pLastMouseEvent; - int m_NumMouseButtonsDown; static std::vector<long> KeyCodeTranslationTable; XInputMTInputDevice * m_pXIMTInputDevice; - GLContextPtr m_pGLContext; + GLContext* m_pGLContext; - double m_Gamma[3]; + float m_Gamma[3]; }; typedef boost::shared_ptr<SDLDisplayEngine> SDLDisplayEnginePtr; diff --git a/src/player/SVG.cpp b/src/player/SVG.cpp index 2a69560..9e778fa 100644 --- a/src/player/SVG.cpp +++ b/src/player/SVG.cpp @@ -1,6 +1,6 @@ // // libavg - Media Playback Engine. -// Copyright (C) 2003-2011 Ulrich von Zadow +// Copyright (C) 2003-2014 Ulrich von Zadow // // This library is free software; you can redistribute it and/or // modify it under the terms of the GNU Lesser General Public @@ -30,42 +30,40 @@ #include "../graphics/PixelFormat.h" #include "../graphics/Filterfill.h" +#include "../graphics/Filterfliprgb.h" #include "../graphics/FilterUnmultiplyAlpha.h" +#include "../graphics/BitmapLoader.h" #include "OGLSurface.h" #include "Player.h" #include "ImageNode.h" #include <glib-object.h> + +#ifndef RSVG_CAIRO_H #include <librsvg/rsvg-cairo.h> +#endif + #include <cairo.h> #include <iostream> -using namespace boost::python; using namespace std; namespace avg { -bool SVG::s_RSVGInitialized = false; - SVG::SVG(const UTF8String& sFilename, bool bUnescapeIllustratorIDs) : m_sFilename(sFilename), m_bUnescapeIllustratorIDs(bUnescapeIllustratorIDs) { - if (!s_RSVGInitialized) { - rsvg_init(); - s_RSVGInitialized = true; - } - - GError* pErr = new GError; + GError* pErr = 0; m_pRSVG = rsvg_handle_new_from_file(m_sFilename.c_str(), &pErr); if (!m_pRSVG) { throw Exception(AVG_ERR_INVALID_ARGS, string("Could not open svg file: ") + m_sFilename); + g_error_free(pErr); } - delete pErr; } SVG::~SVG() @@ -78,52 +76,58 @@ BitmapPtr SVG::renderElement(const UTF8String& sElementID) return renderElement(sElementID, 1); } -BitmapPtr SVG::renderElement(const UTF8String& sElementID, const DPoint& size) +BitmapPtr SVG::renderElement(const UTF8String& sElementID, const glm::vec2& size) { SVGElementPtr pElement = getElement(sElementID); - DPoint elementSize = pElement->getSize(); + glm::vec2 elementSize = pElement->getSize(); return internalRenderElement(pElement, size, elementSize); } -BitmapPtr SVG::renderElement(const UTF8String& sElementID, double scale) +BitmapPtr SVG::renderElement(const UTF8String& sElementID, float scale) { SVGElementPtr pElement = getElement(sElementID); - DPoint size = pElement->getSize(); - DPoint renderSize = size * scale; + glm::vec2 size = pElement->getSize(); + glm::vec2 renderSize = size * scale; return internalRenderElement(pElement, renderSize, size); } -NodePtr SVG::createImageNode(const UTF8String& sElementID, const dict& nodeAttrs) +NodePtr SVG::createImageNode(const UTF8String& sElementID, const py::dict& nodeAttrs) { BitmapPtr pBmp = renderElement(sElementID); return createImageNodeFromBitmap(pBmp, nodeAttrs); } -NodePtr SVG::createImageNode(const UTF8String& sElementID, const dict& nodeAttrs, - const DPoint& renderSize) +NodePtr SVG::createImageNode(const UTF8String& sElementID, const py::dict& nodeAttrs, + const glm::vec2& renderSize) { BitmapPtr pBmp = renderElement(sElementID, renderSize); return createImageNodeFromBitmap(pBmp, nodeAttrs); } -NodePtr SVG::createImageNode(const UTF8String& sElementID, const dict& nodeAttrs, - double scale) +NodePtr SVG::createImageNode(const UTF8String& sElementID, const py::dict& nodeAttrs, + float scale) { BitmapPtr pBmp = renderElement(sElementID, scale); return createImageNodeFromBitmap(pBmp, nodeAttrs); } -DPoint SVG::getElementSize(const UTF8String& sElementID) +glm::vec2 SVG::getElementPos(const UTF8String& sElementID) +{ + SVGElementPtr pElement = getElement(sElementID); + return pElement->getPos(); +} + +glm::vec2 SVG::getElementSize(const UTF8String& sElementID) { SVGElementPtr pElement = getElement(sElementID); return pElement->getSize(); } BitmapPtr SVG::internalRenderElement(const SVGElementPtr& pElement, - const DPoint& renderSize, const DPoint& size) + const glm::vec2& renderSize, const glm::vec2& size) { - DPoint pos = pElement->getPos(); - DPoint scale(renderSize.x/size.x, renderSize.y/size.y); + glm::vec2 pos = pElement->getPos(); + glm::vec2 scale(renderSize.x/size.x, renderSize.y/size.y); IntPoint boundingBox = IntPoint(renderSize) + IntPoint(int(scale.x+0.5), int(scale.y+0.5)); BitmapPtr pBmp(new Bitmap(boundingBox, B8G8R8A8)); @@ -143,11 +147,15 @@ BitmapPtr SVG::internalRenderElement(const SVGElementPtr& pElement, cairo_surface_destroy(pSurface); cairo_destroy(pCairo); - + + if (!BitmapLoader::get()->isBlueFirst()) { + FilterFlipRGB().applyInPlace(pBmp); + } + return pBmp; } -NodePtr SVG::createImageNodeFromBitmap(BitmapPtr pBmp, const dict& nodeAttrs) +NodePtr SVG::createImageNodeFromBitmap(BitmapPtr pBmp, const py::dict& nodeAttrs) { ImageNodePtr pNode = boost::dynamic_pointer_cast<ImageNode>( Player::get()->createNode("image", nodeAttrs)); diff --git a/src/player/SVG.h b/src/player/SVG.h index cc38620..73f0d55 100644 --- a/src/player/SVG.h +++ b/src/player/SVG.h @@ -1,6 +1,6 @@ // // libavg - Media Playback Engine. -// Copyright (C) 2003-2011 Ulrich von Zadow +// Copyright (C) 2003-2014 Ulrich von Zadow // // This library is free software; you can redistribute it and/or // modify it under the terms of the GNU Lesser General Public @@ -48,29 +48,28 @@ public: virtual ~SVG(); BitmapPtr renderElement(const UTF8String& sElementID); - BitmapPtr renderElement(const UTF8String& sElementID, const DPoint& size); - BitmapPtr renderElement(const UTF8String& sElementID, double scale); + BitmapPtr renderElement(const UTF8String& sElementID, const glm::vec2& size); + BitmapPtr renderElement(const UTF8String& sElementID, float scale); NodePtr createImageNode(const UTF8String& sElementID, - const boost::python::dict& nodeAttrs); + const py::dict& nodeAttrs); NodePtr createImageNode(const UTF8String& sElementID, - const boost::python::dict& nodeAttrs, const DPoint& renderSize); + const py::dict& nodeAttrs, const glm::vec2& renderSize); NodePtr createImageNode(const UTF8String& sElementID, - const boost::python::dict& nodeAttrs, double scale); - DPoint getElementSize(const UTF8String& sElementID); + const py::dict& nodeAttrs, float scale); + glm::vec2 getElementPos(const UTF8String& sElementID); + glm::vec2 getElementSize(const UTF8String& sElementID); private: BitmapPtr internalRenderElement(const SVGElementPtr& pElement, - const DPoint& renderSize, const DPoint& size); + const glm::vec2& renderSize, const glm::vec2& size); NodePtr createImageNodeFromBitmap(BitmapPtr pBmp, - const boost::python::dict& nodeAttrs); + const py::dict& nodeAttrs); SVGElementPtr getElement(const UTF8String& sElementID); std::map<UTF8String, SVGElementPtr> m_ElementMap; UTF8String m_sFilename; bool m_bUnescapeIllustratorIDs; RsvgHandle* m_pRSVG; - - static bool s_RSVGInitialized; }; } diff --git a/src/player/SVGElement.cpp b/src/player/SVGElement.cpp index 6531431..dc0ba28 100644 --- a/src/player/SVGElement.cpp +++ b/src/player/SVGElement.cpp @@ -1,6 +1,6 @@ // // libavg - Media Playback Engine. -// Copyright (C) 2003-2011 Ulrich von Zadow +// Copyright (C) 2003-2014 Ulrich von Zadow // // This library is free software; you can redistribute it and/or // modify it under the terms of the GNU Lesser General Public @@ -36,11 +36,11 @@ SVGElement::SVGElement(RsvgHandle* pRSVG, const UTF8String& sFilename, RsvgPositionData pos; rsvg_handle_get_position_sub(pRSVG, &pos, m_sUnescapedID.c_str()); - m_Pos = DPoint(pos.x, pos.y); + m_Pos = glm::vec2(pos.x, pos.y); RsvgDimensionData dim; rsvg_handle_get_dimensions_sub(pRSVG, &dim, m_sUnescapedID.c_str()); - m_Size = DPoint(dim.width+1, dim.height+1); + m_Size = glm::vec2(dim.width+1, dim.height+1); } const UTF8String& SVGElement::getUnescapedID() const @@ -48,12 +48,12 @@ const UTF8String& SVGElement::getUnescapedID() const return m_sUnescapedID; } -const DPoint& SVGElement::getPos() const +const glm::vec2& SVGElement::getPos() const { return m_Pos; } -const DPoint& SVGElement::getSize() const +const glm::vec2& SVGElement::getSize() const { return m_Size; } @@ -66,16 +66,18 @@ UTF8String SVGElement::unescapeID(RsvgHandle* pRSVG, const UTF8String& sFilename vector<string> sPossibleIDs; sPossibleIDs.push_back(sResult); string::size_type pos = sResult.find("_"); - while (pos != UTF8String::npos) { - sResult.replace(pos, 1, "_x5F_"); - pos = sResult.find("_", pos+5); + if (pos != UTF8String::npos) { + while (pos != UTF8String::npos) { + sResult.replace(pos, 1, "_x5F_"); + pos = sResult.find("_", pos+5); + } + sPossibleIDs.push_back(sResult); } // Illustrator adds suffixes to IDs to get rid of duplicates. Even after the // duplicates are removed, the suffixes remain :-(. // We handle two cases here: // 1) If there is only one version with a suffix, we take that version. // 2) If there are duplicate IDs, we warn. - sPossibleIDs.push_back(sResult); for (int i=1; i<30; ++i) { string sTempID = sResult + "_" + toString(i) + "_"; sPossibleIDs.push_back(sTempID); @@ -92,8 +94,7 @@ UTF8String SVGElement::unescapeID(RsvgHandle* pRSVG, const UTF8String& sFilename throwIDNotFound(sFilename, sElementID); } if (numFound > 1) { - AVG_TRACE(Logger::WARNING, - "svg file '" << sFilename << + AVG_LOG_WARNING("svg file '" << sFilename << "' has more than one element with id '" << sElementID << "'."); } } else { diff --git a/src/player/SVGElement.h b/src/player/SVGElement.h index 8eda90d..280df6b 100644 --- a/src/player/SVGElement.h +++ b/src/player/SVGElement.h @@ -1,6 +1,6 @@ // // libavg - Media Playback Engine. -// Copyright (C) 2003-2011 Ulrich von Zadow +// Copyright (C) 2003-2014 Ulrich von Zadow // // This library is free software; you can redistribute it and/or // modify it under the terms of the GNU Lesser General Public @@ -25,7 +25,7 @@ #include "../api.h" #include "../base/UTF8String.h" -#include "../base/Point.h" +#include "../base/GLMHelper.h" #include <librsvg/rsvg.h> #include <boost/shared_ptr.hpp> @@ -41,8 +41,8 @@ public: const UTF8String& sElementID, bool bUnescapeIllustratorIDs); const UTF8String& getUnescapedID() const; - const DPoint& getPos() const; - const DPoint& getSize() const; + const glm::vec2& getPos() const; + const glm::vec2& getSize() const; private: UTF8String unescapeID(RsvgHandle* pRSVG, const UTF8String& sFilename, @@ -50,8 +50,8 @@ private: void throwIDNotFound(const UTF8String& sFilename, const UTF8String& sElementID); UTF8String m_sUnescapedID; - DPoint m_Pos; - DPoint m_Size; + glm::vec2 m_Pos; + glm::vec2 m_Size; }; typedef boost::shared_ptr<SVGElement> SVGElementPtr; diff --git a/src/player/ShadowFXNode.cpp b/src/player/ShadowFXNode.cpp index 703a901..30ef766 100644 --- a/src/player/ShadowFXNode.cpp +++ b/src/player/ShadowFXNode.cpp @@ -1,6 +1,6 @@ // // libavg - Media Playback Engine. -// Copyright (C) 2003-2011 Ulrich von Zadow +// Copyright (C) 2003-2014 Ulrich von Zadow // // This library is free software; you can redistribute it and/or // modify it under the terms of the GNU Lesser General Public @@ -23,7 +23,6 @@ #include "../base/ObjectCounter.h" #include "../base/Exception.h" -#include "../graphics/ShaderRegistry.h" #include <string> @@ -31,18 +30,15 @@ using namespace std; namespace avg { -ShadowFXNode::ShadowFXNode() - : FXNode(), - m_Offset(0,0), - m_StdDev(1), - m_Opacity(1), - m_Color(255,255,255,255) +ShadowFXNode::ShadowFXNode(glm::vec2 offset, float radius, float opacity, string sColor) + : FXNode(false), + m_Offset(offset), + m_StdDev(radius), + m_Opacity(opacity) { + m_sColorName = sColor; + m_Color = colorStringToColor(sColor); ObjectCounter::get()->incRef(&typeid(*this)); - if (!GLTexture::isFloatFormatSupported()) { - throw Exception(AVG_ERR_UNSUPPORTED, - "OpenGL configuration doesn't support Shadow (no float textures)."); - } } ShadowFXNode::~ShadowFXNode() @@ -52,10 +48,6 @@ ShadowFXNode::~ShadowFXNode() void ShadowFXNode::connect() { - if (!GLTexture::isFloatFormatSupported()) { - throw Exception(AVG_ERR_UNSUPPORTED, - "Cannot create ShadowFX: OpenGL configuration doesn't support Blur (no float textures)."); - } FXNode::connect(); } @@ -65,46 +57,35 @@ void ShadowFXNode::disconnect() FXNode::disconnect(); } -void ShadowFXNode::setParams(const DPoint& offset, double stdDev, double opacity, - const string& sColor) -{ - m_Offset = offset; - m_StdDev = stdDev; - m_Opacity = opacity; - m_sColorName = sColor; - m_Color = colorStringToColor(sColor); - updateFilter(); -} - -void ShadowFXNode::setOffset(const DPoint& offset) +void ShadowFXNode::setOffset(const glm::vec2& offset) { m_Offset = offset; updateFilter(); } -DPoint ShadowFXNode::getOffset() const +glm::vec2 ShadowFXNode::getOffset() const { return m_Offset; } -void ShadowFXNode::setRadius(double radius) +void ShadowFXNode::setRadius(float radius) { m_StdDev = radius; updateFilter(); } -double ShadowFXNode::getRadius() const +float ShadowFXNode::getRadius() const { return m_StdDev; } -void ShadowFXNode::setOpacity(double opacity) +void ShadowFXNode::setOpacity(float opacity) { m_Opacity = opacity; updateFilter(); } -double ShadowFXNode::getOpacity() const +float ShadowFXNode::getOpacity() const { return m_Opacity; } diff --git a/src/player/ShadowFXNode.h b/src/player/ShadowFXNode.h index bd5a19c..e0bd77a 100644 --- a/src/player/ShadowFXNode.h +++ b/src/player/ShadowFXNode.h @@ -1,6 +1,6 @@ // // libavg - Media Playback Engine. -// Copyright (C) 2003-2011 Ulrich von Zadow +// Copyright (C) 2003-2014 Ulrich von Zadow // // This library is free software; you can redistribute it and/or // modify it under the terms of the GNU Lesser General Public @@ -26,6 +26,7 @@ #include "FXNode.h" #include "../graphics/GPUShadowFilter.h" +#include "../base/GLMHelper.h" #include <boost/shared_ptr.hpp> #include <string> @@ -34,20 +35,19 @@ namespace avg { class AVG_API ShadowFXNode: public FXNode { public: - ShadowFXNode(); + ShadowFXNode(glm::vec2 offset=glm::vec2(0,0), float radius=1.f, float opacity=1.f, + std::string sColor="FFFFFF"); virtual ~ShadowFXNode(); virtual void connect(); virtual void disconnect(); - void setParams(const DPoint& offset, double stdDev, double opacity, - const std::string& sColor); - void setOffset(const DPoint& offset); - DPoint getOffset() const; - void setRadius(double radius); - double getRadius() const; - void setOpacity(double opacity); - double getOpacity() const; + void setOffset(const glm::vec2& offset); + glm::vec2 getOffset() const; + void setRadius(float radius); + float getRadius() const; + void setOpacity(float opacity); + float getOpacity() const; void setColor(const std::string& sColor); std::string getColor() const; @@ -57,9 +57,9 @@ private: GPUShadowFilterPtr m_pFilter; - DPoint m_Offset; - double m_StdDev; - double m_Opacity; + glm::vec2 m_Offset; + float m_StdDev; + float m_Opacity; std::string m_sColorName; Pixel32 m_Color; }; diff --git a/src/player/Shape.cpp b/src/player/Shape.cpp index f93cd6b..a40f01b 100644 --- a/src/player/Shape.cpp +++ b/src/player/Shape.cpp @@ -1,6 +1,6 @@ // // libavg - Media Playback Engine. -// Copyright (C) 2003-2011 Ulrich von Zadow +// Copyright (C) 2003-2014 Ulrich von Zadow // // This library is free software; you can redistribute it and/or // modify it under the terms of the GNU Lesser General Public @@ -26,6 +26,7 @@ #include "../graphics/Filterfliprgb.h" #include "../graphics/GLContext.h" +#include "../graphics/OGLShader.h" #include "OGLSurface.h" @@ -58,21 +59,20 @@ void Shape::setBitmap(BitmapPtr pBmp) if (m_pImage->getState() == Image::GPU) { if (prevState != Image::GPU) { // TODO: This shouldn't happen. - m_pVertexArray = VertexArrayPtr(new VertexArray()); + m_pVertexData = VertexDataPtr(new VertexData()); } } } void Shape::moveToGPU() { - m_pSurface->attach(); m_pImage->moveToGPU(); - m_pVertexArray = VertexArrayPtr(new VertexArray()); + m_pVertexData = VertexDataPtr(new VertexData()); } void Shape::moveToCPU() { - m_pVertexArray = VertexArrayPtr(); + m_pVertexData = VertexDataPtr(); m_pImage->moveToCPU(); } @@ -86,35 +86,43 @@ bool Shape::isTextured() const return m_pImage->getSource() != Image::NONE; } -VertexArrayPtr Shape::getVertexArray() +VertexDataPtr Shape::getVertexData() { - return m_pVertexArray; + return m_pVertexData; } -void Shape::draw() +void Shape::setVertexArray(const VertexArrayPtr& pVA) +{ + pVA->startSubVA(m_SubVA); + m_SubVA.appendVertexData(m_pVertexData); +/* + cerr << endl; + cerr << "Global VA: " << endl; + pVA->dump(); + cerr << "Local vertex data: " << endl; + m_pVertexData->dump(); +*/ +} + +void Shape::draw(const glm::mat4& transform, float opacity) { bool bIsTextured = isTextured(); - GLContext* pContext = GLContext::getCurrent(); + GLContext* pContext = GLContext::getMain(); + StandardShaderPtr pShader = pContext->getStandardShader(); + pShader->setTransform(transform); + pShader->setAlpha(opacity); if (bIsTextured) { m_pSurface->activate(); } else { - if (GLContext::getCurrent()->isUsingShaders()) { - glproc::UseProgramObject(0); - } - for (int i = 1; i < 5; ++i) { - glproc::ActiveTexture(GL_TEXTURE0 + i); - glDisable(GL_TEXTURE_2D); - } - glproc::ActiveTexture(GL_TEXTURE0); + pShader->setUntextured(); + pShader->activate(); } - pContext->enableTexture(bIsTextured); - pContext->enableGLColorArray(!bIsTextured); - m_pVertexArray->draw(); + m_SubVA.draw(); } void Shape::discard() { - m_pVertexArray = VertexArrayPtr(); + m_pVertexData = VertexDataPtr(); m_pImage->discard(); } diff --git a/src/player/Shape.h b/src/player/Shape.h index 6502aaa..4cbb390 100644 --- a/src/player/Shape.h +++ b/src/player/Shape.h @@ -1,6 +1,6 @@ // // libavg - Media Playback Engine. -// Copyright (C) 2003-2011 Ulrich von Zadow +// Copyright (C) 2003-2014 Ulrich von Zadow // // This library is free software; you can redistribute it and/or // modify it under the terms of the GNU Lesser General Public @@ -26,9 +26,9 @@ #include "Image.h" #include "MaterialInfo.h" -#include "../base/Point.h" +#include "../base/GLMHelper.h" #include "../graphics/Bitmap.h" -#include "../graphics/VertexArray.h" +#include "../graphics/SubVertexArray.h" #include <boost/shared_ptr.hpp> #include <string> @@ -47,15 +47,17 @@ class AVG_API Shape virtual void moveToCPU(); ImagePtr getImage(); - VertexArrayPtr getVertexArray(); - void draw(); + VertexDataPtr getVertexData(); + void setVertexArray(const VertexArrayPtr& pVA); + void draw(const glm::mat4& transform, float opacity); void discard(); private: bool isTextured() const; - VertexArrayPtr m_pVertexArray; + VertexDataPtr m_pVertexData; + SubVertexArray m_SubVA; OGLSurface * m_pSurface; ImagePtr m_pImage; }; diff --git a/src/player/SoundNode.cpp b/src/player/SoundNode.cpp index 9d31597..3bb089c 100644 --- a/src/player/SoundNode.cpp +++ b/src/player/SoundNode.cpp @@ -1,6 +1,6 @@ // // libavg - Media Playback Engine. -// Copyright (C) 2003-2011 Ulrich von Zadow +// Copyright (C) 2003-2014 Ulrich von Zadow // // This library is free software; you can redistribute it and/or // modify it under the terms of the GNU Lesser General Public @@ -20,18 +20,18 @@ // #include "SoundNode.h" #include "Player.h" -#include "NodeDefinition.h" +#include "TypeDefinition.h" #include "Canvas.h" #include "../base/Exception.h" #include "../base/Logger.h" #include "../base/ScopeTimer.h" #include "../base/XMLHelper.h" +#include "../base/ObjectCounter.h" -#include "../audio/SDLAudioEngine.h" +#include "../audio/AudioEngine.h" #include "../video/AsyncVideoDecoder.h" -#include "../video/FFMpegDecoder.h" #include <iostream> #include <sstream> @@ -40,33 +40,35 @@ #include <unistd.h> #endif -using namespace boost::python; +using namespace boost; using namespace std; namespace avg { -NodeDefinition SoundNode::createDefinition() +void SoundNode::registerType() { - return NodeDefinition("sound", Node::buildNode<SoundNode>) - .extendDefinition(AreaNode::createDefinition()) + TypeDefinition def = TypeDefinition("sound", "areanode", + ExportedObject::buildObject<SoundNode>) .addArg(Arg<UTF8String>("href", "", false, offsetof(SoundNode, m_href))) .addArg(Arg<bool>("loop", false, false, offsetof(SoundNode, m_bLoop))) - .addArg(Arg<double>("volume", 1.0, false, offsetof(SoundNode, m_Volume))) + .addArg(Arg<float>("volume", 1.0, false, offsetof(SoundNode, m_Volume))) ; + TypeRegistry::get()->registerType(def); } SoundNode::SoundNode(const ArgList& args) : m_Filename(""), m_pEOFCallback(0), + m_SeekBeforeCanRenderTime(0), m_pDecoder(0), m_Volume(1.0), - m_State(Unloaded) + m_State(Unloaded), + m_AudioID(-1) { args.setMembers(this); m_Filename = m_href; initFilename(m_Filename); - VideoDecoderPtr pSyncDecoder(new FFMpegDecoder()); - m_pDecoder = new AsyncVideoDecoder(pSyncDecoder, 8); + m_pDecoder = new AsyncVideoDecoder(8); ObjectCounter::get()->incRef(&typeid(*this)); } @@ -110,7 +112,7 @@ int SoundNode::getNumAudioChannels() const long long SoundNode::getCurTime() const { exceptionIfUnloaded("getCurTime"); - return (long long)(m_pDecoder->getCurTime(SS_AUDIO)*1000); + return (long long)(m_pDecoder->getCurTime()*1000); } void SoundNode::seekToTime(long long Time) @@ -129,13 +131,19 @@ void SoundNode::setEOFCallback(PyObject * pEOFCallback) if (m_pEOFCallback) { Py_DECREF(m_pEOFCallback); } - Py_INCREF(pEOFCallback); - m_pEOFCallback = pEOFCallback; + if (pEOFCallback == Py_None) { + m_pEOFCallback = 0; + } else { + avgDeprecationWarning("1.8", "SoundNode.setEOFCallback()", + "Node.subscribe(END_OF_FILE)"); + Py_INCREF(pEOFCallback); + m_pEOFCallback = pEOFCallback; + } } void SoundNode::connectDisplay() { - if (!SDLAudioEngine::get()) { + if (!AudioEngine::get()) { throw Exception(AVG_ERR_UNSUPPORTED, "Sound nodes can only be created if audio is not disabled."); } @@ -154,6 +162,7 @@ void SoundNode::connectDisplay() void SoundNode::connect(CanvasPtr pCanvas) { + checkReload(); AreaNode::connect(pCanvas); pCanvas->registerFrameEndListener(this); } @@ -194,19 +203,19 @@ void SoundNode::setHRef(const UTF8String& href) checkReload(); } -double SoundNode::getVolume() +float SoundNode::getVolume() { return m_Volume; } -void SoundNode::setVolume(double volume) +void SoundNode::setVolume(float volume) { if (volume < 0) { volume = 0; } m_Volume = volume; - if (m_pDecoder) { - m_pDecoder->setVolume(volume); + if (m_AudioID != -1) { + AudioEngine::get()->setSourceVolume(m_AudioID, volume); } } @@ -215,13 +224,12 @@ void SoundNode::checkReload() string fileName (m_href); if (m_href != "") { initFilename(fileName); - if (fileName != m_Filename) { - SoundState oldState = m_State; + if (fileName != m_Filename && m_State != Unloaded) { changeSoundState(Unloaded); m_Filename = fileName; - if (oldState != Unloaded) { - changeSoundState(Paused); - } + changeSoundState(Paused); + } else { + m_Filename = fileName; } } else { changeSoundState(Unloaded); @@ -231,17 +239,12 @@ void SoundNode::checkReload() void SoundNode::onFrameEnd() { - if (m_State == Playing && m_pDecoder->isEOF(SS_AUDIO)) { - onEOF(); - } -} - -int SoundNode::fillAudioBuffer(AudioBufferPtr pBuffer) -{ if (m_State == Playing) { - return m_pDecoder->fillAudioBuffer(pBuffer); - } else { - return 0; + m_pDecoder->updateAudioStatus(); + } + if (m_State == Playing && m_pDecoder->isEOF()) { + NodePtr pTempThis = getSharedThis(); + onEOF(); } } @@ -265,8 +268,10 @@ void SoundNode::changeSoundState(SoundState newSoundState) } if (newSoundState == Paused) { m_PauseStartTime = curTime; + AudioEngine::get()->pauseSource(m_AudioID); } else if (newSoundState == Playing && m_State == Paused) { m_PauseTime += curTime-m_PauseStartTime; + AudioEngine::get()->playSource(m_AudioID); } } m_State = newSoundState; @@ -274,16 +279,22 @@ void SoundNode::changeSoundState(SoundState newSoundState) void SoundNode::seek(long long destTime) { - m_pDecoder->seek(double(destTime)/1000); - m_StartTime = Player::get()->getFrameTime() - destTime; - m_PauseTime = 0; - m_PauseStartTime = Player::get()->getFrameTime(); + if (getState() == NS_CANRENDER) { + AudioEngine::get()->notifySeek(m_AudioID); + m_pDecoder->seek(float(destTime)/1000); + m_StartTime = Player::get()->getFrameTime() - destTime; + m_PauseTime = 0; + m_PauseStartTime = Player::get()->getFrameTime(); + } else { + // If we get a seek command before decoding has really started, we need to defer + // the actual seek until the decoder is ready. + m_SeekBeforeCanRenderTime = destTime; + } } void SoundNode::open() { - m_pDecoder->setVolume(m_Volume); - m_pDecoder->open(m_Filename, true); + m_pDecoder->open(m_Filename, false, true); VideoInfo videoInfo = m_pDecoder->getVideoInfo(); if (!videoInfo.m_bHasAudio) { throw Exception(AVG_ERR_VIDEO_GENERAL, @@ -294,14 +305,23 @@ void SoundNode::open() void SoundNode::startDecoding() { - SDLAudioEngine* pEngine = SDLAudioEngine::get(); + AudioEngine* pEngine = AudioEngine::get(); m_pDecoder->startDecoding(false, pEngine->getParams()); - pEngine->addSource(this); + m_AudioID = pEngine->addSource(*m_pDecoder->getAudioMsgQ(), + *m_pDecoder->getAudioStatusQ()); + pEngine->setSourceVolume(m_AudioID, m_Volume); + if (m_SeekBeforeCanRenderTime != 0) { + seek(m_SeekBeforeCanRenderTime); + m_SeekBeforeCanRenderTime = 0; + } } void SoundNode::close() { - SDLAudioEngine::get()->removeSource(this); + if (m_AudioID != -1) { + AudioEngine::get()->removeSource(m_AudioID); + m_AudioID = -1; + } m_pDecoder->close(); } @@ -309,7 +329,7 @@ void SoundNode::exceptionIfUnloaded(const std::string& sFuncName) const { if (m_State == Unloaded) { throw Exception(AVG_ERR_VIDEO_GENERAL, - string("SoundNode.")+sFuncName+" failed: video not loaded."); + string("SoundNode.")+sFuncName+" failed: sound not loaded."); } } @@ -324,10 +344,11 @@ void SoundNode::onEOF() PyObject * result = PyEval_CallObject(m_pEOFCallback, arglist); Py_DECREF(arglist); if (!result) { - throw error_already_set(); + throw py::error_already_set(); } Py_DECREF(result); } + notifySubscribers("END_OF_FILE"); } } diff --git a/src/player/SoundNode.h b/src/player/SoundNode.h index 04f927d..66f9308 100644 --- a/src/player/SoundNode.h +++ b/src/player/SoundNode.h @@ -1,6 +1,6 @@ // // libavg - Media Playback Engine. -// Copyright (C) 2003-2011 Ulrich von Zadow +// Copyright (C) 2003-2014 Ulrich von Zadow // // This library is free software; you can redistribute it and/or // modify it under the terms of the GNU Lesser General Public @@ -28,16 +28,15 @@ #include "../base/IFrameEndListener.h" #include "../base/UTF8String.h" -#include "../audio/IAudioSource.h" namespace avg { -class VideoDecoder; +class AsyncVideoDecoder; -class AVG_API SoundNode : public AreaNode, IFrameEndListener, IAudioSource +class AVG_API SoundNode : public AreaNode, IFrameEndListener { public: - static NodeDefinition createDefinition(); + static void registerType(); SoundNode(const ArgList& args); virtual ~SoundNode(); @@ -52,8 +51,8 @@ class AVG_API SoundNode : public AreaNode, IFrameEndListener, IAudioSource const UTF8String& getHRef() const; void setHRef(const UTF8String& href); - double getVolume(); - void setVolume(double volume); + float getVolume(); + void setVolume(float volume); void checkReload(); long long getDuration() const; @@ -68,8 +67,6 @@ class AVG_API SoundNode : public AreaNode, IFrameEndListener, IAudioSource virtual void onFrameEnd(); - virtual int fillAudioBuffer(AudioBufferPtr pBuffer); - private: void seek(long long destTime); void onEOF(); @@ -85,15 +82,16 @@ class AVG_API SoundNode : public AreaNode, IFrameEndListener, IAudioSource std::string m_Filename; bool m_bLoop; PyObject * m_pEOFCallback; - bool m_bAudioEnabled; + long long m_SeekBeforeCanRenderTime; long long m_StartTime; long long m_PauseTime; long long m_PauseStartTime; - VideoDecoder * m_pDecoder; - double m_Volume; + AsyncVideoDecoder* m_pDecoder; + float m_Volume; SoundState m_State; + int m_AudioID; }; } diff --git a/src/player/SubscriberInfo.cpp b/src/player/SubscriberInfo.cpp new file mode 100644 index 0000000..85c0da2 --- /dev/null +++ b/src/player/SubscriberInfo.cpp @@ -0,0 +1,85 @@ + +// +// libavg - Media Playback Engine. +// Copyright (C) 2003-2014 Ulrich von Zadow +// +// This library is free software; you can redistribute it and/or +// modify it under the terms of the GNU Lesser General Public +// License as published by the Free Software Foundation; either +// version 2 of the License, or (at your option) any later version. +// +// This library 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 +// Lesser General Public License for more details. +// +// You should have received a copy of the GNU Lesser General Public +// License along with this library; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +// +// Current versions can be found at www.libavg.de +// + +#include "SubscriberInfo.h" + +#include "../base/Exception.h" +#include "../base/ObjectCounter.h" +#include "../base/ScopeTimer.h" + +#include <boost/python/slice.hpp> + +using namespace std; + +namespace avg { + +py::object SubscriberInfo::s_MethodrefModule; + +SubscriberInfo::SubscriberInfo(int id, const py::object& callable) + : m_ID(id) +{ + ObjectCounter::get()->incRef(&typeid(*this)); + if (s_MethodrefModule.ptr() == py::object().ptr()) { + s_MethodrefModule = py::import("libavg.methodref"); + } + // Use the methodref module to manage the lifetime of the callables. This makes + // sure that we can delete bound-method callbacks when the object they are bound + // to disappears. + m_Callable = py::object(s_MethodrefModule.attr("methodref")(callable)); +} + +SubscriberInfo::~SubscriberInfo() +{ + ObjectCounter::get()->decRef(&typeid(*this)); +} + +bool SubscriberInfo::hasExpired() const +{ + py::object func = m_Callable(); + return (func.ptr() == py::object().ptr()); +} + +static ProfilingZoneID InvokeSubscriberProfilingZone("SubscriberInfo: invoke"); + +void SubscriberInfo::invoke(py::list args) const +{ + ScopeTimer timer(InvokeSubscriberProfilingZone); + py::object func = m_Callable(); + py::tuple argsTuple(args); + py::object pyResult = func(*argsTuple); + if (pyResult.ptr() == 0) { + throw py::error_already_set(); + } +} + +int SubscriberInfo::getID() const +{ + return m_ID; +} + +bool SubscriberInfo::isCallable(const py::object& callable) const +{ + bool bResult = py::call_method<bool>(m_Callable.ptr(), "isSameFunc", callable); + return bResult; +} + +} diff --git a/src/player/SubscriberInfo.h b/src/player/SubscriberInfo.h new file mode 100644 index 0000000..a8dc388 --- /dev/null +++ b/src/player/SubscriberInfo.h @@ -0,0 +1,58 @@ +// +// libavg - Media Playback Engine. +// Copyright (C) 2003-2014 Ulrich von Zadow +// +// This library is free software; you can redistribute it and/or +// modify it under the terms of the GNU Lesser General Public +// License as published by the Free Software Foundation; either +// version 2 of the License, or (at your option) any later version. +// +// This library 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 +// Lesser General Public License for more details. +// +// You should have received a copy of the GNU Lesser General Public +// License along with this library; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +// +// Current versions can be found at www.libavg.de +// + +#ifndef _SubscriberInfo_H_ +#define _SubscriberInfo_H_ + +#include "../api.h" + +#include "BoostPython.h" +#include <boost/shared_ptr.hpp> + +// Python docs say python.h should be included before any standard headers (!) +#include "WrapPython.h" + +#include <vector> + +namespace avg { + +class SubscriberInfo { +public: + SubscriberInfo(int id, const py::object& callable); + virtual ~SubscriberInfo(); + + bool hasExpired() const; + void invoke(py::list args) const; + int getID() const; + bool isCallable(const py::object& callable) const; + +private: + int m_ID; + py::object m_Callable; + static py::object s_MethodrefModule; +}; + +typedef boost::shared_ptr<SubscriberInfo> SubscriberInfoPtr; +} + +#endif + + diff --git a/src/player/TUIOInputDevice.cpp b/src/player/TUIOInputDevice.cpp index a722289..f6f3f08 100644 --- a/src/player/TUIOInputDevice.cpp +++ b/src/player/TUIOInputDevice.cpp @@ -1,6 +1,6 @@ // // libavg - Media Playback Engine. -// Copyright (C) 2003-2011 Ulrich von Zadow +// Copyright (C) 2003-2014 Ulrich von Zadow // // This library is free software; you can redistribute it and/or // modify it under the terms of the GNU Lesser General Public @@ -28,7 +28,6 @@ #include "../base/Logger.h" #include "../base/StringHelper.h" #include "../base/OSHelper.h" -#include "../base/Point.h" #include "../base/ObjectCounter.h" #include "../base/Exception.h" @@ -49,7 +48,8 @@ DWORD WINAPI TUIOInputDevice::threadFunc(LPVOID p) }; TUIOInputDevice::TUIOInputDevice() - : m_LastID(0) + : m_pSocket(0), + m_LastID(0) { } @@ -83,8 +83,8 @@ void TUIOInputDevice::start() if (!m_pSocket->IsBound()) { throw Exception(AVG_ERR_MT_INIT, "TUIO event source: Socket not bound."); } - AVG_TRACE(Logger::CONFIG, "TUIO multitouch event source created, listening on port " - << port); + AVG_TRACE(Logger::category::CONFIG,Logger::severity::INFO, + "TUIO multitouch event source created, listening on port " << port); #ifndef WIN32 pthread_create(&m_Thread, NULL, threadFunc, this); @@ -97,7 +97,7 @@ void TUIOInputDevice::start() void TUIOInputDevice::ProcessPacket(const char* pData, int size, const IpEndpointName& remoteEndpoint) { - boost::mutex::scoped_lock lock(getMutex()); + lock_guard lock(getMutex()); try { ReceivedPacket packet(pData, size); if (packet.IsBundle()) { @@ -105,8 +105,8 @@ void TUIOInputDevice::ProcessPacket(const char* pData, int size, } else { processMessage(ReceivedMessage(packet), remoteEndpoint); } - } catch (MalformedBundleException& e) { - AVG_TRACE(Logger::WARNING, "Malformed OSC bundle received: " << e.what()); + } catch (osc::Exception& e) { + AVG_LOG_WARNING("OSC exception: " << e.what()); } } @@ -123,8 +123,8 @@ void TUIOInputDevice::processBundle(const ReceivedBundle& bundle, processMessage(ReceivedMessage(*it), remoteEndpoint); } } - } catch (MalformedBundleException& e) { - AVG_TRACE(Logger::WARNING, "Malformed OSC bundle received: " << e.what()); + } catch (osc::Exception& e) { + AVG_LOG_WARNING("OSC exception: " << e.what()); } } @@ -149,7 +149,7 @@ void TUIOInputDevice::processMessage(const ReceivedMessage& msg, } } } catch (osc::Exception& e) { - AVG_TRACE(Logger::WARNING, "Error parsing TUIO message: " << e.what() + AVG_LOG_WARNING("Error parsing TUIO message: " << e.what() << ". Message was " << msg); } } @@ -161,19 +161,19 @@ void TUIOInputDevice::processSet(ReceivedMessageArgumentStream& args) float xspeed, yspeed; float accel; args >> tuioID >> xpos >> ypos >> xspeed >> yspeed >> accel; - DPoint pos(xpos, ypos); - DPoint speed(xspeed, yspeed); + glm::vec2 pos(xpos, ypos); + glm::vec2 speed(xspeed, yspeed); // cerr << "Set: ID: " << tuioID << ", pos: " << pos << ", speed: " << speed // << ", accel: " << accel << endl; TouchStatusPtr pTouchStatus = getTouchStatus(tuioID); if (!pTouchStatus) { // Down m_LastID++; - TouchEventPtr pEvent = createEvent(m_LastID, Event::CURSORDOWN, pos, speed); + TouchEventPtr pEvent = createEvent(m_LastID, Event::CURSOR_DOWN, pos, speed); addTouchStatus((long)tuioID, pEvent); } else { // Move - TouchEventPtr pEvent = createEvent(0, Event::CURSORMOTION, pos, speed); + TouchEventPtr pEvent = createEvent(0, Event::CURSOR_MOTION, pos, speed); pTouchStatus->pushEvent(pEvent); } } @@ -196,20 +196,20 @@ void TUIOInputDevice::processAlive(ReceivedMessageArgumentStream& args) TouchStatusPtr pTouchStatus = getTouchStatus(id); TouchEventPtr pOldEvent = pTouchStatus->getLastEvent(); TouchEventPtr pUpEvent = boost::dynamic_pointer_cast<TouchEvent>( - pOldEvent->cloneAs(Event::CURSORUP)); + pOldEvent->cloneAs(Event::CURSOR_UP)); pTouchStatus->pushEvent(pUpEvent); removeTouchStatus(id); } } -TouchEventPtr TUIOInputDevice::createEvent(int id, Event::Type type, DPoint pos, - DPoint speed) +TouchEventPtr TUIOInputDevice::createEvent(int id, Event::Type type, glm::vec2 pos, + glm::vec2 speed) { - DPoint size = getWindowSize(); - IntPoint screenPos(int(pos.x*size.x+0.5), int(pos.y*size.y+0.5)); - DPoint screenSpeed(int(speed.x*size.x+0.5), int(speed.y*size.y+0.5)); + const glm::vec2 size = getTouchArea(); + IntPoint screenPos = getScreenPos(pos); + glm::vec2 screenSpeed(int(speed.x*size.x+0.5), int(speed.y*size.y+0.5)); TouchEventPtr pEvent(new TouchEvent(id, type, screenPos, Event::TOUCH)); - pEvent->setSpeed(screenSpeed/1000); + pEvent->setSpeed(screenSpeed/1000.f); return pEvent; } diff --git a/src/player/TUIOInputDevice.h b/src/player/TUIOInputDevice.h index 6bd99f1..7315345 100644 --- a/src/player/TUIOInputDevice.h +++ b/src/player/TUIOInputDevice.h @@ -1,6 +1,6 @@ // // libavg - Media Playback Engine. -// Copyright (C) 2003-2011 Ulrich von Zadow +// Copyright (C) 2003-2014 Ulrich von Zadow // // This library is free software; you can redistribute it and/or // modify it under the terms of the GNU Lesser General Public @@ -60,7 +60,7 @@ private: const IpEndpointName& remoteEndpoint); void processSet(osc::ReceivedMessageArgumentStream& args); void processAlive(osc::ReceivedMessageArgumentStream& args); - TouchEventPtr createEvent(int id, Event::Type type, DPoint pos, DPoint speed); + TouchEventPtr createEvent(int id, Event::Type type, glm::vec2 pos, glm::vec2 speed); UdpListeningReceiveSocket* m_pSocket; int m_LastID; diff --git a/src/player/TestHelper.cpp b/src/player/TestHelper.cpp index c9a3e48..342e7fd 100644 --- a/src/player/TestHelper.cpp +++ b/src/player/TestHelper.cpp @@ -1,6 +1,6 @@ // // libavg - Media Playback Engine. -// Copyright (C) 2003-2011 Ulrich von Zadow +// Copyright (C) 2003-2014 Ulrich von Zadow // // This library is free software; you can redistribute it and/or // modify it under the terms of the GNU Lesser General Public @@ -65,7 +65,7 @@ void TestHelper::fakeMouseEvent(Event::Type eventType, } void TestHelper::fakeTouchEvent(int id, Event::Type eventType, - Event::Source source, const DPoint& pos, const DPoint& speed) + Event::Source source, const glm::vec2& pos, const glm::vec2& speed) { checkEventType(eventType); // The id is modified to avoid collisions with real touch events. @@ -73,14 +73,14 @@ void TestHelper::fakeTouchEvent(int id, Event::Type eventType, IntPoint(pos), source, speed)); map<int, TouchStatusPtr>::iterator it = m_Touches.find(pEvent->getCursorID()); switch (pEvent->getType()) { - case Event::CURSORDOWN: { + case Event::CURSOR_DOWN: { AVG_ASSERT(it == m_Touches.end()); TouchStatusPtr pTouchStatus(new TouchStatus(pEvent)); m_Touches[pEvent->getCursorID()] = pTouchStatus; } break; - case Event::CURSORMOTION: - case Event::CURSORUP: { + case Event::CURSOR_MOTION: + case Event::CURSOR_UP: { if (it == m_Touches.end()) { cerr << "borked: " << pEvent->getCursorID() << ", " << pEvent->typeStr() << endl; @@ -110,6 +110,11 @@ void TestHelper::dumpObjects() cerr << ObjectCounter::get()->dump(); } +TypeMap TestHelper::getObjectCount() +{ + return ObjectCounter::get()->getObjectCount(); +} + // From IInputDevice std::vector<EventPtr> TestHelper::pollEvents() { @@ -120,7 +125,7 @@ std::vector<EventPtr> TestHelper::pollEvents() CursorEventPtr pEvent = pTouchStatus->pollEvent(); if (pEvent) { events.push_back(pEvent); - if (pEvent->getType() == Event::CURSORUP) { + if (pEvent->getType() == Event::CURSOR_UP) { m_Touches.erase(it++); } else { ++it; @@ -136,9 +141,9 @@ std::vector<EventPtr> TestHelper::pollEvents() void TestHelper::checkEventType(Event::Type eventType) { - if (eventType == Event::CURSOROVER || eventType == Event::CURSOROUT) { + if (eventType == Event::CURSOR_OVER || eventType == Event::CURSOR_OUT) { throw Exception(AVG_ERR_UNSUPPORTED, "TestHelper::fakeXxxEvent: Can't send " - "CURSOROVER and CURSOROUT events directly. They are generated " + "CURSOR_OVER and CURSOR_OUT events directly. They are generated " "internally."); } } diff --git a/src/player/TestHelper.h b/src/player/TestHelper.h index 0461729..f0741e9 100644 --- a/src/player/TestHelper.h +++ b/src/player/TestHelper.h @@ -1,6 +1,6 @@ // // libavg - Media Playback Engine. -// Copyright (C) 2003-2011 Ulrich von Zadow +// Copyright (C) 2003-2014 Ulrich von Zadow // // This library is free software; you can redistribute it and/or // modify it under the terms of the GNU Lesser General Public @@ -23,6 +23,7 @@ #define _TestHelper_H_ #include "../api.h" +#include "../base/ObjectCounter.h" #include "../graphics/Bitmap.h" #include "Event.h" #include "IInputDevice.h" @@ -51,11 +52,12 @@ class AVG_API TestHelper : public IInputDevice bool rightButtonState, int xPosition, int yPosition, int button); void fakeTouchEvent(int id, Event::Type eventType, Event::Source source, - const DPoint& pos, const DPoint& speed=DPoint(0, 0)); + const glm::vec2& pos, const glm::vec2& speed=glm::vec2(0, 0)); void fakeKeyEvent(Event::Type eventType, unsigned char scanCode, int keyCode, const std::string& keyString, int unicode, int modifiers); void dumpObjects(); + TypeMap getObjectCount(); // From IInputDevice virtual std::vector<EventPtr> pollEvents(); diff --git a/src/player/TextEngine.cpp b/src/player/TextEngine.cpp index 9d89e36..226b0de 100644 --- a/src/player/TextEngine.cpp +++ b/src/player/TextEngine.cpp @@ -1,6 +1,6 @@ // // libavg - Media Playback Engine. -// Copyright (C) 2003-2011 Ulrich von Zadow +// Copyright (C) 2003-2014 Ulrich von Zadow // // This library is free software; you can redistribute it and/or // modify it under the terms of the GNU Lesser General Public @@ -78,7 +78,6 @@ TextEngine::~TextEngine() void TextEngine::init() { - g_type_init(); m_pFontMap = PANGO_FT2_FONT_MAP(pango_ft2_font_map_new()); pango_ft2_font_map_set_resolution(m_pFontMap, 72, 72); if (m_bHint) { @@ -88,7 +87,11 @@ void TextEngine::init() pango_ft2_font_map_set_default_substitute(m_pFontMap, text_subst_func_nohint, 0, 0); } +#if PANGO_VERSION > PANGO_VERSION_ENCODE(1,22,0) + m_pPangoContext = pango_font_map_create_context(PANGO_FONT_MAP(m_pFontMap)); +#else m_pPangoContext = pango_ft2_font_map_create_context(m_pFontMap); +#endif pango_context_set_language(m_pPangoContext, pango_language_from_string ("en_US")); @@ -160,7 +163,7 @@ PangoFontDescription * TextEngine::getFontDescription(const string& sFamily, pFamily = getFontFamily(sFamily); } catch (Exception&) { if (m_sFontsNotFound.find(sFamily) == m_sFontsNotFound.end()) { - AVG_TRACE(Logger::WARNING, "Could not find font face " << sFamily << + AVG_LOG_WARNING("Could not find font face " << sFamily << ". Using sans instead."); m_sFontsNotFound.insert(sFamily); } @@ -186,7 +189,7 @@ PangoFontDescription * TextEngine::getFontDescription(const string& sFamily, pair<string, string> variant(sFamily, sVariant); if (m_VariantsNotFound.find(variant) == m_VariantsNotFound.end()) { m_VariantsNotFound.insert(variant); - AVG_TRACE(Logger::WARNING, "Could not find font variant " + AVG_LOG_WARNING("Could not find font variant " << sFamily << ":" << sVariant << ". Using " << pango_font_face_get_face_name(pFace) << " instead."); } @@ -205,32 +208,41 @@ PangoFontDescription * TextEngine::getFontDescription(const string& sFamily, void GLibLogFunc(const gchar *log_domain, GLogLevelFlags log_level, const gchar *message, gpointer unused_data) { +//TODO: Make this use correct AVG_LOG_LEVEL function #ifndef WIN32 string s = "Pango "; if (log_level & G_LOG_LEVEL_ERROR) { - s += "error: "; + s += message; + AVG_LOG_ERROR(s); + return; } else if (log_level & G_LOG_LEVEL_CRITICAL) { - s += string("critical: ")+message; - AVG_TRACE(Logger::ERROR, s); + s += message; + AVG_LOG_ERROR(s); AVG_ASSERT(false); } else if (log_level & G_LOG_LEVEL_WARNING) { - s += "warning: "; + s += message; + AVG_LOG_WARNING(s); + return; } else if (log_level & G_LOG_LEVEL_MESSAGE) { - s += "message: "; + s += (string("message: ") + message); + AVG_LOG_INFO(s); + return; } else if (log_level & G_LOG_LEVEL_INFO) { - s += "info: "; + s += message; + AVG_LOG_INFO(s); + return; } else if (log_level & G_LOG_LEVEL_DEBUG) { - s += "debug: "; + s += message; + AVG_TRACE(Logger::category::NONE, Logger::severity::DEBUG, s); + return; } s += message; - AVG_TRACE(Logger::WARNING, s); + AVG_LOG_WARNING(s); #endif } void TextEngine::initFonts() { - g_type_init(); - std::vector<std::string> fontConfPathPrefixList; #ifndef WIN32 fontConfPathPrefixList.push_back("/"); diff --git a/src/player/TextEngine.h b/src/player/TextEngine.h index 734b2a4..4fef426 100644 --- a/src/player/TextEngine.h +++ b/src/player/TextEngine.h @@ -1,6 +1,6 @@ // // libavg - Media Playback Engine. -// Copyright (C) 2003-2011 Ulrich von Zadow +// Copyright (C) 2003-2014 Ulrich von Zadow // // This library is free software; you can redistribute it and/or // modify it under the terms of the GNU Lesser General Public diff --git a/src/player/Timeout.cpp b/src/player/Timeout.cpp index 48f5e11..9820699 100644 --- a/src/player/Timeout.cpp +++ b/src/player/Timeout.cpp @@ -1,6 +1,6 @@ // // libavg - Media Playback Engine. -// Copyright (C) 2003-2011 Ulrich von Zadow +// Copyright (C) 2003-2014 Ulrich von Zadow // // This library is free software; you can redistribute it and/or // modify it under the terms of the GNU Lesser General Public @@ -21,19 +21,19 @@ #include "Timeout.h" +#include "BoostPython.h" + #include "../base/Exception.h" #include "../base/ObjectCounter.h" -#include "BoostPython.h" - #include <iostream> -using namespace boost::python; using namespace std; namespace avg { -int Timeout::s_LastID = 0; +// Hack to make sure ids don't overlap with publisher/subsriber ids +int Timeout::s_LastID = 100000; Timeout::Timeout(int time, PyObject * pyfunc, bool isInterval, long long startTime) : m_Interval(time), @@ -54,17 +54,17 @@ Timeout::~Timeout() ObjectCounter::get()->decRef(&typeid(*this)); } -bool Timeout::IsReady(long long time) const +bool Timeout::isReady(long long time) const { return m_NextTimeout <= time; } -bool Timeout::IsInterval() const +bool Timeout::isInterval() const { return m_IsInterval; } -void Timeout::Fire(long long curTime) +void Timeout::fire(long long curTime) { if (m_IsInterval) { m_NextTimeout = m_Interval + curTime; @@ -75,12 +75,12 @@ void Timeout::Fire(long long curTime) // by a call to clearTimeout()! Py_DECREF(arglist); if (!result) { - throw error_already_set(); + throw py::error_already_set(); } Py_DECREF(result); } -int Timeout::GetID() const +int Timeout::getID() const { return m_ID; } diff --git a/src/player/Timeout.h b/src/player/Timeout.h index 0f73a4e..9682d76 100644 --- a/src/player/Timeout.h +++ b/src/player/Timeout.h @@ -1,6 +1,6 @@ // // libavg - Media Playback Engine. -// Copyright (C) 2003-2011 Ulrich von Zadow +// Copyright (C) 2003-2014 Ulrich von Zadow // // This library is free software; you can redistribute it and/or // modify it under the terms of the GNU Lesser General Public @@ -34,10 +34,10 @@ class AVG_API Timeout Timeout (int time, PyObject * pyfunc, bool isInterval, long long startTime); virtual ~Timeout (); - bool IsReady(long long time) const; - bool IsInterval() const; - void Fire(long long curTime); - int GetID() const; + bool isReady(long long time) const; + bool isInterval() const; + void fire(long long curTime); + int getID() const; bool operator <(const Timeout& other) const; private: diff --git a/src/player/TouchEvent.cpp b/src/player/TouchEvent.cpp index 17a1f52..c2541df 100644 --- a/src/player/TouchEvent.cpp +++ b/src/player/TouchEvent.cpp @@ -1,6 +1,6 @@ // // libavg - Media Playback Engine. -// Copyright (C) 2003-2011 Ulrich von Zadow +// Copyright (C) 2003-2014 Ulrich von Zadow // // This library is free software; you can redistribute it and/or // modify it under the terms of the GNU Lesser General Public @@ -38,7 +38,7 @@ using namespace std; namespace avg { TouchEvent::TouchEvent(int id, Type eventType, BlobPtr pBlob, const IntPoint& pos, - Source source, const DPoint& speed) + Source source, const glm::vec2& speed) : CursorEvent(id, eventType, pos, source), m_pBlob(pBlob), m_bHasHandOrientation(false) @@ -49,9 +49,9 @@ TouchEvent::TouchEvent(int id, Type eventType, BlobPtr pBlob, const IntPoint& po m_Area = pBlob->getArea(); m_Center = pBlob->getCenter(); m_Eccentricity = pBlob->getEccentricity(); - const DPoint& axis0 = m_pBlob->getScaledBasis(0); - const DPoint& axis1 = m_pBlob->getScaledBasis(1); - if (axis0.getNorm() > axis1.getNorm()) { + const glm::vec2& axis0 = m_pBlob->getScaledBasis(0); + const glm::vec2& axis1 = m_pBlob->getScaledBasis(1); + if (glm::length(axis0) > glm::length(axis1)) { m_MajorAxis = axis0; m_MinorAxis = axis1; } else { @@ -61,16 +61,16 @@ TouchEvent::TouchEvent(int id, Type eventType, BlobPtr pBlob, const IntPoint& po } else { m_Orientation = 0; m_Area = 20; - m_Center = DPoint(0, 0); + m_Center = glm::vec2(0, 0); m_Eccentricity = 0; - m_MajorAxis = DPoint(5, 0); - m_MinorAxis = DPoint(0, 5); + m_MajorAxis = glm::vec2(5, 0); + m_MinorAxis = glm::vec2(0, 5); } } TouchEvent::TouchEvent(int id, Type eventType, const IntPoint& pos, Source source, - const DPoint& speed, double orientation, double area, double eccentricity, - DPoint majorAxis, DPoint minorAxis) + const glm::vec2& speed, float orientation, float area, float eccentricity, + glm::vec2 majorAxis, glm::vec2 minorAxis) : CursorEvent(id, eventType, pos, source), m_Orientation(orientation), m_Area(area), @@ -82,7 +82,7 @@ TouchEvent::TouchEvent(int id, Type eventType, const IntPoint& pos, Source sourc } TouchEvent::TouchEvent(int id, Type eventType, const IntPoint& pos, Source source, - const DPoint& speed) + const glm::vec2& speed) : CursorEvent(id, eventType, pos, source), m_Orientation(0), m_Area(20), @@ -104,32 +104,32 @@ CursorEventPtr TouchEvent::cloneAs(Type eventType) const return pClone; } -double TouchEvent::getOrientation() const +float TouchEvent::getOrientation() const { return m_Orientation; } -double TouchEvent::getArea() const +float TouchEvent::getArea() const { return m_Area; } -const DPoint & TouchEvent::getCenter() const +const glm::vec2 & TouchEvent::getCenter() const { return m_Center; } -double TouchEvent::getEccentricity() const +float TouchEvent::getEccentricity() const { return m_Eccentricity; } -const DPoint & TouchEvent::getMajorAxis() const +const glm::vec2 & TouchEvent::getMajorAxis() const { return m_MajorAxis; } -const DPoint & TouchEvent::getMinorAxis() const +const glm::vec2 & TouchEvent::getMinorAxis() const { return m_MinorAxis; } @@ -149,14 +149,14 @@ ContourSeq TouchEvent::getContour() } } -double TouchEvent::getHandOrientation() const +float TouchEvent::getHandOrientation() const { if (getSource() == Event::TOUCH) { if (m_bHasHandOrientation) { return m_HandOrientation; } else { - DPoint screenCenter = Player::get()->getRootNode()->getSize()/2; - return (getPos()-screenCenter).getAngle(); + glm::vec2 screenCenter = Player::get()->getRootNode()->getSize()/2.f; + return getAngle(getPos()-screenCenter); } } else { throw Exception(AVG_ERR_UNSUPPORTED, @@ -169,7 +169,7 @@ void TouchEvent::addRelatedEvent(TouchEventPtr pEvent) m_RelatedEvents.push_back(pEvent); if (getSource() == Event::TOUCH && m_RelatedEvents.size() == 1) { TouchEventPtr pHandEvent = m_RelatedEvents.begin()->lock(); - m_HandOrientation = (pHandEvent->getPos()-getPos()).getAngle(); + m_HandOrientation = getAngle(pHandEvent->getPos()-getPos()); m_bHasHandOrientation = true; } } @@ -192,7 +192,7 @@ void TouchEvent::removeBlob() void TouchEvent::trace() { CursorEvent::trace(); - AVG_TRACE(Logger::EVENTS2, "pos: " << getPos() + AVG_TRACE(Logger::category::EVENTS,Logger::severity::DEBUG, "pos: " << getPos() << ", ID: " << getCursorID() << ", Area: " << m_Area << ", Eccentricity: " << m_Eccentricity); diff --git a/src/player/TouchEvent.h b/src/player/TouchEvent.h index 95bbca4..730883a 100644 --- a/src/player/TouchEvent.h +++ b/src/player/TouchEvent.h @@ -1,6 +1,6 @@ // // libavg - Media Playback Engine. -// Copyright (C) 2003-2011 Ulrich von Zadow +// Copyright (C) 2003-2014 Ulrich von Zadow // // This library is free software; you can redistribute it and/or // modify it under the terms of the GNU Lesser General Public @@ -28,7 +28,7 @@ #include "CursorEvent.h" #include "../imaging/Blob.h" -#include "../base/Point.h" +#include "../base/GLMHelper.h" #include <math.h> #include <boost/weak_ptr.hpp> @@ -43,25 +43,25 @@ class AVG_API TouchEvent: public CursorEvent { public: TouchEvent(int id, Type eventType, BlobPtr pBlob, const IntPoint& pos, - Source source, const DPoint& speed=DPoint(0,0)); + Source source, const glm::vec2& speed=glm::vec2(0,0)); TouchEvent(int id, Type eventType, const IntPoint& pos, Source source, - const DPoint& speed, double orientation, double area, double eccentricity, - DPoint majorAxis, DPoint minorAxis); + const glm::vec2& speed, float orientation, float area, + float eccentricity, glm::vec2 majorAxis, glm::vec2 minorAxis); TouchEvent(int id, Type eventType, const IntPoint& pos, Source source, - const DPoint& speed=DPoint(0, 0)); + const glm::vec2& speed=glm::vec2(0, 0)); virtual ~TouchEvent(); virtual CursorEventPtr cloneAs(Type eventType) const; - double getOrientation() const; - double getArea() const; - const DPoint & getCenter() const; - double getEccentricity() const; - const DPoint & getMajorAxis() const; - const DPoint & getMinorAxis() const; + float getOrientation() const; + float getArea() const; + const glm::vec2 & getCenter() const; + float getEccentricity() const; + const glm::vec2 & getMajorAxis() const; + const glm::vec2 & getMinorAxis() const; const BlobPtr getBlob() const; ContourSeq getContour(); - double getHandOrientation() const; + float getHandOrientation() const; void addRelatedEvent(TouchEventPtr pEvent); std::vector<TouchEventPtr> getRelatedEvents() const; @@ -72,15 +72,15 @@ class AVG_API TouchEvent: public CursorEvent private: BlobPtr m_pBlob; - double m_Orientation; - double m_Area; - DPoint m_Center; - double m_Eccentricity; - DPoint m_MajorAxis; - DPoint m_MinorAxis; + float m_Orientation; + float m_Area; + glm::vec2 m_Center; + float m_Eccentricity; + glm::vec2 m_MajorAxis; + glm::vec2 m_MinorAxis; std::vector<TouchEventWeakPtr> m_RelatedEvents; bool m_bHasHandOrientation; - double m_HandOrientation; + float m_HandOrientation; }; } diff --git a/src/player/TouchStatus.cpp b/src/player/TouchStatus.cpp index 66d63bb..ff08bc9 100644 --- a/src/player/TouchStatus.cpp +++ b/src/player/TouchStatus.cpp @@ -1,6 +1,6 @@ // // libavg - Media Playback Engine. -// Copyright (C) 2003-2011 Ulrich von Zadow +// Copyright (C) 2003-2014 Ulrich von Zadow // // This library is free software; you can redistribute it and/or // modify it under the terms of the GNU Lesser General Public @@ -53,14 +53,14 @@ void TouchStatus::pushEvent(TouchEventPtr pEvent, bool bCheckMotion) if (m_bFirstFrame) { // Ignore unless cursorup. - if (pEvent->getType() == Event::CURSORUP) { + if (pEvent->getType() == Event::CURSOR_UP) { // Down and up in the first frame. To avoid inconsistencies, both // messages must be delivered. This is the only time that m_pNewEvents // has more than one entry. m_pNewEvents.push_back(pEvent); } } else { - if (bCheckMotion && pEvent->getType() == Event::CURSORMOTION && + if (bCheckMotion && pEvent->getType() == Event::CURSOR_MOTION && getLastEvent()->getPos() == pEvent->getPos()) { // Ignore motion events without motion. diff --git a/src/player/TouchStatus.h b/src/player/TouchStatus.h index 7a4eb5a..ffe3e7f 100644 --- a/src/player/TouchStatus.h +++ b/src/player/TouchStatus.h @@ -1,6 +1,6 @@ // // libavg - Media Playback Engine. -// Copyright (C) 2003-2011 Ulrich von Zadow +// Copyright (C) 2003-2014 Ulrich von Zadow // // This library is free software; you can redistribute it and/or // modify it under the terms of the GNU Lesser General Public @@ -22,7 +22,7 @@ #ifndef _TouchStatus_H_ #define _TouchStatus_H_ -#include "../base/Point.h" +#include "../api.h" #include <boost/shared_ptr.hpp> diff --git a/src/player/TrackerCalibrator.cpp b/src/player/TrackerCalibrator.cpp index a6a6a58..4bc13b9 100644 --- a/src/player/TrackerCalibrator.cpp +++ b/src/player/TrackerCalibrator.cpp @@ -1,6 +1,6 @@ // // libavg - Media Playback Engine. -// Copyright (C) 2003-2011 Ulrich von Zadow +// Copyright (C) 2003-2014 Ulrich von Zadow // // This library is free software; you can redistribute it and/or // modify it under the terms of the GNU Lesser General Public @@ -83,7 +83,7 @@ TrackerCalibrator::TrackerCalibrator(const IntPoint& CamExtents, m_DisplayPoints.push_back( IntPoint(OffsetPerPoint.x*x+MIN_DIST_FROM_BORDER, OffsetPerPoint.y*y+MIN_DIST_FROM_BORDER)); - m_CamPoints.push_back(DPoint(0,0)); + m_CamPoints.push_back(glm::dvec2(0,0)); } } } @@ -116,7 +116,7 @@ IntPoint TrackerCalibrator::getDisplayPoint() return m_DisplayPoints[m_CurPoint]; } -void TrackerCalibrator::setCamPoint(const DPoint& pt) +void TrackerCalibrator::setCamPoint(const glm::vec2& pt) { m_CamPoints[m_CurPoint] = pt; m_bCurPointSet = true; @@ -140,8 +140,8 @@ DeDistortPtr TrackerCalibrator::makeTransformer() m_DistortParams.push_back(0); m_Angle = 0; m_TrapezoidFactor = 0.0; - m_DisplayOffset= DPoint(0,0); - m_DisplayScale = DPoint(2,2); + m_DisplayOffset= glm::vec2(0,0); + m_DisplayScale = glm::vec2(2,2); int n_p = NUM_PARAMS; //should really match the Params enum!!!! @@ -160,15 +160,15 @@ DeDistortPtr TrackerCalibrator::makeTransformer() initThisFromDouble(p); /* for(int i=0;i<NUM_POINTS*NUM_POINTS;i++) { - DPoint screenPoint = m_CurrentTrafo->transformBlobToScreen( + glm::vec2 screenPoint = m_CurrentTrafo->transformBlobToScreen( m_CurrentTrafo->transform_point(m_CamPoints[i])); cerr << "sample value of trafo of (cam) " << m_CamPoints[i]<<" : (transformed) " << screenPoint << "== (display)" - << DPoint(m_DisplayPoints[i]) + << glm::vec2(m_DisplayPoints[i]) << " dist=" - << calcDist(DPoint(m_DisplayPoints[i]), screenPoint) + << calcDist(glm::vec2(m_DisplayPoints[i]), screenPoint) << endl; } cerr<<" DisplayScale = "<<m_DisplayScale << endl; @@ -192,7 +192,7 @@ void TrackerCalibrator::initThisFromDouble(double *p) m_Angle = p[ANGLE]; m_TrapezoidFactor = p[TRAPEZ]; m_CurrentTrafo = DeDistortPtr( - new DeDistort(DPoint(m_CamExtents), + new DeDistort(glm::vec2(m_CamExtents), m_DistortParams, m_Angle, m_TrapezoidFactor, @@ -206,13 +206,10 @@ void TrackerCalibrator::evaluate_tracker(double *p, int m_dat, double* fvec, int { initThisFromDouble(p); - for (int i=0; i<m_dat; i++){ - fvec[i] = calcDist( - m_CurrentTrafo->transformBlobToScreen( - m_CurrentTrafo->transform_point(m_CamPoints[i]) - ), - DPoint(m_DisplayPoints[i]) - ); + for (int i=0; i<m_dat; i++) { + glm::dvec2 resultPt = m_CurrentTrafo->transformBlobToScreen( + m_CurrentTrafo->transform_point(m_CamPoints[i])); + fvec[i] = glm::length(resultPt - glm::dvec2(m_DisplayPoints[i])); } *info = *info; /* to prevent a 'unused variable' warning */ /* if <parameters drifted away> { *info = -1; } */ diff --git a/src/player/TrackerCalibrator.h b/src/player/TrackerCalibrator.h index 9b31963..93779a6 100644 --- a/src/player/TrackerCalibrator.h +++ b/src/player/TrackerCalibrator.h @@ -1,6 +1,6 @@ // // libavg - Media Playback Engine. -// Copyright (C) 2003-2011 Ulrich von Zadow +// Copyright (C) 2003-2014 Ulrich von Zadow // // This library is free software; you can redistribute it and/or // modify it under the terms of the GNU Lesser General Public @@ -24,7 +24,7 @@ #include "../api.h" #include "../imaging/DeDistort.h" -#include "../base/Point.h" +#include "../base/GLMHelper.h" #include <vector> @@ -43,7 +43,7 @@ public: bool nextPoint(); IntPoint getDisplayPoint(); - void setCamPoint(const DPoint& pt); + void setCamPoint(const glm::vec2& pt); DeDistortPtr makeTransformer(); @@ -56,13 +56,13 @@ private: std::vector<double> m_DistortParams; double m_Angle; - DPoint m_DisplayScale; - DPoint m_DisplayOffset; + glm::dvec2 m_DisplayScale; + glm::dvec2 m_DisplayOffset; double m_TrapezoidFactor; DeDistortPtr m_CurrentTrafo; unsigned int m_CurPoint; std::vector<IntPoint> m_DisplayPoints; - std::vector<DPoint> m_CamPoints; + std::vector<glm::dvec2> m_CamPoints; IntPoint m_CamExtents; IntPoint m_DisplayExtents; diff --git a/src/player/TrackerInputDevice.cpp b/src/player/TrackerInputDevice.cpp index af85784..88e6baa 100644 --- a/src/player/TrackerInputDevice.cpp +++ b/src/player/TrackerInputDevice.cpp @@ -1,6 +1,6 @@ // // libavg - Media Playback Engine. -// Copyright (C) 2003-2011 Ulrich von Zadow +// Copyright (C) 2003-2014 Ulrich von Zadow // // This library is free software; you can redistribute it and/or // modify it under the terms of the GNU Lesser General Public @@ -37,6 +37,8 @@ #include "../imaging/DeDistort.h" #include "../imaging/CoordTransformer.h" +#include "../glm/gtx/norm.hpp" + #include "Player.h" #include "AVGNode.h" @@ -69,7 +71,7 @@ TrackerInputDevice::TrackerInputDevice() bool bFW800 = m_TrackerConfig.getBoolParam("/camera/fw800/@value"); IntPoint captureSize(m_TrackerConfig.getPointParam("/camera/size/")); string sCaptureFormat = m_TrackerConfig.getParam("/camera/format/@value"); - double frameRate = m_TrackerConfig.getDoubleParam("/camera/framerate/@value"); + float frameRate = m_TrackerConfig.getFloatParam("/camera/framerate/@value"); PixelFormat camPF = stringToPixelFormat(sCaptureFormat); if (camPF == NO_PIXELFORMAT) { @@ -77,12 +79,14 @@ TrackerInputDevice::TrackerInputDevice() "Unknown camera pixel format "+sCaptureFormat+"."); } - AVG_TRACE(Logger::CONFIG, "Trying to create a Tracker for " << sDriver + AVG_TRACE(Logger::category::CONFIG, Logger::severity::INFO, + "Trying to create a Tracker for " << sDriver << " Camera: " << sDevice << " Size: " << captureSize << "format: " << sCaptureFormat); m_pCamera = createCamera(sDriver, sDevice, -1, bFW800, captureSize, camPF, I8, frameRate); - AVG_TRACE(Logger::CONFIG, "Got Camera " << m_pCamera->getDevice() << " from driver: " + AVG_TRACE(Logger::category::CONFIG, Logger::severity::INFO, + "Got Camera " << m_pCamera->getDevice() << " from driver: " << m_pCamera->getDriverName()); IntPoint imgSize = m_pCamera->getImgSize(); @@ -99,15 +103,14 @@ TrackerInputDevice::TrackerInputDevice() try { m_DisplayROI = m_TrackerConfig.getRectParam("/transform/displayroi/"); } catch (Exception) { - m_DisplayROI = DRect(DPoint(0,0), DPoint(m_ActiveDisplaySize)); + m_DisplayROI = FRect(glm::vec2(0,0), glm::vec2(m_ActiveDisplaySize)); } IntRect roi = m_pDeDistort->getActiveBlobArea(m_DisplayROI); if (roi.tl.x < 0 || roi.tl.y < 0 || roi.br.x > imgSize.x || roi.br.y > imgSize.y) { - AVG_TRACE(Logger::ERROR, - "Impossible tracker configuration: Region of interest is " + AVG_LOG_ERROR("Impossible tracker configuration: Region of interest is " << roi << ", camera image size is " << imgSize << ". Aborting."); exit(5); } @@ -157,8 +160,8 @@ void TrackerInputDevice::setParam(const string& sElement, const string& sValue) m_TrackerConfig.setParam(sElement, sValue); // Test if active area is outside camera. - DRect area = m_pDeDistort->getActiveBlobArea(m_DisplayROI); - DPoint size = m_TrackerConfig.getPointParam("/camera/size/"); + FRect area = m_pDeDistort->getActiveBlobArea(m_DisplayROI); + glm::vec2 size = m_TrackerConfig.getPointParam("/camera/size/"); int prescale = m_TrackerConfig.getIntParam("/tracker/prescale/@value"); if (area.br.x > size.x/prescale || area.br.y > size.y/prescale || area.tl.x < 0 || area.tl.y < 0) @@ -194,7 +197,7 @@ void TrackerInputDevice::saveConfig() void TrackerInputDevice::setConfig() { m_pDeDistort = m_TrackerConfig.getTransform(); - DRect area = m_pDeDistort->getActiveBlobArea(m_DisplayROI); + FRect area = m_pDeDistort->getActiveBlobArea(m_DisplayROI); createBitmaps(area); m_pCmdQueue->pushCmd(boost::bind(&TrackerThread::setConfig, _1, m_TrackerConfig, area, m_pBitmaps)); @@ -202,7 +205,7 @@ void TrackerInputDevice::setConfig() void TrackerInputDevice::createBitmaps(const IntRect& area) { - boost::mutex::scoped_lock lock(*m_pMutex); + lock_guard lock(*m_pMutex); for (int i=1; i<NUM_TRACKER_IMAGES; i++) { switch (i) { case TRACKER_IMG_HISTOGRAM: @@ -226,16 +229,16 @@ void TrackerInputDevice::createBitmaps(const IntRect& area) Bitmap * TrackerInputDevice::getImage(TrackerImageID imageID) const { - boost::mutex::scoped_lock lock(*m_pMutex); + lock_guard lock(*m_pMutex); return new Bitmap(*m_pBitmaps[imageID]); } -DPoint TrackerInputDevice::getDisplayROIPos() const +glm::vec2 TrackerInputDevice::getDisplayROIPos() const { return m_DisplayROI.tl; } -DPoint TrackerInputDevice::getDisplayROISize() const +glm::vec2 TrackerInputDevice::getDisplayROISize() const { return m_DisplayROI.size(); } @@ -259,14 +262,14 @@ void TrackerInputDevice::update(BlobVectorPtr pTrackBlobs, // Temporary structure to be put into heap of blob distances. Used only in // trackBlobIDs. struct BlobDistEntry { - BlobDistEntry(double dist, BlobPtr pNewBlob, BlobPtr pOldBlob) + BlobDistEntry(float dist, BlobPtr pNewBlob, BlobPtr pOldBlob) : m_Dist(dist), m_pNewBlob(pNewBlob), m_pOldBlob(pOldBlob) { } - double m_Dist; + float m_Dist; BlobPtr m_pNewBlob; BlobPtr m_pOldBlob; }; @@ -300,14 +303,14 @@ void TrackerInputDevice::trackBlobIDs(BlobVectorPtr pNewBlobs, long long time, oldBlobs.push_back((*it).first); } // Create a heap that contains all distances of old to new blobs < MaxDist - double MaxDist = m_TrackerConfig.getDoubleParam(sConfigPath+"similarity/@value"); - double MaxDistSquared = MaxDist*MaxDist; + float MaxDist = m_TrackerConfig.getFloatParam(sConfigPath+"similarity/@value"); + float MaxDistSquared = MaxDist*MaxDist; priority_queue<BlobDistEntryPtr> distHeap; for (BlobVector::iterator it = pNewBlobs->begin(); it != pNewBlobs->end(); ++it) { BlobPtr pNewBlob = *it; for(BlobVector::iterator it2 = oldBlobs.begin(); it2 != oldBlobs.end(); ++it2) { BlobPtr pOldBlob = *it2; - double distSquared = calcDistSquared(pNewBlob->getCenter(), + float distSquared = glm::distance2(pNewBlob->getCenter(), pOldBlob->getEstimatedNextCenter()); if (distSquared <= MaxDistSquared) { BlobDistEntryPtr pEntry = BlobDistEntryPtr( @@ -368,9 +371,9 @@ TrackerCalibrator* TrackerInputDevice::startCalibration() AVG_ASSERT(!m_pCalibrator); m_pOldTransformer = m_TrackerConfig.getTransform(); m_OldDisplayROI = m_DisplayROI; - m_DisplayROI = DRect(DPoint(0,0), DPoint(m_ActiveDisplaySize)); + m_DisplayROI = FRect(glm::vec2(0,0), glm::vec2(m_ActiveDisplaySize)); m_TrackerConfig.setTransform(DeDistortPtr(new DeDistort( - DPoint(m_pBitmaps[0]->getSize()), DPoint(m_ActiveDisplaySize)))); + glm::vec2(m_pBitmaps[0]->getSize()), glm::vec2(m_ActiveDisplaySize)))); setConfig(); m_pCalibrator = new TrackerCalibrator(m_pBitmaps[0]->getSize(), m_ActiveDisplaySize); @@ -382,10 +385,9 @@ void TrackerInputDevice::endCalibration() AVG_ASSERT(m_pCalibrator); m_TrackerConfig.setTransform(m_pCalibrator->makeTransformer()); m_DisplayROI = m_OldDisplayROI; - DRect area = m_TrackerConfig.getTransform()->getActiveBlobArea(m_DisplayROI); + FRect area = m_TrackerConfig.getTransform()->getActiveBlobArea(m_DisplayROI); if (area.size().x*area.size().y > 1024*1024*8) { - AVG_TRACE(Logger::WARNING, "Ignoring calibration - resulting area would be " - << area); + AVG_LOG_WARNING("Ignoring calibration - resulting area would be " << area); m_TrackerConfig.setTransform(m_pOldTransformer); } setConfig(); @@ -406,7 +408,7 @@ void TrackerInputDevice::abortCalibration() vector<EventPtr> TrackerInputDevice::pollEvents() { - boost::mutex::scoped_lock lock(*m_pMutex); + lock_guard lock(*m_pMutex); vector<EventPtr> pTouchEvents; vector<EventPtr> pTrackEvents; pollEventType(pTouchEvents, m_TouchEvents, CursorEvent::TOUCH); @@ -429,7 +431,7 @@ void TrackerInputDevice::pollEventType(vector<EventPtr>& res, TouchStatusMap& Ev pEvent = pTouchStatus->pollEvent(); if (pEvent) { res.push_back(pEvent); - if (pEvent->getType() == Event::CURSORUP) { + if (pEvent->getType() == Event::CURSOR_UP) { Events.erase(it++); } else { ++it; @@ -476,12 +478,12 @@ void TrackerInputDevice::findFingertips(std::vector<EventPtr>& pTouchEvents) TouchEventPtr pTouchEvent = boost::dynamic_pointer_cast<TouchEvent>(*it); vector<TouchEventPtr> pTrackEvents = pTouchEvent->getRelatedEvents(); if (pTrackEvents.size() > 0) { - double handAngle = pTouchEvent->getHandOrientation(); - double dist = pTouchEvent->getMajorAxis().getNorm()*2; - DPoint tweakVec = DPoint::fromPolar(handAngle, dist); - DPoint newPos = pTouchEvent->getPos()-tweakVec; - newPos.x = max(0.0, min(newPos.x, double(m_ActiveDisplaySize.x))); - newPos.y = max(0.0, min(newPos.y, double(m_ActiveDisplaySize.y))); + float handAngle = pTouchEvent->getHandOrientation(); + float dist = glm::length(pTouchEvent->getMajorAxis())*2; + glm::vec2 tweakVec = fromPolar(handAngle, dist); + glm::vec2 newPos = pTouchEvent->getPos()-tweakVec; + newPos.x = max(0.0f, min(newPos.x, float(m_ActiveDisplaySize.x))); + newPos.y = max(0.0f, min(newPos.y, float(m_ActiveDisplaySize.y))); pTouchEvent->setPos(newPos); } } diff --git a/src/player/TrackerInputDevice.h b/src/player/TrackerInputDevice.h index b09890b..eda8a8d 100644 --- a/src/player/TrackerInputDevice.h +++ b/src/player/TrackerInputDevice.h @@ -1,6 +1,6 @@ // // libavg - Media Playback Engine. -// Copyright (C) 2003-2011 Ulrich von Zadow +// Copyright (C) 2003-2014 Ulrich von Zadow // // This library is free software; you can redistribute it and/or // modify it under the terms of the GNU Lesser General Public @@ -62,8 +62,8 @@ class AVG_API TrackerInputDevice: public IBlobTarget, public IInputDevice void setDebugImages(bool bImg, bool bFinger); void saveConfig(); Bitmap * getImage(TrackerImageID imageID) const; - DPoint getDisplayROIPos() const; - DPoint getDisplayROISize() const; + glm::vec2 getDisplayROIPos() const; + glm::vec2 getDisplayROISize() const; std::vector<EventPtr> pollEvents(); //main thread @@ -95,8 +95,8 @@ class AVG_API TrackerInputDevice: public IBlobTarget, public IInputDevice DeDistortPtr m_pDeDistort; DeDistortPtr m_pOldTransformer; IntPoint m_ActiveDisplaySize; - DRect m_DisplayROI; - DRect m_OldDisplayROI; + FRect m_DisplayROI; + FRect m_OldDisplayROI; TrackerCalibrator * m_pCalibrator; bool m_bFindFingertips; diff --git a/src/player/TrackerTouchStatus.cpp b/src/player/TrackerTouchStatus.cpp index 2377228..f52bd3b 100644 --- a/src/player/TrackerTouchStatus.cpp +++ b/src/player/TrackerTouchStatus.cpp @@ -1,6 +1,6 @@ // // libavg - Media Playback Engine. -// Copyright (C) 2003-2011 Ulrich von Zadow +// Copyright (C) 2003-2014 Ulrich von Zadow // // This library is free software; you can redistribute it and/or // modify it under the terms of the GNU Lesser General Public @@ -35,8 +35,8 @@ namespace avg { int TrackerTouchStatus::s_LastID = 0; TrackerTouchStatus::TrackerTouchStatus(BlobPtr pFirstBlob, long long time, - DeDistortPtr pDeDistort, const DRect& displayROI, Event::Source source) - : TouchStatus(createEvent(source, Event::CURSORDOWN, ++s_LastID, pFirstBlob, time, + DeDistortPtr pDeDistort, const FRect& displayROI, Event::Source source) + : TouchStatus(createEvent(source, Event::CURSOR_DOWN, ++s_LastID, pFirstBlob, time, pDeDistort, displayROI)), m_Source(source), m_pDeDistort(pDeDistort), @@ -62,16 +62,16 @@ void TrackerTouchStatus::blobChanged(BlobPtr pNewBlob, long long time, bool bKee AVG_ASSERT(m_pBlob); AVG_ASSERT(pNewBlob); if (!m_bGone) { - DPoint c = pNewBlob->getCenter(); + glm::vec2 c = pNewBlob->getCenter(); bool bPosChanged; if (bKeepEvent) { bPosChanged = true; } else { - bPosChanged = (calcDist(c, m_LastCenter) > 1); + bPosChanged = (glm::length(c-m_LastCenter) > 1); } if (bPosChanged) { m_LastCenter = pNewBlob->getCenter(); - TouchEventPtr pEvent = createEvent(Event::CURSORMOTION, pNewBlob, time); + TouchEventPtr pEvent = createEvent(Event::CURSOR_MOTION, pNewBlob, time); pushEvent(pEvent, false); } m_pBlob = pNewBlob; @@ -83,7 +83,7 @@ void TrackerTouchStatus::blobChanged(BlobPtr pNewBlob, long long time, bool bKee void TrackerTouchStatus::blobGone() { if (!m_bGone) { - TouchEventPtr pEvent = createEvent(Event::CURSORUP, m_pBlob, m_LastTime+1); + TouchEventPtr pEvent = createEvent(Event::CURSOR_UP, m_pBlob, m_LastTime+1); pushEvent(pEvent, false); m_bGone = true; } @@ -101,11 +101,11 @@ bool TrackerTouchStatus::isStale() TouchEventPtr TrackerTouchStatus::createEvent(Event::Source source, Event::Type type, int id, BlobPtr pBlob, long long time, DeDistortPtr pDeDistort, - const DRect& displayROI) + const FRect& displayROI) { - DPoint blobOffset = pDeDistort->getActiveBlobArea(displayROI).tl; - DPoint pt = pBlob->getCenter() + blobOffset; - DPoint screenpos = pDeDistort->transformBlobToScreen(pt); + glm::vec2 blobOffset = pDeDistort->getActiveBlobArea(displayROI).tl; + glm::vec2 pt = pBlob->getCenter() + blobOffset; + glm::dvec2 screenpos(pDeDistort->transformBlobToScreen(glm::dvec2(pt))); IntPoint pos(int(screenpos.x+0.5), int(screenpos.y+0.5)); return TouchEventPtr(new TouchEvent(id, type, pBlob, pos, source)); diff --git a/src/player/TrackerTouchStatus.h b/src/player/TrackerTouchStatus.h index 53b9e4a..5d75f5d 100644 --- a/src/player/TrackerTouchStatus.h +++ b/src/player/TrackerTouchStatus.h @@ -1,6 +1,6 @@ // // libavg - Media Playback Engine. -// Copyright (C) 2003-2011 Ulrich von Zadow +// Copyright (C) 2003-2014 Ulrich von Zadow // // This library is free software; you can redistribute it and/or // modify it under the terms of the GNU Lesser General Public @@ -26,7 +26,7 @@ #include "Event.h" #include "TouchStatus.h" -#include "../base/Point.h" +#include "../base/GLMHelper.h" #include "../imaging/Blob.h" #include "../imaging/DeDistort.h" @@ -39,7 +39,7 @@ class AVG_API TrackerTouchStatus: public TouchStatus { public: TrackerTouchStatus(BlobPtr pFirstBlob, long long time, DeDistortPtr pDeDistort, - const DRect& displayROI, Event::Source source); + const FRect& displayROI, Event::Source source); virtual ~TrackerTouchStatus(); void blobChanged(BlobPtr pNewBlob, long long time, bool bKeepEvent); void blobGone(); @@ -49,18 +49,18 @@ class AVG_API TrackerTouchStatus: public TouchStatus private: TouchEventPtr createEvent(Event::Source source, Event::Type type, int id, BlobPtr pBlob, long long time, DeDistortPtr pDeDistort, - const DRect& displayROI); + const FRect& displayROI); TouchEventPtr createEvent(Event::Type type, BlobPtr pBlob, long long time); Event::Source m_Source; DeDistortPtr m_pDeDistort; - DRect m_DisplayROI; + FRect m_DisplayROI; bool m_Stale; bool m_bGone; int m_ID; BlobPtr m_pBlob; long long m_LastTime; - DPoint m_LastCenter; + glm::vec2 m_LastCenter; static int s_LastID; }; diff --git a/src/player/NodeDefinition.cpp b/src/player/TypeDefinition.cpp index 32cfb68..f2d5ec5 100644 --- a/src/player/NodeDefinition.cpp +++ b/src/player/TypeDefinition.cpp @@ -1,6 +1,6 @@ // // libavg - Media Playback Engine. -// Copyright (C) 2003-2011 Ulrich von Zadow +// Copyright (C) 2003-2014 Ulrich von Zadow // // This library is free software; you can redistribute it and/or // modify it under the terms of the GNU Lesser General Public @@ -18,10 +18,8 @@ // // Current versions can be found at www.libavg.de // -// Original author of this file is Nick Hebner (hebnern@gmail.com). -// -#include "NodeDefinition.h" +#include "TypeDefinition.h" #include "../base/Logger.h" @@ -29,42 +27,48 @@ using namespace std; namespace avg { -NodeDefinition::NodeDefinition() : +TypeDefinition::TypeDefinition() : m_pBuilder(0) { } -NodeDefinition::NodeDefinition(const string& sName, NodeBuilder pBuilder) +TypeDefinition::TypeDefinition(const string& sName, const string& sBaseName, + ObjectBuilder pBuilder) : m_sName(sName), m_pBuilder(pBuilder) { + if (sBaseName != "") { + TypeDefinition baseDef = TypeRegistry::get()->getTypeDef(sBaseName); + m_Args.copyArgsFrom(baseDef.m_Args); + m_sChildren = baseDef.m_sChildren; + } } -NodeDefinition::~NodeDefinition() +TypeDefinition::~TypeDefinition() { } -const std::string& NodeDefinition::getName() const +const std::string& TypeDefinition::getName() const { return m_sName; } -NodeBuilder NodeDefinition::getBuilder() const +ObjectBuilder TypeDefinition::getBuilder() const { return m_pBuilder; } -const ArgList& NodeDefinition::getDefaultArgs() const +const ArgList& TypeDefinition::getDefaultArgs() const { return m_Args; } -const string& NodeDefinition::getDTDElements() const +const string& TypeDefinition::getDTDElements() const { return m_sDTDElements; } -string NodeDefinition::getDTDChildrenString() const +string TypeDefinition::getDTDChildrenString() const { if (m_sChildren.empty()) { return "EMPTY"; @@ -79,7 +83,7 @@ string NodeDefinition::getDTDChildrenString() const } } -bool NodeDefinition::isChildAllowed(const string& sChild) const +bool TypeDefinition::isChildAllowed(const string& sChild) const { for (unsigned i=0; i<m_sChildren.size(); ++i) { if (m_sChildren[i] == sChild) { @@ -89,34 +93,38 @@ bool NodeDefinition::isChildAllowed(const string& sChild) const return false; } -bool NodeDefinition::hasChildren() const +bool TypeDefinition::hasChildren() const { return !m_sChildren.empty(); } -NodeDefinition& NodeDefinition::extendDefinition(const NodeDefinition& Def) +bool TypeDefinition::isAbstract() const { - m_Args.copyArgsFrom(Def.m_Args); - m_sChildren = Def.m_sChildren; - return *this; + return m_pBuilder == 0; } -NodeDefinition& NodeDefinition::addArg(const ArgBase& newArg) +TypeDefinition& TypeDefinition::addArg(const ArgBase& newArg) { m_Args.setArg(newArg); return *this; } -NodeDefinition& NodeDefinition::addDTDElements(const string& s) +TypeDefinition& TypeDefinition::addDTDElements(const string& s) { m_sDTDElements = s; return *this; } -NodeDefinition& NodeDefinition::addChildren(const vector<string>& sChildren) +TypeDefinition& TypeDefinition::addChildren(const vector<string>& sChildren) { m_sChildren.insert(m_sChildren.end(), sChildren.begin(), sChildren.end()); return *this; } +TypeDefinition& TypeDefinition::addChild(const string& sChild) +{ + m_sChildren.push_back(sChild); + return *this; +} + } diff --git a/src/player/NodeDefinition.h b/src/player/TypeDefinition.h index aeda123..e1275f4 100644 --- a/src/player/NodeDefinition.h +++ b/src/player/TypeDefinition.h @@ -1,6 +1,6 @@ // // libavg - Media Playback Engine. -// Copyright (C) 2003-2011 Ulrich von Zadow +// Copyright (C) 2003-2014 Ulrich von Zadow // // This library is free software; you can redistribute it and/or // modify it under the terms of the GNU Lesser General Public @@ -18,51 +18,52 @@ // // Current versions can be found at www.libavg.de // -// Original author of this file is Nick Hebner (hebnern@gmail.com). -// -#ifndef _NodeDefinition_H_ -#define _NodeDefinition_H_ +#ifndef _TypeDefinition_H_ +#define _TypeDefinition_H_ #include "../api.h" #include "ArgList.h" +#include "TypeRegistry.h" #include <map> #include <string> namespace avg { -class Node; -typedef boost::shared_ptr<Node> NodePtr; -class NodeDefinition; +class ExportedObject; +typedef boost::shared_ptr<ExportedObject> ExportedObjectPtr; +class TypeDefinition; -typedef NodePtr (*NodeBuilder)(const ArgList& Args); -typedef std::map<std::string, NodeDefinition> ChildMap; +typedef ExportedObjectPtr (*ObjectBuilder)(const ArgList& Args); +typedef std::map<std::string, TypeDefinition> ChildMap; -class AVG_API NodeDefinition +class AVG_API TypeDefinition { public: - NodeDefinition(); - NodeDefinition(const std::string& sName, NodeBuilder pBuilder = 0); - virtual ~NodeDefinition(); + TypeDefinition(); + TypeDefinition(const std::string& sName, const std::string& sBaseName="", + ObjectBuilder pBuilder = 0); + virtual ~TypeDefinition(); const std::string& getName() const; - NodeBuilder getBuilder() const; + ObjectBuilder getBuilder() const; const ArgList& getDefaultArgs() const; const std::string& getDTDElements() const; std::string getDTDChildrenString() const; bool isChildAllowed(const std::string& sChild) const; bool hasChildren() const; + bool isAbstract() const; - NodeDefinition& extendDefinition(const NodeDefinition& Def); - NodeDefinition& addArg(const ArgBase& newArg); - NodeDefinition& addDTDElements(const std::string& s); - NodeDefinition& addChildren(const std::vector<std::string>& sChildren); + TypeDefinition& addArg(const ArgBase& newArg); + TypeDefinition& addDTDElements(const std::string& s); + TypeDefinition& addChildren(const std::vector<std::string>& sChildren); + TypeDefinition& addChild(const std::string& sChild); private: std::string m_sName; - NodeBuilder m_pBuilder; + ObjectBuilder m_pBuilder; ArgList m_Args; std::string m_sDTDElements; std::vector<std::string> m_sChildren; diff --git a/src/player/TypeRegistry.cpp b/src/player/TypeRegistry.cpp new file mode 100644 index 0000000..0de3609 --- /dev/null +++ b/src/player/TypeRegistry.cpp @@ -0,0 +1,159 @@ +// +// libavg - Media Playback Engine. +// Copyright (C) 2003-2014 Ulrich von Zadow +// +// This library is free software; you can redistribute it and/or +// modify it under the terms of the GNU Lesser General Public +// License as published by the Free Software Foundation; either +// version 2 of the License, or (at your option) any later version. +// +// This library 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 +// Lesser General Public License for more details. +// +// You should have received a copy of the GNU Lesser General Public +// License along with this library; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +// +// Current versions can be found at www.libavg.de +// +// Original author of this file is Nick Hebner (hebnern@gmail.com). +// + +#include "TypeRegistry.h" +#include "TypeDefinition.h" + +#include "../base/MathHelper.h" +#include "../base/Exception.h" + +#include <set> + +using namespace std; + +namespace avg { + +TypeRegistry* TypeRegistry::s_pInstance = 0; + +TypeRegistry::TypeRegistry() +{ +} + +TypeRegistry::~TypeRegistry() +{ +} + +TypeRegistry* TypeRegistry::get() +{ + if (!s_pInstance) { + s_pInstance = new TypeRegistry(); + } + return s_pInstance; +} + +void TypeRegistry::registerType(const TypeDefinition& def, const char* pParentNames[]) +{ + m_TypeDefs.insert(TypeDefMap::value_type(def.getName(), def)); + + if (pParentNames) { + string sChildArray[1]; + sChildArray[0] = def.getName(); + vector<string> sChildren = vectorFromCArray(1, sChildArray); + const char **ppCurParentName = pParentNames; + + while (*ppCurParentName) { + TypeDefinition def = getTypeDef(*ppCurParentName); + def.addChildren(sChildren); + updateDefinition(def); + + ++ppCurParentName; + } + } +} + +void TypeRegistry::updateDefinition(const TypeDefinition& def) +{ + m_TypeDefs[def.getName()] = def; +} + +ExportedObjectPtr TypeRegistry::createObject(const string& sType, + const xmlNodePtr xmlNode) +{ + const TypeDefinition& def = getTypeDef(sType); + ArgList args(def.getDefaultArgs(), xmlNode); + ObjectBuilder builder = def.getBuilder(); + ExportedObjectPtr pObj = builder(args); + pObj->setTypeInfo(&def); + return pObj; +} + +ExportedObjectPtr TypeRegistry::createObject(const string& sType, const py::dict& pyDict) +{ + const TypeDefinition& def = getTypeDef(sType); + py::dict effParams; + effParams = pyDict; + ArgList args(def.getDefaultArgs(), effParams); + ObjectBuilder builder = def.getBuilder(); + ExportedObjectPtr pObj = builder(args); + pObj->setTypeInfo(&def); + return pObj; +} + +string TypeRegistry::getDTD() const +{ + if (m_TypeDefs.empty()) { + return string(""); + } + + stringstream ss; + + for (TypeDefMap::const_iterator defIt = m_TypeDefs.begin(); + defIt != m_TypeDefs.end(); defIt++) + { + const TypeDefinition& def = defIt->second; + if (!def.isAbstract()) { + writeTypeDTD(def, ss); + } + } + + for (TypeDefMap::const_iterator defIt = m_TypeDefs.begin(); + defIt != m_TypeDefs.end(); defIt++) + { + const TypeDefinition& def = defIt->second; + if (!def.isAbstract()) { + ss << def.getDTDElements(); + } + } + + return ss.str(); +} + +TypeDefinition& TypeRegistry::getTypeDef(const string& sType) +{ + TypeDefMap::iterator it = m_TypeDefs.find(sType); + if (it == m_TypeDefs.end()) { + throw (Exception (AVG_ERR_XML_NODE_UNKNOWN, + string("Unknown node type ") + sType + " encountered.")); + } + return it->second; +} + +void TypeRegistry::writeTypeDTD(const TypeDefinition& def, stringstream& ss) const +{ + ss << "<!ELEMENT " << def.getName() << " " << def.getDTDChildrenString() << " >\n"; + if (!def.getDefaultArgs().getArgMap().empty()) { + ss << "<!ATTLIST " << def.getName(); + for (ArgMap::const_iterator argIt = def.getDefaultArgs().getArgMap().begin(); + argIt != def.getDefaultArgs().getArgMap().end(); argIt++) + { + string argName = argIt->first; + string argType = (argName == "id") ? "ID" : "CDATA"; + string argRequired = def.getDefaultArgs().getArg(argName)->isRequired() ? + "#REQUIRED" : "#IMPLIED"; + ss << "\n " << argName << " " << argType << " " << argRequired; + } + ss << " >\n"; + } +} + +} diff --git a/src/player/NodeRegistry.h b/src/player/TypeRegistry.h index 9aee371..3b38018 100644 --- a/src/player/NodeRegistry.h +++ b/src/player/TypeRegistry.h @@ -1,6 +1,6 @@ // // libavg - Media Playback Engine. -// Copyright (C) 2003-2011 Ulrich von Zadow +// Copyright (C) 2003-2014 Ulrich von Zadow // // This library is free software; you can redistribute it and/or // modify it under the terms of the GNU Lesser General Public @@ -21,14 +21,14 @@ // Original author of this file is Nick Hebner (hebnern@gmail.com). // -#ifndef _NodeRegistry_H_ -#define _NodeRegistry_H_ +#ifndef _TypeRegistry_H_ +#define _TypeRegistry_H_ #include "../api.h" #include "WrapPython.h" #include "Node.h" #include "ArgList.h" -#include "NodeDefinition.h" +#include "TypeDefinition.h" #include <map> #include <string> @@ -36,25 +36,28 @@ namespace avg { -class AVG_API NodeRegistry +class AVG_API TypeRegistry { public: - NodeRegistry(); - virtual ~NodeRegistry(); + virtual ~TypeRegistry(); + static TypeRegistry* get(); - void registerNodeType(const NodeDefinition& def); - void updateNodeDefinition(const NodeDefinition& def); - const NodeDefinition& getNodeDef(const std::string& Type); - NodePtr createNode(const std::string& Type, const xmlNodePtr xmlNode); - NodePtr createNode(const std::string& Type, const boost::python::dict& PyDict); + void registerType(const TypeDefinition& def, const char* pParentNames[] = 0); + void updateDefinition(const TypeDefinition& def); + TypeDefinition& getTypeDef(const std::string& Type); + ExportedObjectPtr createObject(const std::string& Type, const xmlNodePtr xmlNode); + ExportedObjectPtr createObject(const std::string& Type, const py::dict& PyDict); std::string getDTD() const; private: - void writeNodeDTD(const NodeDefinition& def, std::stringstream& ss) const; + TypeRegistry(); + void writeTypeDTD(const TypeDefinition& def, std::stringstream& ss) const; - typedef std::map<std::string, NodeDefinition> NodeDefMap; - NodeDefMap m_NodeDefs; + typedef std::map<std::string, TypeDefinition> TypeDefMap; + TypeDefMap m_TypeDefs; + + static TypeRegistry* s_pInstance; }; } diff --git a/src/player/VectorNode.cpp b/src/player/VectorNode.cpp index 427d637..f484a3b 100644 --- a/src/player/VectorNode.cpp +++ b/src/player/VectorNode.cpp @@ -1,6 +1,6 @@ // // libavg - Media Playback Engine. -// Copyright (C) 2003-2011 Ulrich von Zadow +// Copyright (C) 2003-2014 Ulrich von Zadow // // This library is free software; you can redistribute it and/or // modify it under the terms of the GNU Lesser General Public @@ -21,7 +21,7 @@ #include "VectorNode.h" -#include "NodeDefinition.h" +#include "TypeDefinition.h" #include "OGLSurface.h" #include "Image.h" @@ -37,6 +37,8 @@ #include "../graphics/VertexArray.h" #include "../graphics/Filterfliprgb.h" +#include "../glm/gtx/norm.hpp" + #include <iostream> #include <sstream> @@ -45,19 +47,20 @@ using namespace boost; namespace avg { -NodeDefinition VectorNode::createDefinition() +void VectorNode::registerType() { - return NodeDefinition("vector") - .extendDefinition(Node::createDefinition()) + TypeDefinition def = TypeDefinition("vectornode", "node") .addArg(Arg<string>("color", "FFFFFF", false, offsetof(VectorNode, m_sColorName))) - .addArg(Arg<double>("strokewidth", 1, false, offsetof(VectorNode, m_StrokeWidth))) + .addArg(Arg<float>("strokewidth", 1, false, offsetof(VectorNode, m_StrokeWidth))) .addArg(Arg<UTF8String>("texhref", "", false, offsetof(VectorNode, m_TexHRef))) .addArg(Arg<string>("blendmode", "blend", false, offsetof(VectorNode, m_sBlendMode))) ; + TypeRegistry::get()->registerType(def); } VectorNode::VectorNode(const ArgList& args) + : m_Transform(glm::mat4(0)) { m_pShape = ShapePtr(createDefaultShape()); @@ -79,7 +82,6 @@ void VectorNode::connectDisplay() m_Color = colorStringToColor(m_sColorName); Node::connectDisplay(); m_pShape->moveToGPU(); - m_OldOpacity = -1; setBlendModeStr(m_sBlendMode); } @@ -140,51 +142,44 @@ void VectorNode::setBlendModeStr(const string& sBlendMode) static ProfilingZoneID PrerenderProfilingZone("VectorNode::prerender"); -void VectorNode::preRender() +void VectorNode::preRender(const VertexArrayPtr& pVA, bool bIsParentActive, + float parentEffectiveOpacity) { - Node::preRender(); - double curOpacity = getEffectiveOpacity(); - - VertexArrayPtr pVA = m_pShape->getVertexArray(); + Node::preRender(pVA, bIsParentActive, parentEffectiveOpacity); { - if (m_bDrawNeeded || curOpacity != m_OldOpacity) { - ScopeTimer timer(PrerenderProfilingZone); - pVA->reset(); + ScopeTimer timer(PrerenderProfilingZone); + VertexDataPtr pShapeVD = m_pShape->getVertexData(); + if (m_bDrawNeeded) { + pShapeVD->reset(); Pixel32 color = getColorVal(); - color.setA((unsigned char)(curOpacity*255)); - calcVertexes(pVA, color); - pVA->update(); + calcVertexes(pShapeVD, color); m_bDrawNeeded = false; - m_OldOpacity = curOpacity; + } + if (isVisible()) { + m_pShape->setVertexArray(pVA); } } - } -void VectorNode::maybeRender(const DRect& rect) +void VectorNode::maybeRender(const glm::mat4& parentTransform) { AVG_ASSERT(getState() == NS_CANRENDER); if (isVisible()) { - if (getID() != "") { - AVG_TRACE(Logger::BLTS, "Rendering " << getTypeStr() << - " with ID " << getID()); - } else { - AVG_TRACE(Logger::BLTS, "Rendering " << getTypeStr()); - } - GLContext::getCurrent()->setBlendMode(m_BlendMode); - render(rect); + m_Transform = parentTransform; + GLContext::getMain()->setBlendMode(m_BlendMode); + render(); } } static ProfilingZoneID RenderProfilingZone("VectorNode::render"); -void VectorNode::render(const DRect& rect) +void VectorNode::render() { ScopeTimer timer(RenderProfilingZone); -// glPolygonMode(GL_FRONT_AND_BACK, GL_LINE); - double curOpacity = getEffectiveOpacity(); - glColor4d(1.0, 1.0, 1.0, curOpacity); - m_pShape->draw(); + float curOpacity = getEffectiveOpacity(); + if (curOpacity > 0.01) { + m_pShape->draw(m_Transform, curOpacity); + } } void VectorNode::setColor(const string& sColor) @@ -201,7 +196,7 @@ const string& VectorNode::getColor() const return m_sColorName; } -void VectorNode::setStrokeWidth(double width) +void VectorNode::setStrokeWidth(float width) { if (width != m_StrokeWidth) { m_bDrawNeeded = true; @@ -209,7 +204,7 @@ void VectorNode::setStrokeWidth(double width) } } -double VectorNode::getStrokeWidth() const +float VectorNode::getStrokeWidth() const { return m_StrokeWidth; } @@ -259,27 +254,27 @@ bool VectorNode::isDrawNeeded() return m_bDrawNeeded; } -void VectorNode::calcPolyLineCumulDist(vector<double>& cumulDists, - const vector<DPoint>& pts, bool bIsClosed) +void VectorNode::calcPolyLineCumulDist(vector<float>& cumulDists, + const vector<glm::vec2>& pts, bool bIsClosed) { cumulDists.clear(); cumulDists.reserve(pts.size()); if (!pts.empty()) { - vector<double> distances; + vector<float> distances; distances.reserve(pts.size()); - double totalDist = 0; + float totalDist = 0; for (unsigned i = 1; i < pts.size(); ++i) { - double dist = calcDist(pts[i], pts[i-1]); + float dist = glm::length(pts[i] - pts[i-1]); distances.push_back(dist); totalDist += dist; } if (bIsClosed) { - double dist = calcDist(pts[pts.size()-1], pts[0]); + float dist = glm::length(pts[pts.size()-1] - pts[0]); distances.push_back(dist); totalDist += dist; } - double cumulDist = 0; + float cumulDist = 0; cumulDists.push_back(0); for (unsigned i = 0; i < distances.size(); ++i) { cumulDist += distances[i]/totalDist; @@ -288,8 +283,8 @@ void VectorNode::calcPolyLineCumulDist(vector<double>& cumulDists, } } -void VectorNode::calcEffPolyLineTexCoords(vector<double>& effTC, - const vector<double>& tc, const vector<double>& cumulDist) +void VectorNode::calcEffPolyLineTexCoords(vector<float>& effTC, + const vector<float>& tc, const vector<float>& cumulDist) { if (tc.empty()) { effTC = cumulDist; @@ -298,39 +293,40 @@ void VectorNode::calcEffPolyLineTexCoords(vector<double>& effTC, } else { effTC.reserve(cumulDist.size()); effTC = tc; - double minGivenTexCoord = tc[0]; - double maxGivenTexCoord = tc[tc.size()-1]; - double maxCumulDist = cumulDist[tc.size()-1]; + float minGivenTexCoord = tc[0]; + float maxGivenTexCoord = tc[tc.size()-1]; + float maxCumulDist = cumulDist[tc.size()-1]; int baselineDist = 0; for (unsigned i = tc.size(); i < cumulDist.size(); ++i) { int repeatFactor = int(cumulDist[i]/maxCumulDist); - double effCumulDist = fmod(cumulDist[i], maxCumulDist); + float effCumulDist = fmod(cumulDist[i], maxCumulDist); while (cumulDist[baselineDist+1] < effCumulDist) { baselineDist++; } - double ratio = (effCumulDist-cumulDist[baselineDist])/ + float ratio = (effCumulDist-cumulDist[baselineDist])/ (cumulDist[baselineDist+1]-cumulDist[baselineDist]); - double rawTexCoord = (1-ratio)*tc[baselineDist] +ratio*tc[baselineDist+1]; - double texCoord = rawTexCoord + float rawTexCoord = (1-ratio)*tc[baselineDist] +ratio*tc[baselineDist+1]; + float texCoord = rawTexCoord +repeatFactor*(maxGivenTexCoord-minGivenTexCoord); effTC.push_back(texCoord); } } + } -void VectorNode::calcPolyLine(const vector<DPoint>& origPts, - const vector<double>& origTexCoords, bool bIsClosed, LineJoin lineJoin, - VertexArrayPtr& pVertexArray, Pixel32 color) +void VectorNode::calcPolyLine(const vector<glm::vec2>& origPts, + const vector<float>& origTexCoords, bool bIsClosed, LineJoin lineJoin, + const VertexDataPtr& pVertexData, Pixel32 color) { - vector<DPoint> pts; + vector<glm::vec2> pts; pts.reserve(origPts.size()); - vector<double> texCoords; + vector<float> texCoords; texCoords.reserve(origPts.size()); pts.push_back(origPts[0]); texCoords.push_back(origTexCoords[0]); for (unsigned i = 1; i < origPts.size(); ++i) { - if (calcDistSquared(origPts[i], origPts[i-1]) > 0.1) { + if (glm::distance2(origPts[i], origPts[i-1]) > 0.1) { pts.push_back(origPts[i]); texCoords.push_back(origTexCoords[i]); } @@ -353,38 +349,38 @@ void VectorNode::calcPolyLine(const vector<DPoint>& origPts, // First points if (bIsClosed) { WideLine lastLine = lines[lines.size()-1]; - DPoint pli = getLineLineIntersection(lastLine.pl0, lastLine.dir, + glm::vec2 pli = getLineLineIntersection(lastLine.pl0, lastLine.dir, lines[0].pl0, lines[0].dir); - DPoint pri = getLineLineIntersection(lastLine.pr0, lastLine.dir, + glm::vec2 pri = getLineLineIntersection(lastLine.pr0, lastLine.dir, lines[0].pr0, lines[0].dir); Triangle tri(lastLine.pl1, lines[0].pl0, pri); if (tri.isClockwise()) { - if (!DLineSegment(lastLine.pr0, lastLine.pr1).isPointOver(pri) && - !DLineSegment(lines[0].pr0, lines[0].pr1).isPointOver(pri)) + if (!LineSegment(lastLine.pr0, lastLine.pr1).isPointOver(pri) && + !LineSegment(lines[0].pr0, lines[0].pr1).isPointOver(pri)) { pri = lines[0].pr1; } } else { - if (!DLineSegment(lastLine.pl0, lastLine.pl1).isPointOver(pli) && - !DLineSegment(lines[0].pl0, lines[0].pl1).isPointOver(pli)) + if (!LineSegment(lastLine.pl0, lastLine.pl1).isPointOver(pli) && + !LineSegment(lines[0].pl0, lines[0].pl1).isPointOver(pli)) { pli = lines[0].pl1; } } - double curTC = texCoords[0]; + float curTC = texCoords[0]; switch (lineJoin) { case LJ_MITER: - pVertexArray->appendPos(pli, DPoint(curTC,1), color); - pVertexArray->appendPos(pri, DPoint(curTC,0), color); + pVertexData->appendPos(pli, glm::vec2(curTC,1), color); + pVertexData->appendPos(pri, glm::vec2(curTC,0), color); break; case LJ_BEVEL: { if (tri.isClockwise()) { - pVertexArray->appendPos(lines[0].pl0, DPoint(curTC,1), color); - pVertexArray->appendPos(pri, DPoint(curTC,0), color); + pVertexData->appendPos(lines[0].pl0, glm::vec2(curTC,1), color); + pVertexData->appendPos(pri, glm::vec2(curTC,0), color); } else { - pVertexArray->appendPos(pli, DPoint(curTC,1), color); - pVertexArray->appendPos(lines[0].pr0, DPoint(curTC,0), color); + pVertexData->appendPos(pli, glm::vec2(curTC,1), color); + pVertexData->appendPos(lines[0].pr0, glm::vec2(curTC,0), color); } } break; @@ -393,8 +389,8 @@ void VectorNode::calcPolyLine(const vector<DPoint>& origPts, break; } } else { - pVertexArray->appendPos(lines[0].pl0, DPoint(texCoords[0],1), color); - pVertexArray->appendPos(lines[0].pr0, DPoint(texCoords[0],0), color); + pVertexData->appendPos(lines[0].pl0, glm::vec2(texCoords[0],1), color); + pVertexData->appendPos(lines[0].pr0, glm::vec2(texCoords[0],0), color); } // All complete line segments @@ -412,53 +408,55 @@ void VectorNode::calcPolyLine(const vector<DPoint>& origPts, } else { pLine2 = &(lines[i+1]); } - DPoint pli = getLineLineIntersection(pLine1->pl0, pLine1->dir, pLine2->pl0, pLine2->dir); - DPoint pri = getLineLineIntersection(pLine1->pr0, pLine1->dir, pLine2->pr0, pLine2->dir); + glm::vec2 pli = getLineLineIntersection(pLine1->pl0, pLine1->dir, pLine2->pl0, + pLine2->dir); + glm::vec2 pri = getLineLineIntersection(pLine1->pr0, pLine1->dir, pLine2->pr0, + pLine2->dir); Triangle tri(pLine1->pl1, pLine2->pl0, pri); if (tri.isClockwise()) { - if (!DLineSegment(pLine1->pr0, pLine1->pr1).isPointOver(pri) && - !DLineSegment(pLine2->pr0, pLine2->pr1).isPointOver(pri)) + if (!LineSegment(pLine1->pr0, pLine1->pr1).isPointOver(pri) && + !LineSegment(pLine2->pr0, pLine2->pr1).isPointOver(pri)) { pri = pLine2->pr1; } } else { - if (!DLineSegment(pLine1->pl0, pLine1->pl1).isPointOver(pli) && - !DLineSegment(pLine2->pl0, pLine2->pl1).isPointOver(pli)) + if (!LineSegment(pLine1->pl0, pLine1->pl1).isPointOver(pli) && + !LineSegment(pLine2->pl0, pLine2->pl1).isPointOver(pli)) { pli = pLine2->pl1; } } - int curVertex = pVertexArray->getCurVert(); - double curTC = texCoords[i+1]; + int curVertex = pVertexData->getNumVerts(); + float curTC = texCoords[i+1]; switch (lineJoin) { case LJ_MITER: - pVertexArray->appendPos(pli, DPoint(curTC,1), color); - pVertexArray->appendPos(pri, DPoint(curTC,0), color); - pVertexArray->appendQuadIndexes( + pVertexData->appendPos(pli, glm::vec2(curTC,1), color); + pVertexData->appendPos(pri, glm::vec2(curTC,0), color); + pVertexData->appendQuadIndexes( curVertex-1, curVertex-2, curVertex+1, curVertex); break; case LJ_BEVEL: { - double TC0; - double TC1; + float TC0; + float TC1; if (tri.isClockwise()) { calcBevelTC(*pLine1, *pLine2, true, texCoords, i+1, TC0, TC1); - pVertexArray->appendPos(pLine1->pl1, DPoint(TC0,1), color); - pVertexArray->appendPos(pLine2->pl0, DPoint(TC1,1), color); - pVertexArray->appendPos(pri, DPoint(curTC,0), color); - pVertexArray->appendQuadIndexes( + pVertexData->appendPos(pLine1->pl1, glm::vec2(TC0,1), color); + pVertexData->appendPos(pLine2->pl0, glm::vec2(TC1,1), color); + pVertexData->appendPos(pri, glm::vec2(curTC,0), color); + pVertexData->appendQuadIndexes( curVertex-1, curVertex-2, curVertex+2, curVertex); - pVertexArray->appendTriIndexes( + pVertexData->appendTriIndexes( curVertex, curVertex+1, curVertex+2); } else { calcBevelTC(*pLine1, *pLine2, false, texCoords, i+1, TC0, TC1); - pVertexArray->appendPos(pLine1->pr1, DPoint(TC0,0), color); - pVertexArray->appendPos(pli, DPoint(curTC,1), color); - pVertexArray->appendPos(pLine2->pr0, DPoint(TC1,0), color); - pVertexArray->appendQuadIndexes( + pVertexData->appendPos(pLine1->pr1, glm::vec2(TC0,0), color); + pVertexData->appendPos(pli, glm::vec2(curTC,1), color); + pVertexData->appendPos(pLine2->pr0, glm::vec2(TC1,0), color); + pVertexData->appendQuadIndexes( curVertex-2, curVertex-1, curVertex+1, curVertex); - pVertexArray->appendTriIndexes( + pVertexData->appendTriIndexes( curVertex, curVertex+1, curVertex+2); } } @@ -470,49 +468,54 @@ void VectorNode::calcPolyLine(const vector<DPoint>& origPts, // Last segment (PolyLine only) if (!bIsClosed) { - int curVertex = pVertexArray->getCurVert(); - double curTC = texCoords[numPts-1]; - pVertexArray->appendPos(lines[numPts-2].pl1, DPoint(curTC,1), color); - pVertexArray->appendPos(lines[numPts-2].pr1, DPoint(curTC,0), color); - pVertexArray->appendQuadIndexes(curVertex-1, curVertex-2, curVertex+1, curVertex); + int curVertex = pVertexData->getNumVerts(); + float curTC = texCoords[numPts-1]; + pVertexData->appendPos(lines[numPts-2].pl1, glm::vec2(curTC,1), color); + pVertexData->appendPos(lines[numPts-2].pr1, glm::vec2(curTC,0), color); + pVertexData->appendQuadIndexes(curVertex-1, curVertex-2, curVertex+1, curVertex); } } void VectorNode::calcBevelTC(const WideLine& line1, const WideLine& line2, - bool bIsLeft, const vector<double>& texCoords, unsigned i, - double& TC0, double& TC1) + bool bIsLeft, const vector<float>& texCoords, unsigned i, + float& TC0, float& TC1) { - double line1Len = line1.getLen(); - double line2Len = line2.getLen(); - double triLen; + float line1Len = line1.getLen(); + float line2Len = line2.getLen(); + float triLen; if (bIsLeft) { - triLen = calcDist(line1.pl1, line2.pl0); + triLen = glm::length(line1.pl1 - line2.pl0); } else { - triLen = calcDist(line1.pr1, line2.pr0); + triLen = glm::length(line1.pr1 - line2.pr0); } - double ratio0 = line1Len/(line1Len+triLen/2); + float ratio0 = line1Len/(line1Len+triLen/2); TC0 = (1-ratio0)*texCoords[i-1]+ratio0*texCoords[i]; - double nextTexCoord; + float nextTexCoord; if (i == texCoords.size()-1) { nextTexCoord = texCoords[i]; } else { nextTexCoord = texCoords[i+1]; } - double ratio1 = line2Len/(line2Len+triLen/2); + float ratio1 = line2Len/(line2Len+triLen/2); TC1 = ratio1*texCoords[i]+(1-ratio1)*nextTexCoord; } -int VectorNode::getNumDifferentPts(const vector<DPoint>& pts) +int VectorNode::getNumDifferentPts(const vector<glm::vec2>& pts) { int numPts = pts.size(); for (unsigned i=1; i<pts.size(); ++i) { - if (calcDistSquared(pts[i], pts[i-1])<0.1) { + if (glm::distance2(pts[i], pts[i-1])<0.1) { numPts--; } } return numPts; } +const glm::mat4& VectorNode::getTransform() const +{ + return m_Transform; +} + Shape* VectorNode::createDefaultShape() const { return new Shape(MaterialInfo(GL_REPEAT, GL_CLAMP_TO_EDGE, false)); diff --git a/src/player/VectorNode.h b/src/player/VectorNode.h index d17c7c4..4568342 100644 --- a/src/player/VectorNode.h +++ b/src/player/VectorNode.h @@ -1,6 +1,6 @@ // // libavg - Media Playback Engine. -// Copyright (C) 2003-2011 Ulrich von Zadow +// Copyright (C) 2003-2014 Ulrich von Zadow // // This library is free software; you can redistribute it and/or // modify it under the terms of the GNU Lesser General Public @@ -40,7 +40,7 @@ class AVG_API VectorNode : public Node public: enum LineJoin {LJ_MITER, LJ_BEVEL}; - static NodeDefinition createDefinition(); + static void registerType(); VectorNode(const ArgList& args); virtual ~VectorNode(); @@ -56,17 +56,18 @@ class AVG_API VectorNode : public Node const std::string& getBlendModeStr() const; void setBlendModeStr(const std::string& sBlendMode); - virtual void preRender(); - virtual void maybeRender(const DRect& rect); - virtual void render(const DRect& rect); + virtual void preRender(const VertexArrayPtr& pVA, bool bIsParentActive, + float parentEffectiveOpacity); + virtual void maybeRender(const glm::mat4& parentTransform); + virtual void render(); - virtual void calcVertexes(VertexArrayPtr& pVertexArray, Pixel32 color) = 0; + virtual void calcVertexes(const VertexDataPtr& pVertexData, Pixel32 color) = 0; void setColor(const std::string& sColor); const std::string& getColor() const; - void setStrokeWidth(double width); - double getStrokeWidth() const; + void setStrokeWidth(float width); + float getStrokeWidth() const; static LineJoin string2LineJoin(const std::string& s); static std::string lineJoin2String(LineJoin lineJoin); @@ -78,33 +79,35 @@ class AVG_API VectorNode : public Node void setDrawNeeded(); bool isDrawNeeded(); bool hasVASizeChanged(); - void calcPolyLineCumulDist(std::vector<double>& cumulDist, - const std::vector<DPoint>& pts, bool bIsClosed); - void calcEffPolyLineTexCoords(std::vector<double>& effTC, - const std::vector<double>& tc, const std::vector<double>& cumulDist); - - void calcPolyLine(const std::vector<DPoint>& origPts, - const std::vector<double>& origTexCoords, bool bIsClosed, LineJoin lineJoin, - VertexArrayPtr& pVertexArray, Pixel32 color); + void calcPolyLineCumulDist(std::vector<float>& cumulDist, + const std::vector<glm::vec2>& pts, bool bIsClosed); + void calcEffPolyLineTexCoords(std::vector<float>& effTC, + const std::vector<float>& tc, const std::vector<float>& cumulDist); + + void calcPolyLine(const std::vector<glm::vec2>& origPts, + const std::vector<float>& origTexCoords, bool bIsClosed, + LineJoin lineJoin, const VertexDataPtr& pVertexData, Pixel32 color); void calcBevelTC(const WideLine& line1, const WideLine& line2, - bool bIsLeft, const std::vector<double>& texCoords, unsigned i, - double& TC0, double& TC1); - int getNumDifferentPts(const std::vector<DPoint>& pts); + bool bIsLeft, const std::vector<float>& texCoords, unsigned i, + float& TC0, float& TC1); + int getNumDifferentPts(const std::vector<glm::vec2>& pts); + + protected: + const glm::mat4& getTransform() const; private: Shape* createDefaultShape() const; - private: std::string m_sColorName; Pixel32 m_Color; - double m_StrokeWidth; + float m_StrokeWidth; UTF8String m_TexHRef; std::string m_sBlendMode; bool m_bDrawNeeded; bool m_bVASizeChanged; - double m_OldOpacity; + glm::mat4 m_Transform; ShapePtr m_pShape; GLContext::BlendMode m_BlendMode; }; diff --git a/src/player/VersionInfo.cpp b/src/player/VersionInfo.cpp new file mode 100644 index 0000000..3ab861b --- /dev/null +++ b/src/player/VersionInfo.cpp @@ -0,0 +1,72 @@ +// +// libavg - Media Playback Engine. +// Copyright (C) 2003-2014 Ulrich von Zadow +// +// This library is free software; you can redistribute it and/or +// modify it under the terms of the GNU Lesser General Public +// License as published by the Free Software Foundation; either +// version 2 of the License, or (at your option) any later version. +// +// This library 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 +// Lesser General Public License for more details. +// +// You should have received a copy of the GNU Lesser General Public +// License along with this library; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +// +// Current versions can be found at www.libavg.de +// + +#include "VersionInfo.h" +#include "../version.h" + +namespace avg { + +const std::string VersionInfo::getFull() +{ + return std::string(AVG_VERSION_FULL); +} + +const std::string VersionInfo::getRelease() +{ + return std::string(AVG_VERSION_RELEASE); +} + +const std::string VersionInfo::getBranchUrl() +{ + return std::string(AVG_VERSION_BRANCH_URL); +} + +const std::string VersionInfo::getBuilder() +{ + return std::string(AVG_VERSION_BUILDER); +} + +const std::string VersionInfo::getBuildTime() +{ + return std::string(AVG_VERSION_BUILDTIME); +} + +const std::string VersionInfo::getMajor() +{ + return AVG_VERSION_MAJOR; +} + +const std::string VersionInfo::getMinor() +{ + return AVG_VERSION_MINOR; +} + +const std::string VersionInfo::getMicro() +{ + return AVG_VERSION_MICRO; +} + +int VersionInfo::getRevision() +{ + return AVG_VERSION_REVISION; +} + +} diff --git a/src/player/VersionInfo.h b/src/player/VersionInfo.h new file mode 100644 index 0000000..5a01e7e --- /dev/null +++ b/src/player/VersionInfo.h @@ -0,0 +1,47 @@ +// +// libavg - Media Playback Engine. +// Copyright (C) 2003-2014 Ulrich von Zadow +// +// This library is free software; you can redistribute it and/or +// modify it under the terms of the GNU Lesser General Public +// License as published by the Free Software Foundation; either +// version 2 of the License, or (at your option) any later version. +// +// This library 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 +// Lesser General Public License for more details. +// +// You should have received a copy of the GNU Lesser General Public +// License along with this library; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +// +// Current versions can be found at www.libavg.de +// + +#ifndef _VersionInfo_H_ +#define _VersionInfo_H_ + +#include "../api.h" +#include <string> + +namespace avg { + +class AVG_API VersionInfo +{ + public: + const std::string getFull(); + const std::string getRelease(); + const std::string getBranchUrl(); + const std::string getBuilder(); + const std::string getBuildTime(); + const std::string getMajor(); + const std::string getMinor(); + const std::string getMicro(); + int getRevision(); +}; + +} + +#endif + diff --git a/src/player/VideoNode.cpp b/src/player/VideoNode.cpp index 0df4129..75b2ccc 100644 --- a/src/player/VideoNode.cpp +++ b/src/player/VideoNode.cpp @@ -1,6 +1,6 @@ // // libavg - Media Playback Engine. -// Copyright (C) 2003-2011 Ulrich von Zadow +// Copyright (C) 2003-2014 Ulrich von Zadow // // This library is free software; you can redistribute it and/or // modify it under the terms of the GNU Lesser General Public @@ -21,22 +21,26 @@ #include "VideoNode.h" #include "Player.h" #include "OGLSurface.h" -#include "NodeDefinition.h" +#include "TypeDefinition.h" #include "Canvas.h" #include "../base/Exception.h" #include "../base/Logger.h" #include "../base/ScopeTimer.h" #include "../base/XMLHelper.h" +#include "../base/ObjectCounter.h" #include "../graphics/Filterfill.h" #include "../graphics/GLTexture.h" #include "../graphics/TextureMover.h" -#include "../audio/SDLAudioEngine.h" +#include "../audio/AudioEngine.h" #include "../video/AsyncVideoDecoder.h" -#include "../video/FFMpegDecoder.h" +#include "../video/SyncVideoDecoder.h" +#ifdef AVG_ENABLE_VDPAU +#include "../video/VDPAUDecoder.h" +#endif #include <iostream> #include <sstream> @@ -45,25 +49,28 @@ #include <unistd.h> #endif -using namespace boost::python; +using namespace boost; using namespace std; namespace avg { -NodeDefinition VideoNode::createDefinition() +void VideoNode::registerType() { - return NodeDefinition("video", Node::buildNode<VideoNode>) - .extendDefinition(RasterNode::createDefinition()) + TypeDefinition def = TypeDefinition("video", "rasternode", + ExportedObject::buildObject<VideoNode>) .addArg(Arg<UTF8String>("href", "", false, offsetof(VideoNode, m_href))) .addArg(Arg<bool>("loop", false, false, offsetof(VideoNode, m_bLoop))) .addArg(Arg<bool>("threaded", true, false, offsetof(VideoNode, m_bThreaded))) - .addArg(Arg<double>("fps", 0.0, false, offsetof(VideoNode, m_FPS))) + .addArg(Arg<float>("fps", 0.0, false, offsetof(VideoNode, m_FPS))) .addArg(Arg<int>("queuelength", 8, false, offsetof(VideoNode, m_QueueLength))) - .addArg(Arg<double>("volume", 1.0, false, offsetof(VideoNode, m_Volume))) + .addArg(Arg<float>("volume", 1.0, false, offsetof(VideoNode, m_Volume))) .addArg(Arg<bool>("accelerated", false, false, offsetof(VideoNode, m_bUsesHardwareAcceleration))) + .addArg(Arg<bool>("enablesound", true, false, + offsetof(VideoNode, m_bEnableSound))) ; + TypeRegistry::get()->registerType(def); } VideoNode::VideoNode(const ArgList& args) @@ -78,7 +85,9 @@ VideoNode::VideoNode(const ArgList& args) m_SeekBeforeCanRenderTime(0), m_pDecoder(0), m_Volume(1.0), - m_bUsesHardwareAcceleration(false) + m_bUsesHardwareAcceleration(false), + m_bEnableSound(true), + m_AudioID(-1) { args.setMembers(this); m_Filename = m_href; @@ -88,11 +97,11 @@ VideoNode::VideoNode(const ArgList& args) "Can't set queue length for unthreaded videos because there is no decoder queue in this case."); } if (m_bThreaded) { - VideoDecoderPtr pSyncDecoder = VideoDecoderPtr(new FFMpegDecoder()); - m_pDecoder = new AsyncVideoDecoder(pSyncDecoder, m_QueueLength); + m_pDecoder = new AsyncVideoDecoder(m_QueueLength); } else { - m_pDecoder = new FFMpegDecoder(); + m_pDecoder = new SyncVideoDecoder(); } + ObjectCounter::get()->incRef(&typeid(*this)); } @@ -124,6 +133,7 @@ void VideoNode::connectDisplay() void VideoNode::connect(CanvasPtr pCanvas) { pCanvas->registerFrameEndListener(this); + checkReload(); RasterNode::connect(pCanvas); } @@ -183,7 +193,7 @@ void VideoNode::seekToFrame(int frameNum) } exceptionIfUnloaded("seekToFrame"); if (getCurFrame() != frameNum) { - long long destTime = (long long)(frameNum*1000.0/m_pDecoder->getNominalFPS()); + long long destTime = (long long)(frameNum*1000.0/m_pDecoder->getStreamFPS()); seek(destTime); } } @@ -200,11 +210,32 @@ long long VideoNode::getDuration() const return (long long)(m_pDecoder->getVideoInfo().m_Duration*1000); } +long long VideoNode::getVideoDuration() const +{ + exceptionIfUnloaded("getVideoDuration"); + return (long long)(m_pDecoder->getVideoInfo().m_VideoDuration*1000); +} + +long long VideoNode::getAudioDuration() const +{ + exceptionIfUnloaded("getAudioDuration"); + if (!hasAudio()) { + throw Exception(AVG_ERR_INVALID_ARGS, "Video has no audio track."); + } + + return (long long)(m_pDecoder->getVideoInfo().m_AudioDuration*1000); +} + int VideoNode::getBitrate() const { exceptionIfUnloaded("getBitrate"); return m_pDecoder->getVideoInfo().m_Bitrate; } +std::string VideoNode::getContainerFormat() const +{ + exceptionIfUnloaded("getContainerFormat"); + return m_pDecoder->getVideoInfo().m_sContainerFormat; +} string VideoNode::getVideoCodec() const { @@ -286,6 +317,8 @@ void VideoNode::setEOFCallback(PyObject * pEOFCallback) if (pEOFCallback == Py_None) { m_pEOFCallback = 0; } else { + avgDeprecationWarning("1.8", "VideoNode.setEOFCallback()", + "Node.subscribe(END_OF_FILE)"); Py_INCREF(pEOFCallback); m_pEOFCallback = pEOFCallback; } @@ -308,19 +341,19 @@ void VideoNode::setHRef(const UTF8String& href) checkReload(); } -double VideoNode::getVolume() +float VideoNode::getVolume() { return m_Volume; } -void VideoNode::setVolume(double Volume) +void VideoNode::setVolume(float volume) { - if (Volume < 0) { - Volume = 0; + if (volume < 0) { + volume = 0; } - m_Volume = Volume; - if (m_VideoState != Unloaded && hasAudio()) { - m_pDecoder->setVolume(Volume); + m_Volume = volume; + if (m_AudioID != -1) { + AudioEngine::get()->setSourceVolume(m_AudioID, volume); } } @@ -345,62 +378,65 @@ void VideoNode::checkReload() void VideoNode::onFrameEnd() { + AsyncVideoDecoder* pAsyncDecoder = dynamic_cast<AsyncVideoDecoder*>(m_pDecoder); + if (pAsyncDecoder && (m_VideoState == Playing || m_VideoState == Paused)) { + pAsyncDecoder->updateAudioStatus(); + } if (m_bEOFPending) { // If the VideoNode is unlinked by python in onEOF, the following line prevents // the object from being deleted until we return from this function. - NodePtr pTempThis = shared_from_this(); + NodePtr pTempThis = getSharedThis(); m_bEOFPending = false; onEOF(); } } -int VideoNode::fillAudioBuffer(AudioBufferPtr pBuffer) -{ - AVG_ASSERT(m_bThreaded); - if (m_VideoState == Playing) { - return m_pDecoder->fillAudioBuffer(pBuffer); - } else { - return 0; - } -} - -void VideoNode::changeVideoState(VideoState NewVideoState) +void VideoNode::changeVideoState(VideoState newVideoState) { long long curTime = Player::get()->getFrameTime(); - if (m_VideoState == NewVideoState) { + if (m_VideoState == newVideoState) { return; } if (m_VideoState == Unloaded) { m_PauseStartTime = curTime; open(); } - if (NewVideoState == Unloaded) { + if (newVideoState == Unloaded) { close(); } if (getState() == NS_CANRENDER) { if (m_VideoState == Unloaded) { startDecoding(); } - if (NewVideoState == Paused) { + if (newVideoState == Paused) { m_PauseStartTime = curTime; - } else if (NewVideoState == Playing && m_VideoState == Paused) { + if (m_AudioID != -1) { + AudioEngine::get()->pauseSource(m_AudioID); + } + } else if (newVideoState == Playing && m_VideoState == Paused) { /* cerr << "Play after pause:" << endl; cerr << " getFrameTime()=" << curTime << endl; cerr << " m_PauseStartTime=" << m_PauseStartTime << endl; cerr << " offset=" << (1000.0/m_pDecoder->getFPS()) << endl; */ + if (m_AudioID != -1) { + AudioEngine::get()->playSource(m_AudioID); + } m_PauseTime += (curTime-m_PauseStartTime - (long long)(1000.0/m_pDecoder->getFPS())); } } - m_VideoState = NewVideoState; + m_VideoState = newVideoState; } void VideoNode::seek(long long destTime) { if (getState() == NS_CANRENDER) { - m_pDecoder->seek(double(destTime)/1000.0); + if (m_AudioID != -1) { + AudioEngine::get()->notifySeek(m_AudioID); + } + m_pDecoder->seek(float(destTime)/1000.0f); m_StartTime = Player::get()->getFrameTime() - destTime; m_JitterCompensation = 0.5; m_PauseTime = 0; @@ -419,8 +455,7 @@ void VideoNode::open() m_FramesTooLate = 0; m_FramesInRowTooLate = 0; m_FramesPlayed = 0; - m_pDecoder->open(m_Filename, m_bThreaded, m_bUsesHardwareAcceleration); - m_pDecoder->setVolume(m_Volume); + m_pDecoder->open(m_Filename, m_bUsesHardwareAcceleration, m_bEnableSound); VideoInfo videoInfo = m_pDecoder->getVideoInfo(); if (!videoInfo.m_bHasVideo) { m_pDecoder->close(); @@ -431,34 +466,38 @@ void VideoNode::open() m_JitterCompensation = 0.5; m_PauseTime = 0; + m_bSeekPending = false; m_bFirstFrameDecoded = false; m_bFrameAvailable = false; m_bUsesHardwareAcceleration = videoInfo.m_bUsesVDPAU; + setViewport(-32767, -32767, -32767, -32767); } void VideoNode::startDecoding() { const AudioParams * pAP = 0; - SDLAudioEngine* pAudioEngine = SDLAudioEngine::get(); + AudioEngine* pAudioEngine = AudioEngine::get(); if (pAudioEngine) { pAP = pAudioEngine->getParams(); } - m_pDecoder->startDecoding(GLContext::getCurrent()->isUsingShaders(), pAP); + m_pDecoder->startDecoding(GLContext::getMain()->useGPUYUVConversion(), pAP); VideoInfo videoInfo = m_pDecoder->getVideoInfo(); if (m_FPS != 0.0) { if (videoInfo.m_bHasAudio) { - AVG_TRACE(Logger::WARNING, - getID() + ": Can't set FPS if video contains audio. Ignored."); + AVG_LOG_WARNING(getID() + ": Can't set FPS if video contains audio. Ignored."); } else { m_pDecoder->setFPS(m_FPS); } } if (videoInfo.m_bHasAudio && pAudioEngine) { - pAudioEngine->addSource(this); + AsyncVideoDecoder* pAsyncDecoder = + dynamic_cast<AsyncVideoDecoder*>(m_pDecoder); + m_AudioID = pAudioEngine->addSource(*pAsyncDecoder->getAudioMsgQ(), + *pAsyncDecoder->getAudioStatusQ()); + pAudioEngine->setSourceVolume(m_AudioID, m_Volume); } m_bSeekPending = true; - setViewport(-32767, -32767, -32767, -32767); createTextures(videoInfo.m_Size); if (m_SeekBeforeCanRenderTime != 0) { @@ -474,8 +513,8 @@ void VideoNode::createTextures(IntPoint size) if (pixelFormatIsPlanar(pf)) { m_pTextures[0] = GLTexturePtr(new GLTexture(size, I8, bMipmap)); IntPoint halfSize(size.x/2, size.y/2); - m_pTextures[1] = GLTexturePtr(new GLTexture(halfSize, I8, bMipmap)); - m_pTextures[2] = GLTexturePtr(new GLTexture(halfSize, I8, bMipmap)); + m_pTextures[1] = GLTexturePtr(new GLTexture(halfSize, I8, bMipmap, 128)); + m_pTextures[2] = GLTexturePtr(new GLTexture(halfSize, I8, bMipmap, 128)); if (pixelFormatHasAlpha(pf)) { m_pTextures[3] = GLTexturePtr(new GLTexture(size, I8, bMipmap)); } @@ -501,13 +540,15 @@ void VideoNode::createTextures(IntPoint size) } else { getSurface()->create(pf, m_pTextures[0]); } + newSurface(); } void VideoNode::close() { - SDLAudioEngine* pAudioEngine = SDLAudioEngine::get(); - if (hasAudio() && pAudioEngine) { - pAudioEngine->removeSource(this); + AudioEngine* pAudioEngine = AudioEngine::get(); + if (m_AudioID != -1) { + pAudioEngine->removeSource(m_AudioID); + m_AudioID = -1; } m_pDecoder->close(); if (m_FramesTooLate > 0) { @@ -517,8 +558,9 @@ void VideoNode::close() } else { sID = getID(); } - AVG_TRACE(Logger::PROFILE_VIDEO, "Missed video frames for '" << sID << "': " - << m_FramesTooLate << " of " << m_FramesPlayed); + AVG_TRACE(Logger::category::PROFILE_VIDEO, Logger::severity::INFO, + "Missed video frames for '" << sID << "': " << m_FramesTooLate << + " of " << m_FramesPlayed); m_FramesTooLate = 0; } } @@ -537,7 +579,7 @@ IntPoint VideoNode::getMediaSize() } } -double VideoNode::getFPS() const +float VideoNode::getFPS() const { return m_pDecoder->getFPS(); } @@ -553,6 +595,7 @@ long long VideoNode::getNextFrameTime() const case Unloaded: return 0; case Paused: + AVG_ASSERT(m_PauseStartTime-m_StartTime >= 0); return m_PauseStartTime-m_StartTime; case Playing: { @@ -596,10 +639,11 @@ void VideoNode::exceptionIfUnloaded(const std::string& sFuncName) const static ProfilingZoneID PrerenderProfilingZone("VideoNode::prerender"); -void VideoNode::preRender() +void VideoNode::preRender(const VertexArrayPtr& pVA, bool bIsParentActive, + float parentEffectiveOpacity) { ScopeTimer timer(PrerenderProfilingZone); - Node::preRender(); + Node::preRender(pVA, bIsParentActive, parentEffectiveOpacity); if (isVisible()) { if (m_VideoState != Unloaded) { if (m_VideoState == Playing) { @@ -616,35 +660,36 @@ void VideoNode::preRender() } } } else { - if (m_bSeekPending && m_bFirstFrameDecoded && m_VideoState != Unloaded) { + if (m_VideoState != Unloaded && m_bSeekPending && m_bFirstFrameDecoded) { renderFrame(); } if (m_VideoState == Playing) { // Throw away frames that are not visible to make sure the video // stays in sync. - m_pDecoder->throwAwayFrame(getNextFrameTime()/1000.0); + m_pDecoder->throwAwayFrame(getNextFrameTime()/1000.0f); if (m_pDecoder->isEOF()) { updateStatusDueToDecoderEOF(); } } } + calcVertexArray(pVA); } static ProfilingZoneID RenderProfilingZone("VideoNode::render"); -void VideoNode::render(const DRect& rect) +void VideoNode::render() { ScopeTimer timer(RenderProfilingZone); if (m_VideoState != Unloaded && m_bFirstFrameDecoded) { - blt32(getSize(), getEffectiveOpacity(), getBlendMode()); + blt32(getTransform(), getSize(), getEffectiveOpacity(), getBlendMode()); } } VideoNode::VideoAccelType VideoNode::getVideoAccelConfig() { #ifdef AVG_ENABLE_VDPAU - if (VDPAU::isAvailable()) { + if (VDPAUDecoder::isAvailable()) { return VDPAU; } #endif @@ -653,12 +698,26 @@ VideoNode::VideoAccelType VideoNode::getVideoAccelConfig() bool VideoNode::renderFrame() { - FrameAvailableCode frameAvailable = renderToSurface(); + FrameAvailableCode frameAvailable = + m_pDecoder->renderToTexture(m_pTextures, getNextFrameTime()/1000.0f); + + // Even with vsync, frame duration has a bit of jitter. If the video frames rendered + // are at the border of a frame's time, this can cause irregular display times. + // So, if we detect this condition, we adjust the frame time by a small fraction + // to move it towards the center of the time slot. + long long jitter = (long long)(getNextFrameTime()-m_pDecoder->getCurTime()*1000); + if (jitter > (long long)(0.4*(1000/m_pDecoder->getFPS()))) { + m_JitterCompensation += 0.05; + if (m_JitterCompensation > 1) { + m_JitterCompensation -= 1; + } + } + if (m_pDecoder->isEOF()) { -// AVG_TRACE(Logger::PROFILE, "------------------ EOF -----------------"); updateStatusDueToDecoderEOF(); if (m_bLoop) { - frameAvailable = renderToSurface(); + frameAvailable = + m_pDecoder->renderToTexture(m_pTextures, getNextFrameTime()/1000.0f); } } @@ -666,17 +725,16 @@ bool VideoNode::renderFrame() case FA_NEW_FRAME: m_FramesPlayed++; m_FramesInRowTooLate = 0; - bind(); m_bSeekPending = false; setMaskCoords(); -// AVG_TRACE(Logger::PROFILE, "New frame."); +// AVG_TRACE(Logger::category::PROFILE, "New frame."); break; case FA_STILL_DECODING: { m_FramesPlayed++; m_FramesTooLate++; m_FramesInRowTooLate++; - double framerate = Player::get()->getEffectiveFramerate(); + float framerate = Player::get()->getEffectiveFramerate(); long long frameTime = Player::get()->getFrameTime(); if (m_VideoState == Playing) { if (m_FramesInRowTooLate > 3 && framerate != 0) { @@ -702,50 +760,18 @@ bool VideoNode::renderFrame() } } } -// AVG_TRACE(Logger::PROFILE, "Missed video frame."); +// AVG_TRACE(Logger::category::PROFILE, "Missed video frame."); break; case FA_USE_LAST_FRAME: m_FramesInRowTooLate = 0; m_bSeekPending = false; -// AVG_TRACE(Logger::PROFILE, "Video frame reused."); +// AVG_TRACE(Logger::category::PROFILE, "Video frame reused."); break; default: AVG_ASSERT(false); } return (frameAvailable == FA_NEW_FRAME); - return false; -} - -FrameAvailableCode VideoNode::renderToSurface() -{ - FrameAvailableCode frameAvailable; - PixelFormat pf = m_pDecoder->getPixelFormat(); - std::vector<BitmapPtr> pBmps; - for (unsigned i=0; i<getNumPixelFormatPlanes(pf); ++i) { - pBmps.push_back(m_pTextures[i]->lockStreamingBmp()); - } - if (pixelFormatIsPlanar(pf)) { - frameAvailable = m_pDecoder->renderToBmps(pBmps, getNextFrameTime()/1000.0); - } else { - frameAvailable = m_pDecoder->renderToBmp(pBmps[0], getNextFrameTime()/1000.0); - } - for (unsigned i=0; i<getNumPixelFormatPlanes(pf); ++i) { - m_pTextures[i]->unlockStreamingBmp(frameAvailable == FA_NEW_FRAME); - } - - // Even with vsync, frame duration has a bit of jitter. If the video frames rendered - // are at the border of a frame's time, this can cause irregular display times. - // So, if we detect this condition, we adjust the frame time by a small fraction - // to move it towards the center of the time slot. - long long jitter = (long long)(getNextFrameTime()-m_pDecoder->getCurTime()*1000); - if (jitter > (long long)(0.4*(1000/m_pDecoder->getFPS()))) { - m_JitterCompensation += 0.05; - if (m_JitterCompensation > 1) { - m_JitterCompensation -= 1; - } - } - return frameAvailable; } void VideoNode::onEOF() @@ -755,22 +781,26 @@ void VideoNode::onEOF() PyObject * result = PyEval_CallObject(m_pEOFCallback, arglist); Py_DECREF(arglist); if (!result) { - throw error_already_set(); + throw py::error_already_set(); } Py_DECREF(result); } + notifySubscribers("END_OF_FILE"); } - void VideoNode::updateStatusDueToDecoderEOF() { m_bEOFPending = true; if (m_bLoop) { m_StartTime = Player::get()->getFrameTime(); + m_PauseStartTime = Player::get()->getFrameTime(); m_JitterCompensation = 0.5; m_PauseTime = 0; m_FramesInRowTooLate = 0; m_bFrameAvailable = false; + if (m_AudioID != -1) { + AudioEngine::get()->notifySeek(m_AudioID); + } m_pDecoder->loop(); } else { changeVideoState(Paused); diff --git a/src/player/VideoNode.h b/src/player/VideoNode.h index e625e03..2ae2caf 100644 --- a/src/player/VideoNode.h +++ b/src/player/VideoNode.h @@ -1,6 +1,6 @@ // // libavg - Media Playback Engine. -// Copyright (C) 2003-2011 Ulrich von Zadow +// Copyright (C) 2003-2014 Ulrich von Zadow // // This library is free software; you can redistribute it and/or // modify it under the terms of the GNU Lesser General Public @@ -29,11 +29,10 @@ #include "Node.h" #include "RasterNode.h" -#include "../base/Point.h" +#include "../base/GLMHelper.h" #include "../base/IFrameEndListener.h" #include "../base/UTF8String.h" -#include "../audio/IAudioSource.h" #include "../video/VideoDecoder.h" namespace avg { @@ -42,12 +41,12 @@ class VideoDecoder; class TextureMover; typedef boost::shared_ptr<TextureMover> TextureMoverPtr; -class AVG_API VideoNode: public RasterNode, IFrameEndListener, IAudioSource +class AVG_API VideoNode: public RasterNode, IFrameEndListener { public: enum VideoAccelType {NONE, VDPAU}; - static NodeDefinition createDefinition(); + static void registerType(); VideoNode(const ArgList& args); virtual ~VideoNode(); @@ -62,9 +61,9 @@ class AVG_API VideoNode: public RasterNode, IFrameEndListener, IAudioSource const UTF8String& getHRef() const; void setHRef(const UTF8String& href); - double getVolume(); - void setVolume(double volume); - double getFPS() const; + float getVolume(); + void setVolume(float volume); + float getFPS() const; int getQueueLength() const; void checkReload(); @@ -74,7 +73,10 @@ class AVG_API VideoNode: public RasterNode, IFrameEndListener, IAudioSource void seekToFrame(int frameNum); std::string getStreamPixelFormat() const; long long getDuration() const; + long long getVideoDuration() const; + long long getAudioDuration() const; int getBitrate() const; + std::string getContainerFormat() const; std::string getVideoCodec() const; std::string getAudioCodec() const; int getAudioSampleRate() const; @@ -89,18 +91,17 @@ class AVG_API VideoNode: public RasterNode, IFrameEndListener, IAudioSource void setEOFCallback(PyObject * pEOFCallback); bool isAccelerated() const; - virtual void render(const DRect& rect); - virtual void preRender(); + virtual void preRender(const VertexArrayPtr& pVA, bool bIsParentActive, + float parentEffectiveOpacity); + virtual void render(); virtual void onFrameEnd(); - virtual int fillAudioBuffer(AudioBufferPtr pBuffer); virtual IntPoint getMediaSize(); static VideoAccelType getVideoAccelConfig(); private: bool renderFrame(); - FrameAvailableCode renderToSurface(); void seek(long long destTime); void onEOF(); void updateStatusDueToDecoderEOF(); @@ -126,7 +127,7 @@ class AVG_API VideoNode: public RasterNode, IFrameEndListener, IAudioSource std::string m_Filename; bool m_bLoop; bool m_bThreaded; - double m_FPS; + float m_FPS; int m_QueueLength; bool m_bEOFPending; PyObject * m_pEOFCallback; @@ -139,11 +140,13 @@ class AVG_API VideoNode: public RasterNode, IFrameEndListener, IAudioSource long long m_StartTime; long long m_PauseTime; long long m_PauseStartTime; - double m_JitterCompensation; + float m_JitterCompensation; VideoDecoder * m_pDecoder; - double m_Volume; + float m_Volume; bool m_bUsesHardwareAcceleration; + bool m_bEnableSound; + int m_AudioID; GLTexturePtr m_pTextures[4]; }; diff --git a/src/player/VideoWriter.cpp b/src/player/VideoWriter.cpp index c2c39e9..e91db38 100644 --- a/src/player/VideoWriter.cpp +++ b/src/player/VideoWriter.cpp @@ -1,6 +1,6 @@ // // libavg - Media Playback Engine. -// Copyright (C) 2003-2011 Ulrich von Zadow +// Copyright (C) 2003-2014 Ulrich von Zadow // // This library is free software; you can redistribute it and/or // modify it under the terms of the GNU Lesser General Public @@ -55,7 +55,12 @@ VideoWriter::VideoWriter(CanvasPtr pCanvas, const string& sOutFileName, int fram m_StartTime(-1), m_bFramePending(false) { - m_FrameSize = m_pCanvas->getSize(); + if (!pCanvas) { + throw Exception(AVG_ERR_INVALID_ARGS, "VideoWriter needs a canvas to write to."); + } + if (GLContext::getCurrent()->isGLES()) { + throw Exception(AVG_ERR_UNSUPPORTED, "VideoWriter not supported under GLES."); + } #ifdef WIN32 int fd = _open(m_sOutFileName.c_str(), O_RDWR | O_CREAT, _S_IREAD | _S_IWRITE); #elif defined linux @@ -75,10 +80,12 @@ VideoWriter::VideoWriter(CanvasPtr pCanvas, const string& sOutFileName, int fram #endif remove(m_sOutFileName.c_str()); CanvasPtr pMainCanvas = Player::get()->getMainCanvas(); - if (pMainCanvas != m_pCanvas) { + if (pMainCanvas == m_pCanvas) { + m_FrameSize = Player::get()->getDisplayEngine()->getWindowSize(); + } else { + m_FrameSize = m_pCanvas->getSize(); m_pFBO = dynamic_pointer_cast<OffscreenCanvas>(m_pCanvas)->getFBO(); - m_pCanvas->registerPreRenderListener(this); - if (GLContext::getCurrent()->isUsingShaders()) { + if (GLContext::getMain()->useGPUYUVConversion()) { m_pFilter = GPURGB2YUVFilterPtr(new GPURGB2YUVFilter(m_FrameSize)); } } @@ -92,8 +99,10 @@ VideoWriter::VideoWriter(CanvasPtr pCanvas, const string& sOutFileName, int fram VideoWriter::~VideoWriter() { stop(); - m_pThread->join(); - delete m_pThread; + if (m_pThread) { + m_pThread->join(); + delete m_pThread; + } } void VideoWriter::stop() @@ -109,9 +118,6 @@ void VideoWriter::stop() m_pCanvas->unregisterFrameEndListener(this); m_pCanvas->unregisterPlaybackEndListener(this); - if (m_pFBO) { - m_pCanvas->unregisterPreRenderListener(this); - } } } @@ -163,8 +169,12 @@ void VideoWriter::onFrameEnd() // For MainCanvas, it simply does a screenshot onFrameEnd and sends that to the // VideoWriterThread immediately. // For OffscreenCanvas, an asynchronous PBO readback is started in onFrameEnd. - // In the next frame's onPreRender, the data is read into a bitmap and sent to + // In the next frame's onFrameEnd, the data is read into a bitmap and sent to // the VideoWriterThread. + if (m_pFBO) { + // Read last frame's bitmap. + getFrameFromPBO(); + } if (m_StartTime == -1) { m_StartTime = Player::get()->getFrameTime(); } @@ -174,7 +184,7 @@ void VideoWriter::onFrameEnd() } else { long long movieTime = Player::get()->getFrameTime() - m_StartTime - m_PauseTime; - double timePerFrame = 1000./m_FrameRate; + float timePerFrame = 1000.f/m_FrameRate; int wantedFrame = int(movieTime/timePerFrame+0.1); if (wantedFrame > m_CurFrame) { getFrameFromFBO(); @@ -190,21 +200,13 @@ void VideoWriter::onFrameEnd() } } -void VideoWriter::onPreRender() -{ - getFrameFromPBO(); -} - void VideoWriter::getFrameFromFBO() { if (m_pFBO) { if (m_pFilter) { - glMatrixMode(GL_MODELVIEW); - glPushMatrix(); m_pFilter->apply(m_pFBO->getTex()); FBOPtr pYUVFBO = m_pFilter->getFBO(); pYUVFBO->moveToPBO(); - glPopMatrix(); } else { m_pFBO->moveToPBO(); } @@ -243,6 +245,9 @@ void VideoWriter::sendFrameToEncoder(BitmapPtr pBitmap) void VideoWriter::onPlaybackEnd() { stop(); + m_pThread->join(); + delete m_pThread; + m_pThread = 0; } void VideoWriter::writeDummyFrame() diff --git a/src/player/VideoWriter.h b/src/player/VideoWriter.h index c372991..ef3f724 100644 --- a/src/player/VideoWriter.h +++ b/src/player/VideoWriter.h @@ -1,6 +1,6 @@ // // libavg - Media Playback Engine. -// Copyright (C) 2003-2011 Ulrich von Zadow +// Copyright (C) 2003-2014 Ulrich von Zadow // // This library is free software; you can redistribute it and/or // modify it under the terms of the GNU Lesser General Public @@ -28,8 +28,7 @@ #include "../base/IFrameEndListener.h" #include "../base/IPlaybackEndListener.h" -#include "../base/IPreRenderListener.h" -#include "../base/Point.h" +#include "../base/GLMHelper.h" #include <boost/shared_ptr.hpp> #include <boost/thread.hpp> @@ -45,8 +44,7 @@ typedef boost::shared_ptr<FBO> FBOPtr; class GPURGB2YUVFilter; typedef boost::shared_ptr<GPURGB2YUVFilter> GPURGB2YUVFilterPtr; -class AVG_API VideoWriter : public IFrameEndListener, IPreRenderListener, - IPlaybackEndListener +class AVG_API VideoWriter : public IFrameEndListener, IPlaybackEndListener { public: VideoWriter(CanvasPtr pCanvas, const std::string& sOutFileName, @@ -62,7 +60,6 @@ class AVG_API VideoWriter : public IFrameEndListener, IPreRenderListener, int getQMax() const; virtual void onFrameEnd(); - virtual void onPreRender(); virtual void onPlaybackEnd(); private: diff --git a/src/player/VideoWriterThread.cpp b/src/player/VideoWriterThread.cpp index 3bb9a32..821df1b 100644 --- a/src/player/VideoWriterThread.cpp +++ b/src/player/VideoWriterThread.cpp @@ -1,7 +1,7 @@ // // libavg - Media Playback Engine. -// Copyright (C) 2003-2011 Ulrich von Zadow +// Copyright (C) 2003-2014 Ulrich von Zadow // // This library is free software; you can redistribute it and/or // modify it under the terms of the GNU Lesser General Public @@ -22,12 +22,12 @@ #include "VideoWriterThread.h" -#include "../base/ProfilingZone.h" +#include "../base/ProfilingZoneID.h" #include "../base/ScopeTimer.h" #include "../base/StringHelper.h" -#if LIBAVFORMAT_VERSION_MAJOR > 52 -#include <libavutil/mathematics.h> +#if LIBAVCODEC_VERSION_INT < AV_VERSION_INT(55, 18, 102) + typedef CodecID AVCodecID; #endif using namespace std; @@ -35,11 +35,11 @@ using namespace std; namespace avg { const unsigned int VIDEO_BUFFER_SIZE = 400000; -const ::PixelFormat STREAM_PIXEL_FORMAT = ::PIX_FMT_YUVJ420P; +const AVPixelFormat STREAM_PIXEL_FORMAT = ::PIX_FMT_YUVJ420P; -VideoWriterThread::VideoWriterThread(CQueue& CmdQueue, const string& sFilename, +VideoWriterThread::VideoWriterThread(CQueue& cmdQueue, const string& sFilename, IntPoint size, int frameRate, int qMin, int qMax) - : WorkerThread<VideoWriterThread>(sFilename, CmdQueue, Logger::PROFILE), + : WorkerThread<VideoWriterThread>(sFilename, cmdQueue, Logger::category::PROFILE), m_sFilename(sFilename), m_Size(size), m_FrameRate(frameRate), @@ -53,7 +53,7 @@ VideoWriterThread::~VideoWriterThread() { } -static ProfilingZoneID ProfilingZoneEncodeFrame("Encode frame"); +static ProfilingZoneID ProfilingZoneEncodeFrame("Encode frame", true); void VideoWriterThread::encodeYUVFrame(BitmapPtr pBmp) { @@ -86,7 +86,11 @@ void VideoWriterThread::close() } if (!(m_pOutputFormat->flags & AVFMT_NOFILE)) { +#if LIBAVCODEC_VERSION_INT > AV_VERSION_INT(53, 8, 0) + avio_close(m_pOutputFormatContext->pb); +#else url_fclose(m_pOutputFormatContext->pb); +#endif } av_free(m_pOutputFormatContext); @@ -120,9 +124,9 @@ void VideoWriterThread::open() av_register_all(); // TODO: make sure this is only done once. // av_log_set_level(AV_LOG_DEBUG); #if LIBAVFORMAT_VERSION_MAJOR > 52 - m_pOutputFormat = av_guess_format("mov", NULL, NULL); + m_pOutputFormat = av_guess_format(0, m_sFilename.c_str(), 0); #else - m_pOutputFormat = guess_format("mov", NULL, NULL); + m_pOutputFormat = guess_format(0, m_sFilename.c_str(), 0); #endif m_pOutputFormat->video_codec = CODEC_ID_MJPEG; @@ -143,9 +147,7 @@ void VideoWriterThread::open() av_set_parameters(m_pOutputFormatContext, NULL); #endif - double muxPreload = 0.5; - double muxMaxDelay = 0.7; - m_pOutputFormatContext->preload = int(muxPreload * AV_TIME_BASE); + float muxMaxDelay = 0.7; m_pOutputFormatContext->max_delay = int(muxMaxDelay * AV_TIME_BASE); // av_dump_format(m_pOutputFormatContext, 0, m_sFilename.c_str(), 1); @@ -158,8 +160,13 @@ void VideoWriterThread::open() } if (!(m_pOutputFormat->flags & AVFMT_NOFILE)) { +#if LIBAVCODEC_VERSION_INT > AV_VERSION_INT(53, 8, 0) + int retVal = avio_open(&m_pOutputFormatContext->pb, m_sFilename.c_str(), + URL_WRONLY); +#else int retVal = url_fopen(&m_pOutputFormatContext->pb, m_sFilename.c_str(), URL_WRONLY); +#endif if (retVal < 0) { throw Exception(AVG_ERR_VIDEO_INIT_FAILED, string("Could not open output file: '") + m_sFilename + "'"); @@ -181,10 +188,14 @@ void VideoWriterThread::open() void VideoWriterThread::setupVideoStream() { +#if LIBAVCODEC_VERSION_INT > AV_VERSION_INT(53, 21, 0) + m_pVideoStream = avformat_new_stream(m_pOutputFormatContext, 0); +#else m_pVideoStream = av_new_stream(m_pOutputFormatContext, 0); +#endif AVCodecContext* pCodecContext = m_pVideoStream->codec; - pCodecContext->codec_id = static_cast<CodecID>(m_pOutputFormat->video_codec); + pCodecContext->codec_id = static_cast<AVCodecID>(m_pOutputFormat->video_codec); pCodecContext->codec_type = AVMEDIA_TYPE_VIDEO; /* put sample parameters */ @@ -215,11 +226,16 @@ void VideoWriterThread::openVideoCodec() AVCodec* videoCodec = avcodec_find_encoder(m_pVideoStream->codec->codec_id); AVG_ASSERT(videoCodec); +#if LIBAVCODEC_VERSION_INT > AV_VERSION_INT(53, 8, 0) + int rc = avcodec_open2(m_pVideoStream->codec, videoCodec, 0); + +#else int rc = avcodec_open(m_pVideoStream->codec, videoCodec); +#endif AVG_ASSERT(rc == 0); } -AVFrame* VideoWriterThread::createFrame(::PixelFormat pixelFormat, IntPoint size) +AVFrame* VideoWriterThread::createFrame(AVPixelFormat pixelFormat, IntPoint size) { AVFrame* pPicture; @@ -233,7 +249,7 @@ AVFrame* VideoWriterThread::createFrame(::PixelFormat pixelFormat, IntPoint size return pPicture; } -static ProfilingZoneID ProfilingZoneConvertImage(" Convert image"); +static ProfilingZoneID ProfilingZoneConvertImage(" Convert image", true); void VideoWriterThread::convertRGBImage(BitmapPtr pSrcBmp) { @@ -284,7 +300,7 @@ void VideoWriterThread::convertYUVImage(BitmapPtr pSrcBmp) // pUBmp->save("foo"+toString(m_FramesWritten)+".png"); } -static ProfilingZoneID ProfilingZoneWriteFrame(" Write frame"); +static ProfilingZoneID ProfilingZoneWriteFrame(" Write frame", true); void VideoWriterThread::writeFrame(AVFrame* pFrame) { @@ -299,7 +315,7 @@ void VideoWriterThread::writeFrame(AVFrame* pFrame) AVPacket packet; av_init_packet(&packet); - if ((unsigned long long)(pCodecContext->coded_frame->pts) != AV_NOPTS_VALUE) { + if ((pCodecContext->coded_frame->pts) != (long long)AV_NOPTS_VALUE) { packet.pts = av_rescale_q(pCodecContext->coded_frame->pts, pCodecContext->time_base, m_pVideoStream->time_base); } diff --git a/src/player/VideoWriterThread.h b/src/player/VideoWriterThread.h index 6d61c6d..4cefa1e 100644 --- a/src/player/VideoWriterThread.h +++ b/src/player/VideoWriterThread.h @@ -1,6 +1,6 @@ // // libavg - Media Playback Engine. -// Copyright (C) 2003-2011 Ulrich von Zadow +// Copyright (C) 2003-2014 Ulrich von Zadow // // This library is free software; you can redistribute it and/or // modify it under the terms of the GNU Lesser General Public @@ -38,7 +38,7 @@ namespace avg { class AVG_API VideoWriterThread : public WorkerThread<VideoWriterThread> { public: - VideoWriterThread(CQueue& CmdQueue, const std::string& sFilename, IntPoint size, + VideoWriterThread(CQueue& cmdQueue, const std::string& sFilename, IntPoint size, int frameRate, int qMin, int qMax); virtual ~VideoWriterThread(); @@ -57,7 +57,7 @@ class AVG_API VideoWriterThread : public WorkerThread<VideoWriterThread> { void setupVideoStream(); void openVideoCodec(); - AVFrame* createFrame(::PixelFormat pixelFormat, IntPoint size); + AVFrame* createFrame(AVPixelFormat pixelFormat, IntPoint size); void convertRGBImage(BitmapPtr pSrcBmp); void convertYUVImage(BitmapPtr pSrcBmp); @@ -76,8 +76,6 @@ class AVG_API VideoWriterThread : public WorkerThread<VideoWriterThread> { AVFrame* m_pConvertedFrame; unsigned char* m_pPictureBuffer; unsigned char* m_pVideoBuffer; - int m_VideoBufferSize; - PixelFormat m_StreamPixelFormat; int m_FramesWritten; }; diff --git a/src/player/WordsNode.cpp b/src/player/WordsNode.cpp index be20edb..ba67720 100644 --- a/src/player/WordsNode.cpp +++ b/src/player/WordsNode.cpp @@ -1,6 +1,6 @@ // // libavg - Media Playback Engine. -// Copyright (C) 2003-2011 Ulrich von Zadow +// Copyright (C) 2003-2014 Ulrich von Zadow // // This library is free software; you can redistribute it and/or // modify it under the terms of the GNU Lesser General Public @@ -21,7 +21,7 @@ #include "WordsNode.h" #include "OGLSurface.h" -#include "NodeDefinition.h" +#include "TypeDefinition.h" #include "TextEngine.h" #include "../base/Logger.h" @@ -46,7 +46,7 @@ using namespace std; namespace avg { -NodeDefinition WordsNode::createDefinition() +void WordsNode::registerType() { static const string sDTDElements = "<!ELEMENT span (#PCDATA|span|b|big|i|s|sub|sup|small|tt|u)*>\n" @@ -84,42 +84,50 @@ NodeDefinition WordsNode::createDefinition() "small", "tt", "u", "br"}; vector<string> sChildren = vectorFromCArray(sizeof(sChildArray)/sizeof(*sChildArray), sChildArray); - return NodeDefinition("words", Node::buildNode<WordsNode>) - .extendDefinition(RasterNode::createDefinition()) + TypeDefinition def = TypeDefinition("words", "rasternode", + ExportedObject::buildObject<WordsNode>) .addChildren(sChildren) .addDTDElements(sDTDElements) - .addArg(Arg<string>("font", "arial", false, offsetof(WordsNode, m_sFontName))) - .addArg(Arg<string>("variant", "", false, offsetof(WordsNode, m_sFontVariant))) + .addArg(Arg<string>("font", "sans")) + .addArg(Arg<string>("variant", "")) .addArg(Arg<UTF8String>("text", "")) - .addArg(Arg<string>("color", "FFFFFF", false, offsetof(WordsNode, m_sColorName))) - .addArg(Arg<double>("fontsize", 15, false, offsetof(WordsNode, m_FontSize))) - .addArg(Arg<int>("indent", 0, false, offsetof(WordsNode, m_Indent))) - .addArg(Arg<double>("linespacing", -1, false, offsetof(WordsNode, m_LineSpacing))) + .addArg(Arg<string>("color", "FFFFFF")) + .addArg(Arg<float>("aagamma", 1.0f)) + .addArg(Arg<float>("fontsize", 15)) + .addArg(Arg<int>("indent", 0, false)) + .addArg(Arg<float>("linespacing", 0)) .addArg(Arg<string>("alignment", "left")) .addArg(Arg<string>("wrapmode", "word")) - .addArg(Arg<bool>("justify", false, false, offsetof(WordsNode, m_bJustify))) + .addArg(Arg<bool>("justify", false)) .addArg(Arg<bool>("rawtextmode", false, false, offsetof(WordsNode, m_bRawTextMode))) - .addArg(Arg<double>("letterspacing", 0, false, - offsetof(WordsNode, m_LetterSpacing))) - .addArg(Arg<bool>("hint", true, false, offsetof(WordsNode, m_bHint))) + .addArg(Arg<float>("letterspacing", 0)) + .addArg(Arg<bool>("hint", true)) + .addArg(Arg<FontStyle>("fontstyle", FontStyle())) ; + TypeRegistry::get()->registerType(def); } WordsNode::WordsNode(const ArgList& args) : m_LogicalSize(0,0), m_pFontDescription(0), m_pLayout(0), - m_RedrawState(FONT_CHANGED) + m_bRenderNeeded(true) { m_bParsedText = false; - args.setMembers(this); - setAlignment(args.getArgVal<string>("alignment")); - setWrapMode(args.getArgVal<string>("wrapmode")); + + m_FontStyle = args.getArgVal<FontStyle>("fontstyle"); + m_FontStyle.setDefaultedArgs(args); +#ifdef _WIN32 + if (m_FontStyle.getFont() == "sans") { + m_FontStyle.setFont("Arial"); + m_FontStyle.setFontVariant("Regular"); + } +#endif + updateFont(); setText(args.getArgVal<UTF8String>("text")); - m_Color = colorStringToColor(m_sColorName); - setViewport(-32767, -32767, -32767, -32767); + ObjectCounter::get()->incRef(&typeid(*this)); } @@ -146,7 +154,7 @@ void WordsNode::setTextFromNodeValue(const string& sText) void WordsNode::connectDisplay() { RasterNode::connectDisplay(); - setDirty(FONT_CHANGED); + getSurface()->setAlphaGamma(m_FontStyle.getAAGamma()); } void WordsNode::connect(CanvasPtr pCanvas) @@ -160,132 +168,126 @@ void WordsNode::disconnect(bool bKill) if (m_pFontDescription) { pango_font_description_free(m_pFontDescription); m_pFontDescription = 0; - setDirty(FONT_CHANGED); + updateFont(); } RasterNode::disconnect(bKill); } string WordsNode::getAlignment() const { - switch(m_Alignment) { - case PANGO_ALIGN_LEFT: - return "left"; - case PANGO_ALIGN_CENTER: - return "center"; - case PANGO_ALIGN_RIGHT: - return "right"; - default: - AVG_ASSERT(false); - return ""; - } + return m_FontStyle.getAlignment(); } void WordsNode::setAlignment(const string& sAlign) { - if (sAlign == "left") { - m_Alignment = PANGO_ALIGN_LEFT; - } else if (sAlign == "center") { - m_Alignment = PANGO_ALIGN_CENTER; - } else if (sAlign == "right") { - m_Alignment = PANGO_ALIGN_RIGHT; - } else { - throw(Exception(AVG_ERR_UNSUPPORTED, - "WordsNode alignment "+sAlign+" not supported.")); - } - - setDirty(LAYOUT_CHANGED); + m_FontStyle.setAlignment(sAlign); + updateLayout(); } bool WordsNode::getJustify() const { - return m_bJustify; + return m_FontStyle.getJustify(); } void WordsNode::setJustify(bool bJustify) { - m_bJustify = bJustify; - setDirty(LAYOUT_CHANGED); + m_FontStyle.setJustify(bJustify); + updateLayout(); } -double WordsNode::getLetterSpacing() const +float WordsNode::getLetterSpacing() const { - return m_LetterSpacing; + return m_FontStyle.getLetterSpacing(); } -void WordsNode::setLetterSpacing(double letterSpacing) +void WordsNode::setLetterSpacing(float letterSpacing) { - m_LetterSpacing = letterSpacing; - setDirty(LAYOUT_CHANGED); + m_FontStyle.setLetterSpacing(letterSpacing); + updateLayout(); } bool WordsNode::getHint() const { - return m_bHint; + return m_FontStyle.getHint(); } void WordsNode::setHint(bool bHint) { - setDirty(LAYOUT_CHANGED); - m_bHint = bHint; + m_FontStyle.setHint(bHint); + updateLayout(); } -double WordsNode::getWidth() const +float WordsNode::getWidth() const { - const_cast<WordsNode*>(this)->updateLayout(); return AreaNode::getWidth(); } -void WordsNode::setWidth(double width) +void WordsNode::setWidth(float width) { - setDirty(LAYOUT_CHANGED); AreaNode::setWidth(width); + updateLayout(); } -double WordsNode::getHeight() const +float WordsNode::getHeight() const { - const_cast<WordsNode*>(this)->updateLayout(); return AreaNode::getHeight(); } -void WordsNode::setHeight(double width) +void WordsNode::setHeight(float width) { - setDirty(LAYOUT_CHANGED); AreaNode::setHeight(width); + updateLayout(); } -DPoint WordsNode::getSize() const +glm::vec2 WordsNode::getSize() const { - const_cast<WordsNode*>(this)->updateLayout(); return AreaNode::getSize(); } -void WordsNode::setSize(const DPoint& pt) +void WordsNode::setSize(const glm::vec2& pt) { - setDirty(LAYOUT_CHANGED); AreaNode::setSize(pt); + updateLayout(); } -void WordsNode::getElementsByPos(const DPoint& pos, vector<NodeWeakPtr>& pElements) +glm::vec2 WordsNode::toLocal(const glm::vec2& globalPos) const { - updateLayout(); - DPoint relPos = pos-DPoint(m_AlignOffset, 0); - AreaNode::getElementsByPos(relPos, pElements); + glm::vec2 localPos = globalPos - getRelViewport().tl - glm::vec2(m_AlignOffset, 0); + return getRotatedPivot(localPos, -getAngle(), getPivot()); +} + +glm::vec2 WordsNode::toGlobal(const glm::vec2& localPos) const +{ + glm::vec2 alignPos = localPos + glm::vec2(m_AlignOffset, 0); + glm::vec2 globalPos = getRotatedPivot(alignPos, getAngle(), getPivot()); + return globalPos + getRelViewport().tl; +} + +const FontStyle& WordsNode::getFontStyle() const +{ + return m_FontStyle; +} + +void WordsNode::setFontStyle(const FontStyle& fontStyle) +{ + m_FontStyle = fontStyle; + updateFont(); } const std::string& WordsNode::getFont() const { - return m_sFontName; + return m_FontStyle.getFont(); } void WordsNode::setFont(const std::string& sName) { - m_sFontName = sName; - setDirty(FONT_CHANGED); + m_FontStyle.setFont(sName); + updateFont(); } const std::string& WordsNode::getFontVariant() const { - return m_sFontVariant; + return m_FontStyle.getFontVariant(); } void WordsNode::addFontDir(const std::string& sDir) @@ -296,8 +298,8 @@ void WordsNode::addFontDir(const std::string& sDir) void WordsNode::setFontVariant(const std::string& sVariant) { - m_sFontVariant = sVariant; - setDirty(FONT_CHANGED); + m_FontStyle.setFontVariant(sVariant); + updateFont(); } const UTF8String& WordsNode::getText() const @@ -317,59 +319,67 @@ void WordsNode::setText(const UTF8String& sText) m_sText = m_sRawText; if (m_bRawTextMode) { m_bParsedText = false; + updateLayout(); } else { setParsedText(sText); } - setDirty(LAYOUT_CHANGED); } } const std::string& WordsNode::getColor() const { - return m_sColorName; + return m_FontStyle.getColor(); } void WordsNode::setColor(const string& sColor) { - m_sColorName = sColor; - m_Color = colorStringToColor(m_sColorName); - setDirty(RENDER_NEEDED); + m_FontStyle.setColor(sColor); +} + +float WordsNode::getAAGamma() const +{ + return m_FontStyle.getAAGamma(); +} + +void WordsNode::setAAGamma(float gamma) +{ + m_FontStyle.setAAGamma(gamma); + if (getState() == Node::NS_CANRENDER) { + getSurface()->setAlphaGamma(gamma); + } } -double WordsNode::getFontSize() const +float WordsNode::getFontSize() const { - return m_FontSize; + return m_FontStyle.getFontSize(); } -void WordsNode::setFontSize(double size) +void WordsNode::setFontSize(float size) { - if (size <= 1) { - throw Exception(AVG_ERR_INVALID_ARGS, "Words node: Font size < 1 is illegal."); - } - m_FontSize = size; - setDirty(FONT_CHANGED); + m_FontStyle.setFontSize(size); + updateFont(); } int WordsNode::getIndent() const { - return m_Indent; + return m_FontStyle.getIndent(); } void WordsNode::setIndent(int indent) { - m_Indent = indent; - setDirty(LAYOUT_CHANGED); + m_FontStyle.setIndent(indent); + updateLayout(); } -double WordsNode::getLineSpacing() const +float WordsNode::getLineSpacing() const { - return m_LineSpacing; + return m_FontStyle.getLineSpacing(); } -void WordsNode::setLineSpacing(double lineSpacing) +void WordsNode::setLineSpacing(float lineSpacing) { - m_LineSpacing = lineSpacing; - setDirty(LAYOUT_CHANGED); + m_FontStyle.setLineSpacing(lineSpacing); + updateLayout(); } bool WordsNode::getRawTextMode() const @@ -387,33 +397,34 @@ void WordsNode::setRawTextMode(bool rawTextMode) setParsedText(m_sText); } m_bRawTextMode = rawTextMode; - setDirty(LAYOUT_CHANGED); + updateLayout(); } } -DPoint WordsNode::getGlyphPos(int i) +glm::vec2 WordsNode::getGlyphPos(int i) { PangoRectangle rect = getGlyphRect(i); - return DPoint(double(rect.x)/PANGO_SCALE, double(rect.y)/PANGO_SCALE); + return glm::vec2(float(rect.x)/PANGO_SCALE, float(rect.y)/PANGO_SCALE); } -DPoint WordsNode::getGlyphSize(int i) +glm::vec2 WordsNode::getGlyphSize(int i) { PangoRectangle rect = getGlyphRect(i); - return DPoint(double(rect.width)/PANGO_SCALE, double(rect.height)/PANGO_SCALE); + return glm::vec2(float(rect.width)/PANGO_SCALE, float(rect.height)/PANGO_SCALE); } int WordsNode::getNumLines() { - updateLayout(); - return pango_layout_get_line_count(m_pLayout); + if(m_sText.length() != 0) { + return pango_layout_get_line_count(m_pLayout); + } + return 0; } -PyObject* WordsNode::getCharIndexFromPos(DPoint p) +PyObject* WordsNode::getCharIndexFromPos(glm::vec2 p) { int index; int trailing; - updateLayout(); gboolean bXyToIndex = pango_layout_xy_to_index(m_pLayout, int(p.x*PANGO_SCALE), int(p.y*PANGO_SCALE), &index, &trailing); if (bXyToIndex) { @@ -426,52 +437,31 @@ PyObject* WordsNode::getCharIndexFromPos(DPoint p) std::string WordsNode::getTextAsDisplayed() { - updateLayout(); return pango_layout_get_text(m_pLayout); } -DPoint WordsNode::getLineExtents(int line) +glm::vec2 WordsNode::getLineExtents(int line) { - if(line < 0 || line >= getNumLines()) { + if (line < 0 || line >= getNumLines()) { throw Exception(AVG_ERR_OUT_OF_RANGE, "WordsNode.getLineExtents: line index " +toString(line)+" is out of range."); } - updateLayout(); PangoRectangle logical_rect; PangoRectangle ink_rect; PangoLayoutLine *layoutLine = pango_layout_get_line_readonly(m_pLayout, line); pango_layout_line_get_pixel_extents(layoutLine, &ink_rect, &logical_rect); - return DPoint(double(logical_rect.width), double(logical_rect.height)); + return glm::vec2(float(logical_rect.width), float(logical_rect.height)); } void WordsNode::setWrapMode(const string& sWrapMode) { - if (sWrapMode == "word") { - m_WrapMode = PANGO_WRAP_WORD; - } else if (sWrapMode == "char") { - m_WrapMode = PANGO_WRAP_CHAR; - } else if (sWrapMode == "wordchar") { - m_WrapMode = PANGO_WRAP_WORD_CHAR; - } else { - throw(Exception(AVG_ERR_UNSUPPORTED, - "WordsNode wrapping mode "+sWrapMode+" not supported.")); - } - setDirty(LAYOUT_CHANGED); + m_FontStyle.setWrapMode(sWrapMode); + updateLayout(); } string WordsNode::getWrapMode() const { - switch(m_WrapMode) { - case PANGO_WRAP_WORD: - return "word"; - case PANGO_WRAP_CHAR: - return "char"; - case PANGO_WRAP_WORD_CHAR: - return "wordchar"; - default: - AVG_ASSERT(false); - return ""; - } + return m_FontStyle.getWrapMode(); } void WordsNode::parseString(PangoAttrList** ppAttrList, char** ppText) @@ -497,31 +487,21 @@ void WordsNode::parseString(PangoAttrList** ppAttrList, char** ppText) void WordsNode::calcMaskCoords() { - updateLayout(); - // Calculate texture coordinates for the mask texture, normalized to // the extents of the text. - DPoint normMaskSize; - DPoint normMaskPos; - DPoint mediaSize = DPoint(getMediaSize()); - DPoint effMaskPos = getMaskPos()-DPoint(m_InkOffset); - DPoint maskSize = getMaskSize(); - switch (m_Alignment) { - case PANGO_ALIGN_LEFT: - break; - case PANGO_ALIGN_CENTER: - effMaskPos.x -= m_AlignOffset+getSize().x/2; - break; - case PANGO_ALIGN_RIGHT: - effMaskPos.x -= m_AlignOffset+getSize().x; - break; - } - if (maskSize == DPoint(0,0)) { - normMaskSize = DPoint(getSize().x/mediaSize.x, getSize().y/mediaSize.y); - normMaskPos = DPoint(effMaskPos.x/getSize().x, effMaskPos.y/getSize().y); + glm::vec2 normMaskSize; + glm::vec2 normMaskPos; + glm::vec2 mediaSize = glm::vec2(getMediaSize()); + glm::vec2 effMaskPos = getMaskPos()-glm::vec2(m_InkOffset); + glm::vec2 maskSize = getMaskSize(); + + if (maskSize == glm::vec2(0,0)) { + normMaskSize = glm::vec2(getSize().x/mediaSize.x, getSize().y/mediaSize.y); + normMaskPos = glm::vec2(effMaskPos.x/getSize().x, effMaskPos.y/getSize().y); } else { - normMaskSize = DPoint(maskSize.x/mediaSize.x, maskSize.y/mediaSize.y); - normMaskPos = DPoint(effMaskPos.x/getMaskSize().x, effMaskPos.y/getMaskSize().y); + normMaskSize = glm::vec2(maskSize.x/mediaSize.x, maskSize.y/mediaSize.y); + normMaskPos = glm::vec2(effMaskPos.x/getMaskSize().x, + effMaskPos.y/getMaskSize().y); } /* cerr << "calcMaskCoords" << endl; @@ -535,126 +515,114 @@ void WordsNode::calcMaskCoords() getSurface()->setMaskCoords(normMaskPos, normMaskSize); } -void WordsNode::setDirty(RedrawState newState) -{ - if (newState < m_RedrawState) { - m_RedrawState = newState; - } -} - static ProfilingZoneID UpdateFontProfilingZone("WordsNode: Update font"); void WordsNode::updateFont() { - if (m_RedrawState == FONT_CHANGED) { + { ScopeTimer timer(UpdateFontProfilingZone); if (m_pFontDescription) { pango_font_description_free(m_pFontDescription); } - m_pFontDescription = TextEngine::get(m_bHint).getFontDescription(m_sFontName, - m_sFontVariant); + TextEngine& engine = TextEngine::get(m_FontStyle.getHint()); + m_pFontDescription = engine.getFontDescription(m_FontStyle.getFont(), + m_FontStyle.getFontVariant()); pango_font_description_set_absolute_size(m_pFontDescription, - (int)(m_FontSize * PANGO_SCALE)); - - m_RedrawState = LAYOUT_CHANGED; + (int)(m_FontStyle.getFontSize() * PANGO_SCALE)); } + updateLayout(); } static ProfilingZoneID UpdateLayoutProfilingZone("WordsNode: Update layout"); void WordsNode::updateLayout() { - updateFont(); - if (m_RedrawState == LAYOUT_CHANGED) { - ScopeTimer timer(UpdateLayoutProfilingZone); + ScopeTimer timer(UpdateLayoutProfilingZone); - if (m_sText.length() == 0) { - m_LogicalSize = IntPoint(0,0); - m_RedrawState = RENDER_NEEDED; - } else { - PangoContext* pContext = TextEngine::get(m_bHint).getPangoContext(); - pango_context_set_font_description(pContext, m_pFontDescription); + if (m_sText.length() == 0) { + m_LogicalSize = IntPoint(0,0); + m_bRenderNeeded = true; + } else { + TextEngine& engine = TextEngine::get(m_FontStyle.getHint()); + PangoContext* pContext = engine.getPangoContext(); + pango_context_set_font_description(pContext, m_pFontDescription); - if (m_pLayout) { - g_object_unref(m_pLayout); - } - m_pLayout = pango_layout_new(pContext); + if (m_pLayout) { + g_object_unref(m_pLayout); + } + m_pLayout = pango_layout_new(pContext); - PangoAttrList * pAttrList = 0; + PangoAttrList * pAttrList = 0; #if PANGO_VERSION > PANGO_VERSION_ENCODE(1,18,2) - PangoAttribute * pLetterSpacing = pango_attr_letter_spacing_new - (int(m_LetterSpacing*1024)); + PangoAttribute * pLetterSpacing = pango_attr_letter_spacing_new + (int(m_FontStyle.getLetterSpacing()*1024)); #endif - if (m_bParsedText) { - char * pText = 0; - parseString(&pAttrList, &pText); + if (m_bParsedText) { + char * pText = 0; + parseString(&pAttrList, &pText); #if PANGO_VERSION > PANGO_VERSION_ENCODE(1,18,2) - // Workaround for pango bug. - pango_attr_list_insert_before(pAttrList, pLetterSpacing); + // Workaround for pango bug. + pango_attr_list_insert_before(pAttrList, pLetterSpacing); #endif - pango_layout_set_text(m_pLayout, pText, -1); - g_free (pText); - } else { - pAttrList = pango_attr_list_new(); + pango_layout_set_text(m_pLayout, pText, -1); + g_free(pText); + } else { + pAttrList = pango_attr_list_new(); #if PANGO_VERSION > PANGO_VERSION_ENCODE(1,18,2) - pango_attr_list_insert_before(pAttrList, pLetterSpacing); + pango_attr_list_insert_before(pAttrList, pLetterSpacing); #endif - pango_layout_set_text(m_pLayout, m_sText.c_str(), -1); - } - pango_layout_set_attributes(m_pLayout, pAttrList); - pango_attr_list_unref(pAttrList); - - pango_layout_set_wrap(m_pLayout, m_WrapMode); - pango_layout_set_alignment(m_pLayout, m_Alignment); - pango_layout_set_justify(m_pLayout, m_bJustify); - if (getUserSize().x != 0) { - pango_layout_set_width(m_pLayout, int(getUserSize().x * PANGO_SCALE)); - } - pango_layout_set_indent(m_pLayout, m_Indent * PANGO_SCALE); - if (m_Indent < 0) { - // For hanging indentation, we add a tabstop to support lists - PangoTabArray* pTabs = pango_tab_array_new_with_positions(1, false, - PANGO_TAB_LEFT, -m_Indent * PANGO_SCALE); - pango_layout_set_tabs(m_pLayout, pTabs); - pango_tab_array_free(pTabs); - } - if (m_LineSpacing != -1) { - pango_layout_set_spacing(m_pLayout, (int)(m_LineSpacing*PANGO_SCALE)); - } - PangoRectangle logical_rect; - PangoRectangle ink_rect; - pango_layout_get_pixel_extents(m_pLayout, &ink_rect, &logical_rect); - - /* - cerr << getID() << endl; - cerr << "Ink: " << ink_rect.x << ", " << ink_rect.y << ", " - << ink_rect.width << ", " << ink_rect.height << endl; - cerr << "Logical: " << logical_rect.x << ", " << logical_rect.y << ", " - << logical_rect.width << ", " << logical_rect.height << endl; - cerr << "User Size: " << getUserSize() << endl; - */ - m_InkSize.y = ink_rect.height; - if (getUserSize().x == 0) { - m_InkSize.x = ink_rect.width; - } else { - m_InkSize.x = int(getUserSize().x); - } - if (m_InkSize.x == 0) { - m_InkSize.x = 1; - } - if (m_InkSize.y == 0) { - m_InkSize.y = 1; - } - m_LogicalSize.y = logical_rect.height; - m_LogicalSize.x = logical_rect.width; - m_InkOffset = IntPoint(ink_rect.x-logical_rect.x, ink_rect.y-logical_rect.y); - if (m_LineSpacing == -1) { - m_LineSpacing = pango_layout_get_spacing(m_pLayout)/PANGO_SCALE; - } - m_RedrawState = RENDER_NEEDED; - setViewport(-32767, -32767, -32767, -32767); + pango_layout_set_text(m_pLayout, m_sText.c_str(), -1); + } + pango_layout_set_attributes(m_pLayout, pAttrList); + pango_attr_list_unref(pAttrList); + + pango_layout_set_wrap(m_pLayout, m_FontStyle.getWrapModeVal()); + pango_layout_set_alignment(m_pLayout, m_FontStyle.getAlignmentVal()); + pango_layout_set_justify(m_pLayout, m_FontStyle.getJustify()); + if (getUserSize().x != 0) { + pango_layout_set_width(m_pLayout, int(getUserSize().x * PANGO_SCALE)); + } + int indent = m_FontStyle.getIndent() * PANGO_SCALE; + pango_layout_set_indent(m_pLayout, indent); + if (indent < 0) { + // For hanging indentation, we add a tabstop to support lists + PangoTabArray* pTabs = pango_tab_array_new_with_positions(1, false, + PANGO_TAB_LEFT, -indent); + pango_layout_set_tabs(m_pLayout, pTabs); + pango_tab_array_free(pTabs); + } + pango_layout_set_spacing(m_pLayout, + (int)(m_FontStyle.getLineSpacing()*PANGO_SCALE)); + PangoRectangle logical_rect; + PangoRectangle ink_rect; + pango_layout_get_pixel_extents(m_pLayout, &ink_rect, &logical_rect); + + /* + cerr << getID() << endl; + cerr << "Ink: " << ink_rect.x << ", " << ink_rect.y << ", " + << ink_rect.width << ", " << ink_rect.height << endl; + cerr << "Logical: " << logical_rect.x << ", " << logical_rect.y << ", " + << logical_rect.width << ", " << logical_rect.height << endl; + cerr << "User Size: " << getUserSize() << endl; + */ + m_InkSize.y = ink_rect.height; + if (getUserSize().x == 0) { + m_InkSize.x = ink_rect.width; + } else { + m_InkSize.x = int(getUserSize().x); + } + if (m_InkSize.x == 0) { + m_InkSize.x = 1; + } + if (m_InkSize.y == 0) { + m_InkSize.y = 1; } + m_LogicalSize.y = logical_rect.height; + m_LogicalSize.x = logical_rect.width; + m_InkOffset = IntPoint(ink_rect.x-logical_rect.x, ink_rect.y-logical_rect.y); + m_bRenderNeeded = true; + setViewport(-32767, -32767, -32767, -32767); } } @@ -662,15 +630,16 @@ static ProfilingZoneID RenderTextProfilingZone("WordsNode: render text"); void WordsNode::renderText() { - AVG_ASSERT(m_RedrawState == RENDER_NEEDED || m_RedrawState == CLEAN); - if (!(getState() == NS_CANRENDER)) { return; } - if (m_RedrawState == RENDER_NEEDED) { + if (m_bRenderNeeded) { if (m_sText.length() != 0) { ScopeTimer timer(RenderTextProfilingZone); - int maxTexSize = GLContext::getCurrent()->getMaxTexSize(); + TextEngine& engine = TextEngine::get(m_FontStyle.getHint()); + PangoContext* pContext = engine.getPangoContext(); + pango_context_set_font_description(pContext, m_pFontDescription); + int maxTexSize = GLContext::getMain()->getMaxTexSize(); if (m_InkSize.x > maxTexSize || m_InkSize.y > maxTexSize) { throw Exception(AVG_ERR_UNSUPPORTED, "WordsNode size exceeded maximum (Size=" @@ -695,7 +664,7 @@ void WordsNode::renderText() PangoRectangle ink_rect; pango_layout_get_pixel_extents(m_pLayout, &ink_rect, &logical_rect); pango_ft2_render_layout(&bitmap, m_pLayout, -ink_rect.x, -ink_rect.y); - switch (m_Alignment) { + switch (m_FontStyle.getAlignmentVal()) { case PANGO_ALIGN_LEFT: m_AlignOffset = 0; break; @@ -711,10 +680,9 @@ void WordsNode::renderText() pMover->unlock(); pMover->moveToTexture(*pTex); - - bind(); + newSurface(); } - m_RedrawState = CLEAN; + m_bRenderNeeded = false; } } @@ -722,45 +690,43 @@ void WordsNode::redraw() { AVG_ASSERT(m_sText.length() < 32767); - updateLayout(); renderText(); } -void WordsNode::preRender() +void WordsNode::preRender(const VertexArrayPtr& pVA, bool bIsParentActive, + float parentEffectiveOpacity) { - Node::preRender(); + Node::preRender(pVA, bIsParentActive, parentEffectiveOpacity); if (isVisible()) { redraw(); - } else { - updateLayout(); } + Pixel32 color = m_FontStyle.getColorVal(); if (m_sText.length() != 0 && isVisible()) { - renderFX(getSize(), m_Color, false); + renderFX(getSize(), color, false); } + calcVertexArray(pVA, color); } static ProfilingZoneID RenderProfilingZone("WordsNode::render"); -void WordsNode::render(const DRect& rect) +void WordsNode::render() { ScopeTimer timer(RenderProfilingZone); if (m_sText.length() != 0 && isVisible()) { IntPoint offset = m_InkOffset + IntPoint(m_AlignOffset, 0); - GLContext* pContext = GLContext::getCurrent(); - if (offset != IntPoint(0,0)) { - pContext->pushTransform(DPoint(offset), 0, DPoint(0,0)); - } - blta8(DPoint(getSurface()->getSize()), getEffectiveOpacity(), m_Color, - getBlendMode()); - if (offset != IntPoint(0,0)) { - pContext->popTransform(); + glm::mat4 transform; + if (offset == IntPoint(0,0)) { + transform = getTransform(); + } else { + transform = glm::translate(getTransform(), glm::vec3(offset.x, offset.y, 0)); } + blta8(transform, glm::vec2(getSurface()->getSize()), getEffectiveOpacity(), + m_FontStyle.getColorVal(), getBlendMode()); } } IntPoint WordsNode::getMediaSize() { - updateLayout(); return m_LogicalSize; } @@ -798,7 +764,6 @@ PangoRectangle WordsNode::getGlyphRect(int i) throw(Exception(AVG_ERR_INVALID_ARGS, string("getGlyphRect: Index ") + toString(i) + " out of range.")); } - updateLayout(); const char* pText = pango_layout_get_text(m_pLayout); char * pChar = g_utf8_offset_to_pointer(pText, i); int byteOffset = pChar-pText; @@ -818,16 +783,16 @@ PangoRectangle WordsNode::getGlyphRect(int i) void WordsNode::setParsedText(const UTF8String& sText) { m_sText = removeExcessSpaces(sText); - setDirty(LAYOUT_CHANGED); // This just does a syntax check and throws an exception if appropriate. // The results are discarded. PangoAttrList * pAttrList = 0; char * pText = 0; parseString(&pAttrList, &pText); - pango_attr_list_unref (pAttrList); - g_free (pText); + pango_attr_list_unref(pAttrList); + g_free(pText); m_bParsedText = true; + updateLayout(); } UTF8String WordsNode::applyBR(const UTF8String& sText) diff --git a/src/player/WordsNode.h b/src/player/WordsNode.h index 23c225c..c189e9f 100644 --- a/src/player/WordsNode.h +++ b/src/player/WordsNode.h @@ -1,6 +1,6 @@ // // libavg - Media Playback Engine. -// Copyright (C) 2003-2011 Ulrich von Zadow +// Copyright (C) 2003-2014 Ulrich von Zadow // // This library is free software; you can redistribute it and/or // modify it under the terms of the GNU Lesser General Public @@ -24,6 +24,7 @@ #include "../api.h" #include "RasterNode.h" +#include "FontStyle.h" #include "../graphics/Pixel32.h" #include "../base/UTF8String.h" @@ -37,7 +38,7 @@ namespace avg { class AVG_API WordsNode : public RasterNode { public: - static NodeDefinition createDefinition(); + static void registerType(); WordsNode(const ArgList& args); virtual ~WordsNode(); @@ -45,21 +46,27 @@ class AVG_API WordsNode : public RasterNode virtual void connectDisplay(); virtual void connect(CanvasPtr pCanvas); virtual void disconnect(bool bKill); - virtual void preRender(); - virtual void render(const DRect& rect); + virtual void preRender(const VertexArrayPtr& pVA, bool bIsParentActive, + float parentEffectiveOpacity); + virtual void render(); - virtual double getWidth() const; - virtual void setWidth(double width); + virtual float getWidth() const; + virtual void setWidth(float width); - virtual double getHeight() const; - virtual void setHeight(double width); + virtual float getHeight() const; + virtual void setHeight(float width); - virtual DPoint getSize() const; - virtual void setSize(const DPoint& pt); + virtual glm::vec2 getSize() const; + virtual void setSize(const glm::vec2& pt); + + glm::vec2 toLocal(const glm::vec2& globalPos) const; + glm::vec2 toGlobal(const glm::vec2& localPos) const; - void getElementsByPos(const DPoint& pos, std::vector<NodeWeakPtr>& pElements); void setTextFromNodeValue(const std::string& sText); + const FontStyle& getFontStyle() const; + void setFontStyle(const FontStyle& fontStyle); + const std::string& getFont() const; void setFont(const std::string& sName); @@ -72,14 +79,17 @@ class AVG_API WordsNode : public RasterNode const std::string& getColor() const; void setColor(const std::string& sColor); - double getFontSize() const; - void setFontSize(double size); + virtual float getAAGamma() const; + virtual void setAAGamma(float gamma); + + float getFontSize() const; + void setFontSize(float size); int getIndent() const; void setIndent(int indent); - double getLineSpacing() const; - void setLineSpacing(double lineSpacing); + float getLineSpacing() const; + void setLineSpacing(float lineSpacing); bool getRawTextMode() const; void setRawTextMode(bool rawTextMode); @@ -93,20 +103,20 @@ class AVG_API WordsNode : public RasterNode bool getJustify() const; void setJustify(bool bJustify); - double getLetterSpacing() const; - void setLetterSpacing(double letterSpacing); + float getLetterSpacing() const; + void setLetterSpacing(float letterSpacing); bool getHint() const; void setHint(bool bHint); - DPoint getGlyphPos(int i); - DPoint getGlyphSize(int i); + glm::vec2 getGlyphPos(int i); + glm::vec2 getGlyphSize(int i); virtual IntPoint getMediaSize(); int getNumLines(); - PyObject* getCharIndexFromPos(DPoint p); + PyObject* getCharIndexFromPos(glm::vec2 p); std::string getTextAsDisplayed(); - DPoint getLineExtents(int line); + glm::vec2 getLineExtents(int line); static const std::vector<std::string>& getFontFamilies(); static const std::vector<std::string>& getFontVariants( @@ -114,10 +124,7 @@ class AVG_API WordsNode : public RasterNode static void addFontDir(const std::string& sDir); private: - enum RedrawState {FONT_CHANGED, LAYOUT_CHANGED, RENDER_NEEDED, CLEAN}; - virtual void calcMaskCoords(); - void setDirty(RedrawState newState); void updateFont(); void updateLayout(); void renderText(); @@ -129,21 +136,10 @@ class AVG_API WordsNode : public RasterNode PangoRectangle getGlyphRect(int i); // Exposed Attributes - std::string m_sFontName; - std::string m_sFontVariant; + FontStyle m_FontStyle; UTF8String m_sText; UTF8String m_sRawText; - std::string m_sColorName; - Pixel32 m_Color; - double m_FontSize; - int m_Indent; - double m_LineSpacing; - PangoAlignment m_Alignment; - PangoWrapMode m_WrapMode; - bool m_bJustify; - double m_LetterSpacing; - bool m_bHint; - + bool m_bParsedText; bool m_bRawTextMode; IntPoint m_LogicalSize; @@ -153,7 +149,7 @@ class AVG_API WordsNode : public RasterNode PangoFontDescription * m_pFontDescription; PangoLayout * m_pLayout; - RedrawState m_RedrawState; + bool m_bRenderNeeded; }; } diff --git a/src/player/WrapPython.cpp b/src/player/WrapPython.cpp new file mode 100644 index 0000000..e0eb9bc --- /dev/null +++ b/src/player/WrapPython.cpp @@ -0,0 +1,72 @@ +// +// libavg - Media Playback Engine. +// Copyright (C) 2003-2014 Ulrich von Zadow +// +// This library is free software; you can redistribute it and/or +// modify it under the terms of the GNU Lesser General Public +// License as published by the Free Software Foundation; either +// version 2 of the License, or (at your option) any later version. +// +// This library 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 +// Lesser General Public License for more details. +// +// You should have received a copy of the GNU Lesser General Public +// License along with this library; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +// +// Current versions can be found at www.libavg.de +// + +#include "WrapPython.h" + +#include "../base/Logger.h" +#include "../base/StringHelper.h" +#include "../base/FileHelper.h" + +#include <frameobject.h> + +using namespace std; + +namespace avg { + +aquirePyGIL::aquirePyGIL() +{ + m_pyGilState = PyGILState_Ensure(); +} +aquirePyGIL::~aquirePyGIL() +{ + PyGILState_Release(m_pyGilState); +} + +void avgDeprecationWarning(const string& sVersion, const string& sOldEntryPoint, + const string& sNewEntryPoint) +{ + static vector<string> sWarningsIssued; + bool bWarned = false; + for (vector<string>::iterator it = sWarningsIssued.begin(); + it != sWarningsIssued.end(); ++it) + { + if (*it == sOldEntryPoint) { + return; + } + } + if (!bWarned) { + sWarningsIssued.push_back(sOldEntryPoint); + + PyFrameObject* pFrame = PyEval_GetFrame(); + int lineNo = PyCode_Addr2Line(pFrame->f_code, pFrame->f_lasti); + // lineNo = PyFrame_GetLineNumber(pFrame); + string sFName = getFilenamePart(PyString_AS_STRING(pFrame->f_code->co_filename)); + string sMsg = sFName + ":" + toString(lineNo) + ": "; + sMsg += string(sOldEntryPoint) + " deprecated since version " + + string(sVersion)+"."; + if (sNewEntryPoint != string("")) { + sMsg += " Use "+string(sNewEntryPoint) + " instead."; + } + AVG_TRACE(Logger::category::DEPRECATION, Logger::severity::WARNING, sMsg); + } +} + +} diff --git a/src/player/WrapPython.h b/src/player/WrapPython.h index b81b4eb..20ce764 100644 --- a/src/player/WrapPython.h +++ b/src/player/WrapPython.h @@ -1,6 +1,6 @@ // // libavg - Media Playback Engine. -// Copyright (C) 2003-2011 Ulrich von Zadow +// Copyright (C) 2003-2014 Ulrich von Zadow // // This library is free software; you can redistribute it and/or // modify it under the terms of the GNU Lesser General Public @@ -19,6 +19,9 @@ // Current versions can be found at www.libavg.de // +#ifndef _WrapPython_H_ +#define _WrapPython_H_ + #include "../api.h" #ifdef _DEBUG @@ -47,3 +50,21 @@ # define _DEBUG #endif +namespace avg { + +class aquirePyGIL +{ +public: + aquirePyGIL(); + virtual ~aquirePyGIL(); + +private: + PyGILState_STATE m_pyGilState; +}; + +void avgDeprecationWarning(const std::string& sVersion, const std::string& sOldEntryPoint, + const std::string& sNewEntryPoint); + +} + +#endif diff --git a/src/player/XInputMTInputDevice.cpp b/src/player/XInputMTInputDevice.cpp index 0e042c2..14145c8 100644 --- a/src/player/XInputMTInputDevice.cpp +++ b/src/player/XInputMTInputDevice.cpp @@ -1,6 +1,6 @@ // // libavg - Media Playback Engine. -// Copyright (C) 2003-2011 Ulrich von Zadow +// Copyright (C) 2003-2014 Ulrich von Zadow // // This library is free software; you can redistribute it and/or // modify it under the terms of the GNU Lesser General Public @@ -43,7 +43,7 @@ using namespace std; namespace avg { -Display* XInputMTInputDevice::s_pDisplay = 0; +::Display* XInputMTInputDevice::s_pDisplay = 0; const char* cookieTypeToName(int evtype); string xEventTypeToName(int evtype); @@ -69,6 +69,10 @@ void XInputMTInputDevice::start() { Status status; SDLDisplayEngine * pEngine = Player::get()->getDisplayEngine(); + glm::vec2 size(pEngine->getSize()); + glm::vec2 windowSize(pEngine->getWindowSize()); + m_DisplayScale.x = size.x/windowSize.x; + m_DisplayScale.y = size.y/windowSize.y; SDL_SysWMinfo info; SDL_VERSION(&info.version); @@ -132,7 +136,8 @@ void XInputMTInputDevice::start() pEngine->setXIMTInputDevice(this); MultitouchInputDevice::start(); - AVG_TRACE(Logger::CONFIG, "XInput Multitouch event source created."); + AVG_TRACE(Logger::category::CONFIG, Logger::severity::INFO, + "XInput Multitouch event source created."); } void XInputMTInputDevice::handleXIEvent(const XEvent& xEvent) @@ -148,14 +153,14 @@ void XInputMTInputDevice::handleXIEvent(const XEvent& xEvent) { // cerr << "TouchBegin " << xid << ", " << pos << endl; m_LastID++; - TouchEventPtr pEvent = createEvent(m_LastID, Event::CURSORDOWN, pos); + TouchEventPtr pEvent = createEvent(m_LastID, Event::CURSOR_DOWN, pos); addTouchStatus(xid, pEvent); } break; case XI_TouchUpdate: { // cerr << "TouchUpdate " << xid << ", " << pos << endl; - TouchEventPtr pEvent = createEvent(0, Event::CURSORMOTION, pos); + TouchEventPtr pEvent = createEvent(0, Event::CURSOR_MOTION, pos); TouchStatusPtr pTouchStatus = getTouchStatus(xid); AVG_ASSERT(pTouchStatus); pTouchStatus->pushEvent(pEvent); @@ -166,7 +171,7 @@ void XInputMTInputDevice::handleXIEvent(const XEvent& xEvent) // cerr << "TouchEnd " << xid << ", " << pos << endl; TouchStatusPtr pTouchStatus = getTouchStatus(xid); AVG_ASSERT(pTouchStatus); - TouchEventPtr pEvent = createEvent(0, Event::CURSORUP, pos); + TouchEventPtr pEvent = createEvent(0, Event::CURSOR_UP, pos); pTouchStatus->pushEvent(pEvent); } break; @@ -198,7 +203,6 @@ void XInputMTInputDevice::findMTDevice() pDevices = XIQueryDevice(s_pDisplay, XIAllDevices, &ndevices); XITouchClassInfo* pTouchClass = 0; - int maxTouches; for (int i = 0; i < ndevices && !pTouchClass; ++i) { pDevice = &pDevices[i]; // cerr << "Device " << pDevice->name << "(id: " << pDevice->deviceid << ")." @@ -217,7 +221,6 @@ void XInputMTInputDevice::findMTDevice() } else { m_OldMasterDeviceID = -1; } - maxTouches = pTouchClass->num_touches; break; } } @@ -225,8 +228,9 @@ void XInputMTInputDevice::findMTDevice() } } if (pTouchClass) { - AVG_TRACE(Logger::CONFIG, "Using multitouch input device " << m_sDeviceName - << ", max touches: " << maxTouches); + AVG_TRACE(Logger::category::CONFIG,Logger::severity::INFO, + "Using multitouch input device " << m_sDeviceName << ", max touches: " << + pTouchClass->num_touches); } else { throw Exception(AVG_ERR_MT_INIT, "XInput multitouch event source: No multitouch device found."); @@ -236,6 +240,8 @@ void XInputMTInputDevice::findMTDevice() TouchEventPtr XInputMTInputDevice::createEvent(int id, Event::Type type, IntPoint pos) { + pos.x *= m_DisplayScale.x; + pos.y *= m_DisplayScale.y; return TouchEventPtr(new TouchEvent(id, type, pos, Event::TOUCH)); } diff --git a/src/player/XInputMTInputDevice.h b/src/player/XInputMTInputDevice.h index af10249..d395884 100644 --- a/src/player/XInputMTInputDevice.h +++ b/src/player/XInputMTInputDevice.h @@ -1,6 +1,6 @@ // // libavg - Media Playback Engine. -// Copyright (C) 2003-2011 Ulrich von Zadow +// Copyright (C) 2003-2014 Ulrich von Zadow // // This library is free software; you can redistribute it and/or // modify it under the terms of the GNU Lesser General Public @@ -28,7 +28,7 @@ #include "MultitouchInputDevice.h" #include "Event.h" -#include "../base/Point.h" +#include "../base/GLMHelper.h" #include <X11/Xlib.h> #include <vector> @@ -56,7 +56,7 @@ private: int m_LastID; - static Display* s_pDisplay; + static ::Display* s_pDisplay; void (*m_SDLLockFunc)(void); void (*m_SDLUnlockFunc)(void); @@ -66,6 +66,7 @@ private: int m_DeviceID; int m_OldMasterDeviceID; + glm::vec2 m_DisplayScale; }; typedef boost::shared_ptr<XInputMTInputDevice> XInputMTInputDevicePtr; diff --git a/src/player/testcalibrator.cpp b/src/player/testcalibrator.cpp index 175488f..a9898f5 100644 --- a/src/player/testcalibrator.cpp +++ b/src/player/testcalibrator.cpp @@ -1,6 +1,6 @@ // // libavg - Media Playback Engine. -// Copyright (C) 2003-2011 Ulrich von Zadow +// Copyright (C) 2003-2014 Ulrich von Zadow // // This library is free software; you can redistribute it and/or // modify it under the terms of the GNU Lesser General Public @@ -21,7 +21,7 @@ #include "TrackerCalibrator.h" -#include "../base/Point.h" +#include "../base/GLMHelper.h" #include "../base/TestSuite.h" #include "../base/Exception.h" @@ -49,45 +49,46 @@ public: bool bDone = false; while (!bDone) { IntPoint displayPoint(calibrator.getDisplayPoint()); - calibrator.setCamPoint(DPoint(displayPoint)); + calibrator.setCamPoint(glm::vec2(displayPoint)); bDone = !calibrator.nextPoint(); } pTrafo = calibrator.makeTransformer(); - TEST( calcDist(pTrafo->transformBlobToScreen( DPoint(1.00,1.00) ) , DPoint(1.00,1.00))<1); -// cerr << "scale: " << scale << ", offset: " << offset << endl; - TEST(checkTransform(pTrafo, DPoint(0,0), DPoint(0,0))); - TEST(checkTransform(pTrafo, DPoint(640, 480), DPoint(640, 480))); + TEST(glm::length(pTrafo->transformBlobToScreen(glm::dvec2(1.00,1.00)) - + glm::dvec2(1.00,1.00)) < 1); + TEST(checkTransform(pTrafo, glm::dvec2(0,0), glm::dvec2(0,0))); + TEST(checkTransform(pTrafo, glm::dvec2(640, 480), glm::dvec2(640, 480))); } { TrackerCalibrator calibrator(IntPoint(640, 480), IntPoint(1280,720)); bool bDone = false; while (!bDone) { IntPoint displayPoint(calibrator.getDisplayPoint()); - calibrator.setCamPoint(DPoint(displayPoint.x/2, displayPoint.y/1.5)); + calibrator.setCamPoint(glm::vec2(displayPoint.x/2, displayPoint.y/1.5)); bDone = !calibrator.nextPoint(); } pTrafo = calibrator.makeTransformer(); - TEST( calcDist( pTrafo->transformBlobToScreen( DPoint(1.00,1.00) ), DPoint(2.00,1.50)) <1 ); -// cerr << "scale: " << scale << ", offset: " << offset << endl; - TEST(checkTransform(pTrafo, DPoint(0,0), DPoint(0,0))); - TEST(checkTransform(pTrafo, DPoint(640, 480), DPoint(640, 480))); - TEST(checkBlobToScreen(pTrafo, DPoint(0,0), DPoint(0,0))); - TEST(checkBlobToScreen(pTrafo, DPoint(640, 480), DPoint(1280, 720))); + TEST(glm::length(pTrafo->transformBlobToScreen(glm::dvec2(1.00,1.00)) - + glm::dvec2(2.00,1.50)) < 1); + TEST(checkTransform(pTrafo, glm::dvec2(0,0), glm::dvec2(0,0))); + TEST(checkTransform(pTrafo, glm::dvec2(640, 480), glm::dvec2(640, 480))); + TEST(checkBlobToScreen(pTrafo, glm::dvec2(0,0), glm::dvec2(0,0))); + TEST(checkBlobToScreen(pTrafo, glm::dvec2(640, 480), glm::dvec2(1280, 720))); } } - bool checkTransform(CoordTransformerPtr pTrafo, const DPoint& srcPt, - const DPoint& destPt) + bool checkTransform(CoordTransformerPtr pTrafo, const glm::dvec2& srcPt, + const glm::dvec2& destPt) { - DPoint ResultPt = pTrafo->transform_point(srcPt); + glm::dvec2 ResultPt = pTrafo->transform_point(srcPt); // cerr << srcPt << " -> " << ResultPt << ", expected " << destPt << endl; return ((fabs(ResultPt.x-destPt.x) < 0.1) && (fabs(ResultPt.y-destPt.y) < 0.1)); } bool checkBlobToScreen(DeDistortPtr pTrafo, - const DPoint& srcPt, const DPoint& destPt) + const glm::dvec2& srcPt, const glm::dvec2& destPt) { - DPoint ResultPt = pTrafo->transformBlobToScreen(pTrafo->transform_point(srcPt)); + glm::dvec2 ResultPt = + pTrafo->transformBlobToScreen(pTrafo->transform_point(srcPt)); // cerr << srcPt << " -> " << ResultPt << ", expected " << destPt << endl; return ((fabs(ResultPt.x-destPt.x) < 1) && (fabs(ResultPt.y-destPt.y) < 1)); } diff --git a/src/player/testplayer.cpp b/src/player/testplayer.cpp index 342a2c4..aa0bef9 100644 --- a/src/player/testplayer.cpp +++ b/src/player/testplayer.cpp @@ -1,6 +1,6 @@ // // libavg - Media Playback Engine. -// Copyright (C) 2003-2011 Ulrich von Zadow +// Copyright (C) 2003-2014 Ulrich von Zadow // // This library is free software; you can redistribute it and/or // modify it under the terms of the GNU Lesser General Public @@ -25,11 +25,17 @@ #include "../base/Exception.h" #include "../base/Logger.h" +#include "../graphics/GLConfig.h" + #include <stdio.h> #include <stdlib.h> #include <math.h> #include <string> +#ifdef WIN32 +#include <direct.h> +#endif + using namespace avg; using namespace std; @@ -49,11 +55,18 @@ public: " <words text=\"foo\"/>" " </avg>" ); + player.setOGLOptions(false, true, 1, GLConfig::AUTO, true); + GLContext::enableErrorChecks(true); player.disablePython(); if (!getenv("AVG_CONSOLE_TEST")) { - player.initPlayback(); +#ifdef WIN32 + char sz[1024]; + _getcwd(sz, 1024); + cerr << "Current directory: " << sz << endl; +#endif + player.initPlayback("../graphics/shaders/"); player.doFrame(false); - player.cleanup(); + player.cleanup(false); } try { throw bad_cast(); |