~ubuntu-branches/ubuntu/trusty/geis/trusty

« back to all changes in this revision

Viewing changes to libgeis/geis_gesture_flick.c

  • Committer: Package Import Robot
  • Author(s): Chase Douglas
  • Date: 2012-07-30 08:51:42 UTC
  • Revision ID: package-import@ubuntu.com-20120730085142-jrc33ygjvt0ob1wl
Tags: upstream-2.2.11
ImportĀ upstreamĀ versionĀ 2.2.11

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/**
 
2
 * @file geis_gesture_flick.c
 
3
 * @brief higher-level "flick" gesture recognizer
 
4
 *
 
5
 * Copyright 2011 Canonical Ltd.
 
6
 *
 
7
 * This library is free software; you can redistribute it and/or modify it under
 
8
 * the terms of the GNU Lesser General Public License as published by the Free
 
9
 * Software Foundation; either version 3 of the License, or (at your option) any
 
10
 * later version.
 
11
 *
 
12
 * This library is distributed in the hope that it will be useful, but WITHOUT
 
13
 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
 
14
 * FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
 
15
 * details.
 
16
 *
 
17
 * You should have received a copy of the GNU General Public License
 
18
 * along with this program.  If not, see <http://www.gnu.org/licenses/>.
 
19
 */
 
20
#include "geis_gesture_flick.h"
 
21
 
 
22
#include "geis_class.h"
 
23
#include "geis_frame.h"
 
24
#include "geis_logging.h"
 
25
#include "geis_private.h"
 
26
#include <string.h>
 
27
 
 
28
 
 
29
struct GeisGestureFlick
 
30
{
 
31
  Geis             geis;
 
32
  GeisGestureClass flick_class;
 
33
  GeisBoolean      enabled;
 
34
};
 
35
 
 
36
static GeisFloat _flick_threshold_squared = 1.0f;
 
37
 
 
38
 
 
39
static GeisProcessingResult
 
40
_recognize_flick(GeisEvent event, void *context)
 
41
{
 
42
  GeisProcessingResult result = GEIS_PROCESSING_IGNORED;
 
43
  GeisGestureFlick flick = (GeisGestureFlick)context;
 
44
 
 
45
  if (!flick->enabled)
 
46
    goto final_exit;
 
47
 
 
48
  switch (geis_event_type(event))
 
49
  {
 
50
    case GEIS_EVENT_GESTURE_END:
 
51
      {
 
52
        GeisAttr attr;
 
53
        attr = geis_event_attr_by_name(event, GEIS_EVENT_ATTRIBUTE_GROUPSET);
 
54
        if (!attr)
 
55
        {
 
56
          geis_error("no groupset for gesture event");
 
57
          goto final_exit;
 
58
        }
 
59
 
 
60
        GeisGroupSet groupset = geis_attr_value_to_pointer(attr);
 
61
        if (!groupset)
 
62
        {
 
63
          geis_warning("can not convert attr to groupset");
 
64
          goto final_exit;
 
65
        }
 
66
 
 
67
        GeisSize i;
 
68
        for (i = 0; i < geis_groupset_group_count(groupset); ++i)
 
69
        {
 
70
          GeisGroup group = geis_groupset_group(groupset, i);
 
71
          if (!group)
 
72
          {
 
73
            geis_warning("can not extract group %zu from groupset", i);
 
74
            goto final_exit;
 
75
          }
 
76
 
 
77
          GeisSize j;
 
78
          for (j = 0; j < geis_group_frame_count(group); ++j)
 
79
          {
 
80
            GeisFloat   dx = 0.0f;
 
81
            GeisFloat   dy = 0.0f;
 
82
            GeisFloat   rv = 0.0f;
 
83
            GeisFrame   frame = geis_group_frame(group, j);
 
84
            if (!frame)
 
85
            {
 
86
              geis_warning("can not extract frame %zu from group", j);
 
87
              goto final_exit;
 
88
            }
 
89
 
 
90
            GeisSize num_attrs = geis_frame_attr_count(frame);
 
91
            for (i = 0; i < num_attrs; ++i)
 
92
            {
 
93
              GeisAttr   attr = geis_frame_attr(frame, i);
 
94
              GeisString attr_name = geis_attr_name(attr);
 
95
 
 
96
              if (0 == strcmp(attr_name, GEIS_CLASS_ATTRIBUTE_ID))
 
97
              {
 
98
                GeisInteger class_id = geis_attr_value_to_integer(attr);
 
99
                if (class_id != GEIS_GESTURE_PRIMITIVE_DRAG)
 
100
                {
 
101
                  goto final_exit;
 
102
                }
 
103
              }
 
104
              else if (0 == strcmp(attr_name, GEIS_GESTURE_ATTRIBUTE_VELOCITY_X))
 
105
              {
 
106
                dx = geis_attr_value_to_float(attr);
 
107
              }
 
108
              else if (0 == strcmp(attr_name, GEIS_GESTURE_ATTRIBUTE_VELOCITY_Y))
 
109
              {
 
110
                dy = geis_attr_value_to_float(attr);
 
111
              }
 
112
            }
 
113
 
 
114
            rv = dx * dx + dy * dy;
 
115
            if (rv > _flick_threshold_squared)
 
116
            {
 
117
              geis_frame_set_is_class(frame, flick->flick_class);
 
118
            }
 
119
          }
 
120
        }
 
121
      }
 
122
      break;
 
123
 
 
124
    default:
 
125
      break;
 
126
  }
 
127
 
 
128
final_exit:
 
129
  return result;
 
130
}
 
131
 
 
132
 
 
133
static GeisStatus
 
134
_add_class_term(GeisBackendToken     token,
 
135
                void                *context,
 
136
                GeisString           name,
 
137
                GeisFilterOperation  op,
 
138
                void                *value)
 
139
{
 
140
  GeisStatus status = GEIS_STATUS_UNKNOWN_ERROR;
 
141
  GeisGestureFlick flick = (GeisGestureFlick)context;
 
142
 
 
143
  if (0 == strcmp(name, GEIS_CLASS_ATTRIBUTE_NAME))
 
144
  {
 
145
    if (op == GEIS_FILTER_OP_EQ)
 
146
    {
 
147
      GeisString class_name = (GeisString)value;
 
148
      if (0 == strcmp(class_name, geis_gesture_class_name(flick->flick_class)))
 
149
      {
 
150
        geis_filterable_attribute_foreach(flick->geis,
 
151
                                          GEIS_FILTER_CLASS,
 
152
                                          token,
 
153
                                          GEIS_CLASS_ATTRIBUTE_NAME,
 
154
                                          GEIS_FILTER_OP_EQ,
 
155
                                          GEIS_GESTURE_DRAG);
 
156
        flick->enabled = GEIS_TRUE;
 
157
      }
 
158
      else
 
159
      {
 
160
        flick->enabled = GEIS_FALSE;
 
161
      }
 
162
    }
 
163
    status = GEIS_STATUS_SUCCESS;
 
164
  }
 
165
  else if (0 == strcmp(name, GEIS_CLASS_ATTRIBUTE_ID))
 
166
  {
 
167
    if (op == GEIS_FILTER_OP_EQ)
 
168
    {
 
169
      GeisInteger id = *(GeisInteger*)value;
 
170
      if (id == geis_gesture_class_id(flick->flick_class))
 
171
      {
 
172
        geis_filterable_attribute_foreach(flick->geis,
 
173
                                          GEIS_FILTER_CLASS,
 
174
                                          token,
 
175
                                          GEIS_CLASS_ATTRIBUTE_NAME,
 
176
                                          GEIS_FILTER_OP_EQ,
 
177
                                          GEIS_GESTURE_DRAG);
 
178
        flick->enabled = GEIS_TRUE;
 
179
      }
 
180
      else
 
181
      {
 
182
        flick->enabled = GEIS_FALSE;
 
183
      }
 
184
    }
 
185
    status = GEIS_STATUS_SUCCESS;
 
186
  }
 
187
  else if (0 == strcmp(name, GEIS_GESTURE_ATTRIBUTE_TOUCHES))
 
188
  {
 
189
    /* GeisInteger touches = *(GeisInteger*)value; */
 
190
    /* must explicitly ask for high-level gestures */
 
191
    /* flick->enabled = GEIS_TRUE; */
 
192
    status = GEIS_STATUS_SUCCESS;
 
193
  }
 
194
  return status;
 
195
}
 
196
 
 
197
 
 
198
GeisGestureFlick
 
199
geis_gesture_flick_new(Geis geis)
 
200
{
 
201
  GeisSize attr_count = 0;
 
202
  struct GeisFilterableAttribute attrs[3];
 
203
  GeisGestureFlick flick = calloc(1, sizeof(struct GeisGestureFlick));
 
204
  if (!flick)
 
205
  {
 
206
    geis_error("can not create flick");
 
207
    goto final_exit;
 
208
  }
 
209
 
 
210
  flick->geis = geis;
 
211
  flick->flick_class = geis_gesture_class_new(GEIS_GESTURE_FLICK,
 
212
                                              GEIS_GESTURE_ID_FLICK);
 
213
  geis_gesture_class_ref(flick->flick_class);
 
214
  geis_filterable_attribute_init(&attrs[attr_count++],
 
215
                                 GEIS_CLASS_ATTRIBUTE_NAME,
 
216
                                 GEIS_ATTR_TYPE_STRING,
 
217
                                 _add_class_term,
 
218
                                 flick);
 
219
  geis_filterable_attribute_init(&attrs[attr_count++],
 
220
                                 GEIS_CLASS_ATTRIBUTE_ID,
 
221
                                 GEIS_ATTR_TYPE_INTEGER,
 
222
                                 _add_class_term,
 
223
                                 flick);
 
224
  geis_filterable_attribute_init(&attrs[attr_count++],
 
225
                                 GEIS_GESTURE_ATTRIBUTE_TOUCHES,
 
226
                                 GEIS_ATTR_TYPE_INTEGER,
 
227
                                 _add_class_term,
 
228
                                 flick);
 
229
 
 
230
  geis_register_gesture_class(geis, flick->flick_class, attr_count, attrs);
 
231
  geis_register_processing_callback(geis, 10, _recognize_flick, flick);
 
232
 
 
233
final_exit:
 
234
  return flick;
 
235
}
 
236
 
 
237
 
 
238
void
 
239
geis_gesture_flick_delete(GeisGestureFlick flick)
 
240
{
 
241
  if (flick)
 
242
  {
 
243
    geis_gesture_class_unref(flick->flick_class);
 
244
    free(flick);
 
245
  }
 
246
}
 
247