[ecore] merged svn latest code (svn54830)
[profile/ivi/ecore.git] / src / lib / ecore / ecore_anim.c
1 #ifdef HAVE_CONFIG_H
2 # include <config.h>
3 #endif
4
5 #include <stdlib.h>
6 #include <math.h>
7
8 #include "Ecore.h"
9 #include "ecore_private.h"
10
11
12 struct _Ecore_Animator
13 {
14    EINA_INLIST;
15    ECORE_MAGIC;
16
17    Ecore_Task_Cb func;
18    void          *data;
19
20    Eina_Bool     delete_me : 1;
21    Eina_Bool     suspended : 1;
22 };
23
24
25 static Eina_Bool _ecore_animator(void *data);
26
27 static Ecore_Timer    *timer = NULL;
28 static int             animators_delete_me = 0;
29 static Ecore_Animator *animators = NULL;
30 static double          animators_frametime = 1.0 / 30.0;
31
32 /**
33  * @addtogroup Ecore_Group Ecore - Main Loop and Job Functions.
34  *
35  * @{
36  */
37
38 /**
39  * @addtogroup Ecore_Animator_Group Ecore Animator functions
40  *
41  * @{
42  */
43
44 /**
45  * Add a animator to tick off at every animaton tick during main loop execution.
46  * @param func The function to call when it ticks off
47  * @param data The data to pass to the function
48  * @return A handle to the new animator
49  *
50  * This function adds a animator and returns its handle on success and NULL on
51  * failure. The function @p func will be called every N seconds where N is the
52  * frametime interval set by ecore_animator_frametime_set(). The function will
53  * be passed the @p data pointer as its parameter.
54  *
55  * When the animator @p func is called, it must return a value of either 1 or 0.
56  * If it returns 1 (or ECORE_CALLBACK_RENEW), it will be called again at the
57  * next tick, or if it returns 0 (or ECORE_CALLBACK_CANCEL) it will be deleted
58  * automatically making any references/handles for it invalid.
59  */
60 EAPI Ecore_Animator *
61 ecore_animator_add(Ecore_Task_Cb func, const void *data)
62 {
63    Ecore_Animator *animator;
64
65    if (!func) return NULL;
66    animator = calloc(1, sizeof(Ecore_Animator));
67    if (!animator) return NULL;
68    ECORE_MAGIC_SET(animator, ECORE_MAGIC_ANIMATOR);
69    animator->func = func;
70    animator->data = (void *)data;
71    animators = (Ecore_Animator *)eina_inlist_append(EINA_INLIST_GET(animators), EINA_INLIST_GET(animator));
72    if (!timer)
73      {
74         double t_loop = ecore_loop_time_get();
75         double sync_0 = 0.0;
76         double d = -fmod(t_loop - sync_0, animators_frametime);
77
78         timer = ecore_timer_loop_add(animators_frametime, _ecore_animator, NULL);
79         ecore_timer_delay(timer, d);
80      }
81    return animator;
82 }
83
84 /**
85  * Delete the specified animator from the animator list.
86  * @param animator The animator to delete
87  * @return The data pointer set for the animator
88  *
89  * Delete the specified @p aqnimator from the set of animators that are executed
90  * during main loop execution. This function returns the data parameter that
91  * was being passed to the callback on success, or NULL on failure. After this
92  * call returns the specified animator object @p animator is invalid and should not
93  * be used again. It will not get called again after deletion.
94  */
95 EAPI void *
96 ecore_animator_del(Ecore_Animator *animator)
97 {
98    if (!ECORE_MAGIC_CHECK(animator, ECORE_MAGIC_ANIMATOR))
99      {
100         ECORE_MAGIC_FAIL(animator, ECORE_MAGIC_ANIMATOR,
101                          "ecore_animator_del");
102         return NULL;
103      }
104    if (animator->delete_me) return animator->data;
105    animator->delete_me = EINA_TRUE;
106    animators_delete_me++;
107    return animator->data;
108 }
109
110 /**
111  * Set the animator call interval in seconds.
112  * @param frametime The time in seconds in between animator ticks.
113  *
114  * This function sets the time interval (in seconds) between animator ticks.
115  */
116 EAPI void
117 ecore_animator_frametime_set(double frametime)
118 {
119    if (frametime < 0.0) frametime = 0.0;
120    if (animators_frametime == frametime) return;
121    animators_frametime = frametime;
122    if (timer)
123      {
124         ecore_timer_del(timer);
125         timer = NULL;
126      }
127    if (animators)
128      timer = ecore_timer_add(animators_frametime, _ecore_animator, NULL);
129 }
130
131 /**
132  * Get the animator call interval in seconds.
133  * @return The time in second in between animator ticks.
134  *
135  * this function retrieves the time between animator ticks, in seconds.
136  */
137 EAPI double
138 ecore_animator_frametime_get(void)
139 {
140    return animators_frametime;
141 }
142
143 /**
144  * Suspend the specified animator.
145  * @param animator The animator to delete
146  *
147  * The specified @p animator will be temporarly removed from the set of animators
148  * that are executed during main loop execution.
149  */
150 EAPI void
151 ecore_animator_freeze(Ecore_Animator *animator)
152 {
153    if (!ECORE_MAGIC_CHECK(animator, ECORE_MAGIC_ANIMATOR))
154      {
155         ECORE_MAGIC_FAIL(animator, ECORE_MAGIC_ANIMATOR,
156                          "ecore_animator_del");
157         return;
158      }
159    if (animator->delete_me) return;
160    animator->suspended = EINA_TRUE;
161 }
162
163 /**
164  * Restore execution of the specified animator.
165  * @param animator The animator to delete
166  *
167  * The specified @p animator will be put back in the set of animators
168  * that are executed during main loop execution.
169  */
170 EAPI void
171 ecore_animator_thaw(Ecore_Animator *animator)
172 {
173    if (!ECORE_MAGIC_CHECK(animator, ECORE_MAGIC_ANIMATOR))
174      {
175         ECORE_MAGIC_FAIL(animator, ECORE_MAGIC_ANIMATOR,
176                          "ecore_animator_del");
177         return;
178      }
179    if (animator->delete_me) return;
180    animator->suspended = EINA_FALSE;
181 }
182
183 void
184 _ecore_animator_shutdown(void)
185 {
186    if (timer)
187      {
188         ecore_timer_del(timer);
189         timer = NULL;
190      }
191    while (animators)
192      {
193         Ecore_Animator *animator;
194
195         animator = animators;
196         animators = (Ecore_Animator *) eina_inlist_remove(EINA_INLIST_GET(animators), EINA_INLIST_GET(animators));
197         ECORE_MAGIC_SET(animator, ECORE_MAGIC_NONE);
198         free(animator);
199      }
200 }
201
202 static Eina_Bool
203 _ecore_animator(void *data __UNUSED__)
204 {
205    Ecore_Animator *animator;
206
207    EINA_INLIST_FOREACH(animators, animator)
208      {
209         if (!animator->delete_me && !animator->suspended)
210           {
211              if (!animator->func(animator->data))
212                {
213                   animator->delete_me = EINA_TRUE;
214                   animators_delete_me++;
215                }
216           }
217      }
218    if (animators_delete_me)
219      {
220         Ecore_Animator *l;
221         for(l = animators; l;)
222           {
223              animator = l;
224              l = (Ecore_Animator *) EINA_INLIST_GET(l)->next;
225              if (animator->delete_me)
226                {
227                   animators = (Ecore_Animator *) eina_inlist_remove(EINA_INLIST_GET(animators), EINA_INLIST_GET(animator));
228                   ECORE_MAGIC_SET(animator, ECORE_MAGIC_NONE);
229                   free(animator);
230                   animators_delete_me--;
231                   if (animators_delete_me == 0) break;
232                }
233           }
234      }
235    if (!animators)
236      {
237         timer = NULL;
238         return ECORE_CALLBACK_CANCEL;
239      }
240    return ECORE_CALLBACK_RENEW;
241 }
242
243 /**
244  * @}
245  */
246
247 /**
248  * @}
249  */