2
// libavg - Media Playback Engine.
3
// Copyright (C) 2003-2011 Ulrich von Zadow
5
// This library is free software; you can redistribute it and/or
6
// modify it under the terms of the GNU Lesser General Public
7
// License as published by the Free Software Foundation; either
8
// version 2 of the License, or (at your option) any later version.
10
// This library is distributed in the hope that it will be useful,
11
// but WITHOUT ANY WARRANTY; without even the implied warranty of
12
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13
// Lesser General Public License for more details.
15
// You should have received a copy of the GNU Lesser General Public
16
// License along with this library; if not, write to the Free Software
17
// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
19
// Current versions can be found at www.libavg.de
24
#include "CursorEvent.h"
25
#include "BoostPython.h"
28
#include "../base/Exception.h"
29
#include "../base/StringHelper.h"
37
int Contact::s_LastListenerID = 0;
39
Contact::Contact(CursorEventPtr pEvent)
40
: m_bSendingEvents(false),
41
m_bCurListenerIsDead(false),
42
m_CursorID(pEvent->getCursorID()),
43
m_DistanceTravelled(0)
45
m_Events.push_back(pEvent);
52
int Contact::connectListener(PyObject* pMotionCallback, PyObject* pUpCallback)
55
pair<int, Listener> val =
56
pair<int, Listener>(s_LastListenerID, Listener(pMotionCallback, pUpCallback));
57
m_ListenerMap.insert(val);
58
return s_LastListenerID;
61
void Contact::disconnectListener(int id)
63
map<int, Listener>::iterator it = m_ListenerMap.find(id);
64
if (it == m_ListenerMap.end() || (m_CurListenerID == id && m_bCurListenerIsDead)) {
65
throw Exception(AVG_ERR_INVALID_ARGS,
66
"Contact.disconnectListener: id " + toString(id) + " is not connected.");
68
if (m_bSendingEvents && m_CurListenerID == id) {
69
m_bCurListenerIsDead = true;
71
m_ListenerMap.erase(it);
75
long long Contact::getAge() const
77
return m_Events.back()->getWhen() - m_Events[0]->getWhen();
80
double Contact::getDistanceFromStart() const
82
return getMotionVec().getNorm();
85
double Contact::getMotionAngle() const
87
DPoint motion = getMotionVec();
88
if (motion == DPoint(0,0)) {
91
return motion.getAngle();
95
DPoint Contact::getMotionVec() const
97
return m_Events.back()->getPos() - m_Events[0]->getPos();
100
double Contact::getDistanceTravelled() const
102
return m_DistanceTravelled;
105
vector<CursorEventPtr> Contact::getEvents() const
110
void Contact::addEvent(CursorEventPtr pEvent)
112
pEvent->setCursorID(m_CursorID);
113
pEvent->setContact(shared_from_this());
114
calcSpeed(pEvent, m_Events.back());
115
updateDistanceTravelled(m_Events.back(), pEvent);
116
m_Events.back()->removeBlob();
117
m_Events.push_back(pEvent);
120
bool Contact::hasListeners() const
122
return !(m_ListenerMap.empty() ||
123
(m_ListenerMap.size() == 1 && m_bCurListenerIsDead));
126
void Contact::sendEventToListeners(CursorEventPtr pCursorEvent)
128
m_bSendingEvents = true;
129
AVG_ASSERT(pCursorEvent->getContact() == shared_from_this());
130
EventPtr pEvent = boost::dynamic_pointer_cast<Event>(pCursorEvent);
131
m_bCurListenerIsDead = false;
132
for (map<int, Listener>::iterator it = m_ListenerMap.begin();
133
it != m_ListenerMap.end();)
135
Listener listener = it->second;
136
m_CurListenerID = it->first;
137
m_bCurListenerIsDead = false;
138
switch (pCursorEvent->getType()) {
139
case Event::CURSORMOTION:
140
if (listener.m_pMotionCallback != Py_None) {
141
boost::python::call<void>(listener.m_pMotionCallback, pEvent);
144
case Event::CURSORUP:
145
if (listener.m_pUpCallback != Py_None) {
146
boost::python::call<void>(listener.m_pUpCallback, pEvent);
152
map<int, Listener>::iterator lastIt = it;
154
if (m_bCurListenerIsDead) {
155
m_ListenerMap.erase(lastIt);
156
m_bCurListenerIsDead = false;
159
m_bSendingEvents = false;
162
int Contact::getID() const
167
bool Contact::operator ==(const Contact& other) const
169
return (shared_from_this() == other.shared_from_this());
172
bool Contact::operator !=(const Contact& other) const
174
return (shared_from_this() != other.shared_from_this());
177
long Contact::getHash() const
179
return long(&*shared_from_this());
183
void Contact::calcSpeed(CursorEventPtr pEvent, CursorEventPtr pOldEvent)
185
if (pEvent->getSpeed() == DPoint(0,0)) {
186
DPoint posDiff = pEvent->getPos() - pOldEvent->getPos();
187
long long timeDiff = pEvent->getWhen() - pOldEvent->getWhen();
189
pEvent->setSpeed(posDiff/double(timeDiff));
194
void Contact::updateDistanceTravelled(CursorEventPtr pEvent1, CursorEventPtr pEvent2)
196
double dist = (pEvent2->getPos() - pEvent1->getPos()).getNorm();
197
m_DistanceTravelled += dist;
200
void Contact::dumpListeners(string sFuncName)
202
cerr << " " << sFuncName << ": ";
203
for (map<int, Listener>::iterator it = m_ListenerMap.begin();
204
it != m_ListenerMap.end(); ++it)
206
cerr << it->first << ", ";
211
Contact::Listener::Listener(PyObject * pMotionCallback, PyObject * pUpCallback)
213
Py_INCREF(pMotionCallback);
214
m_pMotionCallback = pMotionCallback;
215
Py_INCREF(pUpCallback);
216
m_pUpCallback = pUpCallback;
219
Contact::Listener::Listener(const Listener& other)
221
Py_INCREF(other.m_pMotionCallback);
222
m_pMotionCallback = other.m_pMotionCallback;
223
Py_INCREF(other.m_pUpCallback);
224
m_pUpCallback = other.m_pUpCallback;
227
Contact::Listener::~Listener()
229
Py_DECREF(m_pMotionCallback);
230
Py_DECREF(m_pUpCallback);