Lines 34-41
Link Here
|
34 |
pthread_mutex_t mtx_paint = PTHREAD_MUTEX_INITIALIZER; |
34 |
pthread_mutex_t mtx_paint = PTHREAD_MUTEX_INITIALIZER; |
35 |
pthread_mutex_t mtx_anim = PTHREAD_MUTEX_INITIALIZER; |
35 |
pthread_mutex_t mtx_anim = PTHREAD_MUTEX_INITIALIZER; |
36 |
pthread_cond_t cnd_anim = PTHREAD_COND_INITIALIZER; |
36 |
pthread_cond_t cnd_anim = PTHREAD_COND_INITIALIZER; |
|
|
37 |
pthread_mutex_t mtx_timeSkewCheck = PTHREAD_MUTEX_INITIALIZER; |
37 |
|
38 |
|
38 |
pthread_t th_switchmon, th_sighandler, th_anim; |
39 |
pthread_t th_switchmon, th_sighandler, th_anim, th_checkTime; |
39 |
|
40 |
|
40 |
int ctty = CTTY_VERBOSE; |
41 |
int ctty = CTTY_VERBOSE; |
41 |
|
42 |
|
Lines 58-64
Link Here
|
58 |
/* A container for the original settings of the silent TTY. */ |
59 |
/* A container for the original settings of the silent TTY. */ |
59 |
struct termios tios; |
60 |
struct termios tios; |
60 |
|
61 |
|
|
|
62 |
/* Flag set by the checkTime thread. Locked by mtx_timeSkewCheck. */ |
63 |
bool timeSkewDetected_b = false; |
64 |
|
61 |
#if WANT_MNG |
65 |
#if WANT_MNG |
|
|
66 |
|
67 |
/* |
68 |
* Check for time skews. |
69 |
*/ |
70 |
void *thf_checkTime(void *unused) |
71 |
{ |
72 |
struct timeval tv_current; |
73 |
const unsigned long sleepTime_ui = 100 * 1000; // 100 msecs |
74 |
long lastMsec; |
75 |
long currentMsec; |
76 |
long diffMsec; |
77 |
|
78 |
|
79 |
/* Try to detect system clock changed */ |
80 |
if ( gettimeofday( &tv_current, NULL ) != 0) |
81 |
{ |
82 |
perror( "Can't get time with gettimeofday!" ); |
83 |
return 0; |
84 |
} |
85 |
|
86 |
lastMsec = ( ( (long) tv_current.tv_sec ) * ( (long) 1000 ) ) + |
87 |
( ( (long) tv_current.tv_usec ) / ( (long) 1000 ) ); |
88 |
usleep( sleepTime_ui ); |
89 |
|
90 |
|
91 |
while ( 1 ) |
92 |
{ |
93 |
gettimeofday( &tv_current, NULL ); |
94 |
currentMsec = ( ( (long) tv_current.tv_sec ) * ( (long) 1000 ) ) + |
95 |
( ( (long) tv_current.tv_usec ) / ( (long) 1000 ) ); |
96 |
|
97 |
diffMsec = currentMsec - lastMsec; |
98 |
|
99 |
if ( ( diffMsec < 0 ) || ( diffMsec > 10*sleepTime_ui ) ) |
100 |
{ |
101 |
/* Time skew detected! Signal thf_anim a reset. */ |
102 |
pthread_mutex_lock( &mtx_timeSkewCheck ); |
103 |
timeSkewDetected_b = true; |
104 |
pthread_mutex_unlock( &mtx_timeSkewCheck ); |
105 |
|
106 |
pthread_mutex_lock(&mtx_anim); |
107 |
pthread_cond_signal(&cnd_anim); |
108 |
pthread_mutex_unlock(&mtx_anim); |
109 |
|
110 |
/* Get time again to compensate for delays caused by the mutex stuff. */ |
111 |
gettimeofday( &tv_current, NULL ); |
112 |
currentMsec = ( ( (long) tv_current.tv_sec ) * ( (long) 1000 ) ) + |
113 |
( ( (long) tv_current.tv_usec ) / ( (long) 1000 ) ); |
114 |
} |
115 |
|
116 |
lastMsec = currentMsec; |
117 |
usleep( sleepTime_ui ); |
118 |
} |
119 |
|
120 |
return 0; |
121 |
} |
122 |
|
123 |
|
62 |
/* |
124 |
/* |
63 |
* Display all animations of the type 'once' or 'loop'. |
125 |
* Display all animations of the type 'once' or 'loop'. |
64 |
*/ |
126 |
*/ |
Lines 69-86
Link Here
|
69 |
item *i; |
131 |
item *i; |
70 |
mng_anim *mng; |
132 |
mng_anim *mng; |
71 |
int delay = 10000, rdelay, oldstate; |
133 |
int delay = 10000, rdelay, oldstate; |
72 |
struct timespec ts, tsc; |
134 |
struct timespec ts, ts_last; |
|
|
135 |
bool resetAnims_b = false; |
136 |
|
137 |
/* Initialize the time value. */ |
138 |
clock_gettime(CLOCK_REALTIME, &ts); |
139 |
ts_last = ts; |
73 |
|
140 |
|
74 |
while(1) { |
141 |
while(1) { |
|
|
142 |
/* Check for a time skew */ |
75 |
pthread_setcancelstate(PTHREAD_CANCEL_DISABLE, &oldstate); |
143 |
pthread_setcancelstate(PTHREAD_CANCEL_DISABLE, &oldstate); |
76 |
pthread_mutex_lock(&mtx_paint); |
144 |
pthread_mutex_lock( &mtx_timeSkewCheck ); |
|
|
145 |
resetAnims_b = timeSkewDetected_b; |
146 |
timeSkewDetected_b = false; |
147 |
pthread_mutex_unlock( &mtx_timeSkewCheck ); |
148 |
pthread_setcancelstate(oldstate, NULL); |
149 |
|
150 |
|
151 |
/* Reset animations if neccessary */ |
152 |
if ( resetAnims_b ) |
153 |
{ |
154 |
pthread_setcancelstate(PTHREAD_CANCEL_DISABLE, &oldstate); |
155 |
pthread_mutex_lock(&mtx_paint); |
156 |
|
157 |
for (i = theme->anims.head; i != NULL; i = i->next) { |
158 |
ca = i->p; |
159 |
co = container_of(ca); |
160 |
|
161 |
if (!co->visible || |
162 |
(ca->flags & F_ANIM_METHOD_MASK) == F_ANIM_PROPORTIONAL || |
163 |
ca->status == F_ANIM_STATUS_DONE) |
164 |
continue; |
165 |
|
166 |
mng = mng_get_userdata(ca->mng); |
167 |
|
168 |
if ( (!mng->displayed_first) || (mng->wait_msecs > 0) ) |
169 |
mng_display_restart(ca->mng); |
170 |
} |
171 |
pthread_mutex_unlock(&mtx_paint); |
172 |
pthread_setcancelstate(oldstate, NULL); |
173 |
|
174 |
/* Our times are not valid any more. */ |
175 |
clock_gettime(CLOCK_REALTIME, &ts_last); |
176 |
} |
177 |
|
178 |
|
77 |
/* Find the shortest delay. */ |
179 |
/* Find the shortest delay. */ |
|
|
180 |
pthread_setcancelstate(PTHREAD_CANCEL_DISABLE, &oldstate); |
181 |
pthread_mutex_lock(&mtx_paint); |
78 |
for (i = theme->anims.head; i != NULL; i = i->next) { |
182 |
for (i = theme->anims.head; i != NULL; i = i->next) { |
79 |
ca = i->p; |
183 |
ca = i->p; |
80 |
co = container_of(ca); |
184 |
co = container_of(ca); |
81 |
|
185 |
|
82 |
if (!co->visible || |
186 |
if (!co->visible || |
83 |
(ca->flags & F_ANIM_METHOD_MASK) == F_ANIM_PROPORTIONAL || |
187 |
(ca->flags & F_ANIM_METHOD_MASK) == F_ANIM_PROPORTIONAL || |
84 |
ca->status == F_ANIM_STATUS_DONE) |
188 |
ca->status == F_ANIM_STATUS_DONE) |
85 |
continue; |
189 |
continue; |
86 |
|
190 |
|
Lines 89-112
Link Here
|
89 |
/* If this is a new animation (activated by a service), |
193 |
/* If this is a new animation (activated by a service), |
90 |
* display it immediately. */ |
194 |
* display it immediately. */ |
91 |
if (!mng->displayed_first) { |
195 |
if (!mng->displayed_first) { |
|
|
196 |
/* Set delay to 0 and paint the complete screen later. */ |
197 |
delay = 0; |
198 |
#if 0 |
92 |
anim_render_canvas(ca); |
199 |
anim_render_canvas(ca); |
93 |
|
200 |
|
94 |
if (ctty == CTTY_SILENT) |
201 |
if (ctty == CTTY_SILENT) |
95 |
fbsplashr_render_screen(theme, true, false, FBSPL_EFF_NONE); |
202 |
fbsplashr_render_screen(theme, true, false, FBSPL_EFF_NONE); |
|
|
203 |
#endif |
96 |
} |
204 |
} |
97 |
|
205 |
|
98 |
if (mng->wait_msecs < delay && mng->wait_msecs > 0) { |
206 |
if (mng->wait_msecs < delay && mng->wait_msecs > 0) { |
99 |
delay = mng->wait_msecs; |
207 |
delay = mng->wait_msecs; |
100 |
} |
208 |
} |
101 |
} |
209 |
} |
102 |
pthread_mutex_unlock(&mtx_paint); |
210 |
pthread_mutex_unlock(&mtx_paint); |
103 |
pthread_setcancelstate(oldstate, NULL); |
211 |
pthread_setcancelstate(oldstate, NULL); |
104 |
|
212 |
|
|
|
213 |
|
214 |
/* Get the current time and calculate the delay until the next refresh. */ |
105 |
pthread_mutex_lock(&mtx_anim); |
215 |
pthread_mutex_lock(&mtx_anim); |
106 |
clock_gettime(CLOCK_REALTIME, &ts); |
216 |
clock_gettime(CLOCK_REALTIME, &ts); |
107 |
|
217 |
|
108 |
ts.tv_sec += (int)(delay / 1000); |
218 |
|
109 |
ts.tv_nsec += (delay % 1000) * 1000000; |
219 |
/* Time we spent between the last update of the anim delays |
|
|
220 |
* and now (ts - ts_last) is subtracted from the delay. |
221 |
*/ |
222 |
ts.tv_sec += (int)(delay / 1000) - (ts.tv_sec - ts_last.tv_sec); |
223 |
ts.tv_nsec += (delay % 1000) * 1000000 - (ts.tv_nsec - ts_last.tv_nsec); |
110 |
|
224 |
|
111 |
/* Check for overflow of the nanoseconds field */ |
225 |
/* Check for overflow of the nanoseconds field */ |
112 |
if (ts.tv_nsec >= 1000000000) { |
226 |
if (ts.tv_nsec >= 1000000000) { |
Lines 114-132
Link Here
|
114 |
ts.tv_nsec -= 1000000000; |
228 |
ts.tv_nsec -= 1000000000; |
115 |
} |
229 |
} |
116 |
|
230 |
|
|
|
231 |
/* Wait until signaled or timeout */ |
117 |
pthread_cond_timedwait(&cnd_anim, &mtx_anim, &ts); |
232 |
pthread_cond_timedwait(&cnd_anim, &mtx_anim, &ts); |
118 |
pthread_mutex_unlock(&mtx_anim); |
233 |
pthread_mutex_unlock(&mtx_anim); |
119 |
|
234 |
|
120 |
pthread_setcancelstate(PTHREAD_CANCEL_DISABLE, &oldstate); |
235 |
pthread_setcancelstate(PTHREAD_CANCEL_DISABLE, &oldstate); |
121 |
pthread_mutex_lock(&mtx_paint); |
236 |
pthread_mutex_lock(&mtx_paint); |
|
|
237 |
|
238 |
|
122 |
/* Don't paint anything if we aren't in silent mode. */ |
239 |
/* Don't paint anything if we aren't in silent mode. */ |
123 |
if (ctty != CTTY_SILENT) |
240 |
if (ctty != CTTY_SILENT) |
124 |
goto next; |
241 |
goto next; |
125 |
|
242 |
|
|
|
243 |
|
126 |
/* Calculate the real delay. We might have been signalled by |
244 |
/* Calculate the real delay. We might have been signalled by |
127 |
* the splash daemon before 'delay' msecs passed. */ |
245 |
* the splash daemon before 'delay' msecs passed. */ |
128 |
clock_gettime(CLOCK_REALTIME, &tsc); |
246 |
clock_gettime(CLOCK_REALTIME, &ts); |
129 |
rdelay = delay + (tsc.tv_sec - ts.tv_sec)*1000 + (tsc.tv_nsec - ts.tv_nsec)/1000000; |
247 |
rdelay = delay + (ts.tv_sec - ts_last.tv_sec)*1000 + (ts.tv_nsec - ts_last.tv_nsec)/1000000; |
130 |
|
248 |
|
131 |
/* Update the wait time for all relevant animation objects. */ |
249 |
/* Update the wait time for all relevant animation objects. */ |
132 |
for (i = theme->anims.head ; i != NULL; i = i->next) { |
250 |
for (i = theme->anims.head ; i != NULL; i = i->next) { |
Lines 138-143
Link Here
|
138 |
continue; |
256 |
continue; |
139 |
|
257 |
|
140 |
mng = mng_get_userdata(ca->mng); |
258 |
mng = mng_get_userdata(ca->mng); |
|
|
259 |
|
260 |
/* Display new anims right now. */ |
261 |
if (!mng->displayed_first) |
262 |
{ |
263 |
anim_render_canvas(ca); |
264 |
} |
265 |
|
141 |
if (mng->wait_msecs > 0) { |
266 |
if (mng->wait_msecs > 0) { |
142 |
mng->wait_msecs -= rdelay; |
267 |
mng->wait_msecs -= rdelay; |
143 |
if (mng->wait_msecs <= 0) |
268 |
if (mng->wait_msecs <= 0) |
Lines 146-152
Link Here
|
146 |
} |
271 |
} |
147 |
fbsplashr_render_screen(theme, true, false, FBSPL_EFF_NONE); |
272 |
fbsplashr_render_screen(theme, true, false, FBSPL_EFF_NONE); |
148 |
|
273 |
|
149 |
next: pthread_mutex_unlock(&mtx_paint); |
274 |
|
|
|
275 |
next: |
276 |
/* Save the time just before refreshing the wait_msecs fields. */ |
277 |
ts_last = ts; |
278 |
|
279 |
pthread_mutex_unlock(&mtx_paint); |
150 |
pthread_setcancelstate(oldstate, NULL); |
280 |
pthread_setcancelstate(oldstate, NULL); |
151 |
|
281 |
|
152 |
/* Default delay is 10s */ |
282 |
/* Default delay is 10s */ |
Lines 560-565
Link Here
|
560 |
#ifdef CONFIG_MNG |
690 |
#ifdef CONFIG_MNG |
561 |
/* Start the animation thread */ |
691 |
/* Start the animation thread */ |
562 |
pthread_create(&th_anim, NULL, &thf_anim, NULL); |
692 |
pthread_create(&th_anim, NULL, &thf_anim, NULL); |
|
|
693 |
|
694 |
/* Start the time skew check thread */ |
695 |
pthread_create(&th_checkTime, NULL, &thf_checkTime, NULL ); |
563 |
#endif |
696 |
#endif |
564 |
|
697 |
|
565 |
pthread_mutex_lock(&mtx_tty); |
698 |
pthread_mutex_lock(&mtx_tty); |