1 /*
2 * Clutter.
3 *
4 * An OpenGL based 'interactive canvas' library.
5 *
6 * Authored By Neil Roberts <neil@linux.intel.com>
7 *
8 * Copyright (C) 2008 OpenedHand
9 *
10 * This library is free software; you can redistribute it and/or
11 * modify it under the terms of the GNU Lesser General Public
12 * License as published by the Free Software Foundation; either
13 * version 2 of the License, or (at your option) any later version.
14 *
15 * This library is distributed in the hope that it will be useful,
16 * but WITHOUT ANY WARRANTY; without even the implied warranty of
17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
18 * Lesser General Public License for more details.
19 *
20 * You should have received a copy of the GNU Lesser General Public
21 * License along with this library. If not, see <http://www.gnu.org/licenses/>.
22 *
23 *
24 */
25
26 #ifdef HAVE_CONFIG_H
27 #include "clutter-build-config.h"
28 #endif
29
30 #define CLUTTER_DISABLE_DEPRECATION_WARNINGS
31
32 #include "clutter-main.h"
33 #include "clutter-private.h"
34
35 #include "deprecated/clutter-frame-source.h"
36 #include "deprecated/clutter-timeout-interval.h"
37
38 typedef struct _ClutterFrameSource ClutterFrameSource;
39
40 struct _ClutterFrameSource
41 {
42 GSource source;
43
44 ClutterTimeoutInterval timeout;
45 };
46
47 static gboolean clutter_frame_source_prepare (GSource *source,
48 gint *timeout);
49 static gboolean clutter_frame_source_check (GSource *source);
50 static gboolean clutter_frame_source_dispatch (GSource *source,
51 GSourceFunc callback,
52 gpointer user_data);
53
54 static GSourceFuncs clutter_frame_source_funcs =
55 {
56 clutter_frame_source_prepare,
57 clutter_frame_source_check,
58 clutter_frame_source_dispatch,
59 NULL
60 };
61
62 /**
63 * clutter_frame_source_add_full: (rename-to clutter_frame_source_add)
64 * @priority: the priority of the frame source. Typically this will be in the
65 * range between %G_PRIORITY_DEFAULT and %G_PRIORITY_HIGH.
66 * @fps: the number of times per second to call the function
67 * @func: function to call
68 * @data: data to pass to the function
69 * @notify: function to call when the timeout source is removed
70 *
71 * Sets a function to be called at regular intervals with the given
72 * priority. The function is called repeatedly until it returns
73 * %FALSE, at which point the timeout is automatically destroyed and
74 * the function will not be called again. The @notify function is
75 * called when the timeout is destroyed. The first call to the
76 * function will be at the end of the first @interval.
77 *
78 * This function is similar to g_timeout_add_full() except that it
79 * will try to compensate for delays. For example, if @func takes half
80 * the interval time to execute then the function will be called again
81 * half the interval time after it finished. In contrast
82 * g_timeout_add_full() would not fire until a full interval after the
83 * function completes so the delay between calls would be 1.0 / @fps *
84 * 1.5. This function does not however try to invoke the function
85 * multiple times to catch up missing frames if @func takes more than
86 * @interval ms to execute.
87 *
88 * Return value: the ID (greater than 0) of the event source.
89 *
90 * Since: 0.8
91 *
92 * Deprecated: 1.6: There is no direct replacement for this API.
93 */
94 guint
clutter_frame_source_add_full(gint priority,guint fps,GSourceFunc func,gpointer data,GDestroyNotify notify)95 clutter_frame_source_add_full (gint priority,
96 guint fps,
97 GSourceFunc func,
98 gpointer data,
99 GDestroyNotify notify)
100 {
101 guint ret;
102 GSource *source = g_source_new (&clutter_frame_source_funcs,
103 sizeof (ClutterFrameSource));
104 ClutterFrameSource *frame_source = (ClutterFrameSource *) source;
105
106 _clutter_timeout_interval_init (&frame_source->timeout, fps);
107
108 if (priority != G_PRIORITY_DEFAULT)
109 g_source_set_priority (source, priority);
110
111 g_source_set_name (source, "Clutter frame timeout");
112 g_source_set_callback (source, func, data, notify);
113
114 ret = g_source_attach (source, NULL);
115
116 g_source_unref (source);
117
118 return ret;
119 }
120
121 /**
122 * clutter_frame_source_add: (skip)
123 * @fps: the number of times per second to call the function
124 * @func: function to call
125 * @data: data to pass to the function
126 *
127 * Simple wrapper around clutter_frame_source_add_full().
128 *
129 * Return value: the ID (greater than 0) of the event source.
130 *
131 * Since: 0.8
132 *
133 * Deprecated: 1.6: There is no direct replacement for this API
134 */
135 guint
clutter_frame_source_add(guint fps,GSourceFunc func,gpointer data)136 clutter_frame_source_add (guint fps,
137 GSourceFunc func,
138 gpointer data)
139 {
140 return clutter_frame_source_add_full (G_PRIORITY_DEFAULT,
141 fps, func, data, NULL);
142 }
143
144 static gboolean
clutter_frame_source_prepare(GSource * source,gint * delay)145 clutter_frame_source_prepare (GSource *source,
146 gint *delay)
147 {
148 ClutterFrameSource *frame_source = (ClutterFrameSource *) source;
149 gint64 current_time;
150
151 #if GLIB_CHECK_VERSION (2, 27, 3)
152 current_time = g_source_get_time (source) / 1000;
153 #else
154 {
155 GTimeVal source_time;
156 g_source_get_current_time (source, &source_time);
157 current_time = source_time.tv_sec * 1000 + source_time.tv_usec / 1000;
158 }
159 #endif
160
161 return _clutter_timeout_interval_prepare (current_time,
162 &frame_source->timeout,
163 delay);
164 }
165
166 static gboolean
clutter_frame_source_check(GSource * source)167 clutter_frame_source_check (GSource *source)
168 {
169 return clutter_frame_source_prepare (source, NULL);
170 }
171
172 static gboolean
clutter_frame_source_dispatch(GSource * source,GSourceFunc callback,gpointer user_data)173 clutter_frame_source_dispatch (GSource *source,
174 GSourceFunc callback,
175 gpointer user_data)
176 {
177 ClutterFrameSource *frame_source = (ClutterFrameSource *) source;
178
179 return _clutter_timeout_interval_dispatch (&frame_source->timeout,
180 callback, user_data);
181 }
182
183 /**
184 * clutter_threads_add_frame_source_full: (rename-to clutter_threads_add_frame_source)
185 * @priority: the priority of the frame source. Typically this will be in the
186 * range between %G_PRIORITY_DEFAULT and %G_PRIORITY_HIGH.
187 * @fps: the number of times per second to call the function
188 * @func: function to call
189 * @data: data to pass to the function
190 * @notify: function to call when the timeout source is removed
191 *
192 * Sets a function to be called at regular intervals holding the Clutter
193 * threads lock, with the given priority. The function is called repeatedly
194 * until it returns %FALSE, at which point the timeout is automatically
195 * removed and the function will not be called again. The @notify function
196 * is called when the timeout is removed.
197 *
198 * This function is similar to clutter_threads_add_timeout_full()
199 * except that it will try to compensate for delays. For example, if
200 * @func takes half the interval time to execute then the function
201 * will be called again half the interval time after it finished. In
202 * contrast clutter_threads_add_timeout_full() would not fire until a
203 * full interval after the function completes so the delay between
204 * calls would be @interval * 1.5. This function does not however try
205 * to invoke the function multiple times to catch up missing frames if
206 * @func takes more than @interval ms to execute.
207 *
208 * See also clutter_threads_add_idle_full().
209 *
210 * Return value: the ID (greater than 0) of the event source.
211 *
212 * Since: 0.8
213 *
214 * Deprecated: 1.6: There is no direct replacement for this API
215 */
216 guint
clutter_threads_add_frame_source_full(gint priority,guint fps,GSourceFunc func,gpointer data,GDestroyNotify notify)217 clutter_threads_add_frame_source_full (gint priority,
218 guint fps,
219 GSourceFunc func,
220 gpointer data,
221 GDestroyNotify notify)
222 {
223 ClutterThreadsDispatch *dispatch;
224
225 g_return_val_if_fail (func != NULL, 0);
226
227 dispatch = g_slice_new (ClutterThreadsDispatch);
228 dispatch->func = func;
229 dispatch->data = data;
230 dispatch->notify = notify;
231
232 return clutter_frame_source_add_full (priority,
233 fps,
234 _clutter_threads_dispatch, dispatch,
235 _clutter_threads_dispatch_free);
236 }
237
238 /**
239 * clutter_threads_add_frame_source: (skip)
240 * @fps: the number of times per second to call the function
241 * @func: function to call
242 * @data: data to pass to the function
243 *
244 * Simple wrapper around clutter_threads_add_frame_source_full().
245 *
246 * Return value: the ID (greater than 0) of the event source.
247 *
248 * Since: 0.8
249 *
250 * Deprecated: 1.6: There is no direct replacement for this API
251 */
252 guint
clutter_threads_add_frame_source(guint fps,GSourceFunc func,gpointer data)253 clutter_threads_add_frame_source (guint fps,
254 GSourceFunc func,
255 gpointer data)
256 {
257 g_return_val_if_fail (func != NULL, 0);
258
259 return clutter_threads_add_frame_source_full (G_PRIORITY_DEFAULT,
260 fps,
261 func, data,
262 NULL);
263 }
264