on cb6d2b2 help sign in
unity8/plugins/Ubuntu/Gestures/AxisVelocityCalculator.cpp
158 lines 4.6 kB history raw
1/*
2 * Copyright (C) 2013 - Canonical Ltd.
3 *
4 * This program is free software: you can redistribute it and/or modify it
5 * under the terms of the GNU Lesser General Public License, as
6 * published by the Free Software Foundation; either version 2.1 or 3.0
7 * of the License.
8 *
9 * This program is distributed in the hope that it will be useful, but
10 * WITHOUT ANY WARRANTY; without even the implied warranties of
11 * MERCHANTABILITY, SATISFACTORY QUALITY or FITNESS FOR A PARTICULAR
12 * PURPOSE. See the applicable version of the GNU Lesser General Public
13 * License for more details.
14 *
15 * You should have received a copy of both the GNU Lesser General Public
16 * License along with this program. If not, see <http://www.gnu.org/licenses/>
17 *
18 * Authored by: Daniel d'Andrada <daniel.dandrada@canonical.com>
19 */
21#include "AxisVelocityCalculator.h"
22#include <QtCore/QElapsedTimer>
24class RealTimeSource : public UbuntuGestures::TimeSource {
25public:
26 RealTimeSource()
27 : UbuntuGestures::TimeSource() {
28 m_timer.start();
29 }
30 virtual qint64 msecsSinceReference() {
31 return m_timer.elapsed();
32 }
33private:
34 QElapsedTimer m_timer;
35};
37AxisVelocityCalculator::AxisVelocityCalculator(QObject *parent)
38 : QObject(parent)
39 , m_timeSource(new RealTimeSource)
40 , m_trackedPosition(0.0)
42 m_timeSource->setParent(this);
43 reset();
46AxisVelocityCalculator::~AxisVelocityCalculator()
50qreal AxisVelocityCalculator::trackedPosition() const
52 return m_trackedPosition;
55void AxisVelocityCalculator::setTrackedPosition(qreal newPosition)
57 processMovement(newPosition - m_trackedPosition);
59 if (newPosition != m_trackedPosition) {
60 m_trackedPosition = newPosition;
61 Q_EMIT trackedPositionChanged(newPosition);
62 }
65void AxisVelocityCalculator::updateIdleTime()
67 processMovement(0);
70void AxisVelocityCalculator::processMovement(qreal movement)
72 if (m_samplesRead == -1) {
73 m_samplesRead = m_samplesWrite;
74 } else if (m_samplesRead == m_samplesWrite) {
75 /* the oldest value is going to be overwritten.
76 so now the oldest will be the next one. */
77 m_samplesRead = (m_samplesRead + 1) % MAX_SAMPLES;
78 }
80 m_samples[m_samplesWrite].mov = movement;
81 m_samples[m_samplesWrite].time = m_timeSource->msecsSinceReference();
82 m_samplesWrite = (m_samplesWrite + 1) % MAX_SAMPLES;
85qreal AxisVelocityCalculator::calculate()
87 if (numSamples() < MIN_SAMPLES_NEEDED) {
88 return 0.0;
89 }
90 updateIdleTime(); // consider the time elapsed since the last update and now
92 int lastIndex;
93 if (m_samplesWrite == 0) {
94 lastIndex = MAX_SAMPLES - 1;
95 } else {
96 lastIndex = m_samplesWrite - 1;
97 }
99 qint64 currTime = m_samples[lastIndex].time;
101 qreal totalTime = 0;
102 qreal totalDistance = 0;
104 int sampleIndex = (m_samplesRead + 1) % MAX_SAMPLES;
105 qint64 previousTime = m_samples[m_samplesRead].time;
106 while (sampleIndex != m_samplesWrite) {
107 // Skip this sample if it's too old
108 if (currTime - m_samples[sampleIndex].time <= AGE_OLDEST_SAMPLE) {
109 int deltaTime = m_samples[sampleIndex].time - previousTime;
110 totalDistance += m_samples[sampleIndex].mov;
111 totalTime += deltaTime;
112 }
114 previousTime = m_samples[sampleIndex].time;
115 sampleIndex = (sampleIndex + 1) % MAX_SAMPLES;
116 }
118 return totalDistance / totalTime;
121void AxisVelocityCalculator::reset()
123 m_samplesRead = -1;
124 m_samplesWrite = 0;
127int AxisVelocityCalculator::numSamples() const
129 if (m_samplesRead == -1) {
130 return 0;
131 } else {
132 if (m_samplesWrite == 0) {
133 /* consider only what's to the right of m_samplesRead (including himself) */
134 return MAX_SAMPLES - m_samplesRead;
135 } else if (m_samplesWrite == m_samplesRead) {
136 return MAX_SAMPLES; /* buffer is full */
137 } else if (m_samplesWrite < m_samplesRead) {
138 return (MAX_SAMPLES - m_samplesRead) + m_samplesWrite;
139 } else {
140 return m_samplesWrite - m_samplesRead;
141 }
142 }
145void AxisVelocityCalculator::setTimeSource(UbuntuGestures::TimeSource *timeSource)
147 if (m_timeSource && m_timeSource->parent() == this)
148 delete m_timeSource;
150 m_timeSource = timeSource;
152 if (numSamples() > 0) {
153 qWarning("AxisVelocityCalculator: changing time source while there are samples present.");
154 // Any existent samples are based on the old time source and are, therefore, incompatible
155 // with this new one.
156 reset();
157 }