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