1 /*****
2  *       Xnee's Not an Event Emulator
3  *
4  * Xnee enables recording and replaying of X protocol data
5  *
6  *        Copyright (C) 1999, 2000, 2001, 2002, 2003
7  *                      2011  Henrik Sandklef
8  *
9  * This program is free software; you can redistribute it and/or
10  * modify it under the terms of the GNU General Public License
11  * as published by the Free Software Foundation; either version 3
12  * of the License, or any later version.
13  *
14  *
15  * This program 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
18  * GNU General Public License for more details.
19  *
20  * You should have received a copy of the GNU General Public License
21  * along with this program; if not, write to the Free Software
22  * Foundation, Inc., 51 Franklin Street, Boston,
23  * MA  02110-1301, USA.
24  ****/
25 
26 
27 
28 #include "libxnee/xnee.h"
29 #include "libxnee/print.h"
30 #include "libxnee/xnee_record.h"
31 #include "libxnee/xnee_replay.h"
32 #include "libxnee/xnee_sem.h"
33 #include "libxnee/xnee_time.h"
34 #include "libxnee/xnee_buffer.h"
35 #include "libxnee/xnee_resolution.h"
36 #include "libxnee/xnee_dl.h"
37 
38 
39 
40 
41 /**************************************************************
42  *                                                            *
43  * xnee_get_elapsed_time                                      *
44  *                                                            *
45  *                                                            *
46  **************************************************************/
47 static  unsigned long last_read_msecec  = 0;
48 static  unsigned long last_read_sec     = 0;
49 static  unsigned long first_read_msecec = 0;
50 static  unsigned long first_read_sec    = 0;
51 
52 
53 int
xnee_reset_elapsed_time(xnee_data * xd)54 xnee_reset_elapsed_time(xnee_data *xd)
55 {
56 
57     xnee_verbose ((xd, " --- xnee_reset_elapsed_time \n"));
58 
59     last_read_msecec       = 0;
60     last_read_sec     = 0;
61     first_read_msecec = 0;
62     first_read_sec    = 0;
63     return XNEE_OK;
64 }
65 
66 
67 long
xnee_get_elapsed_time(xnee_data * xd,char type)68 xnee_get_elapsed_time(xnee_data *xd, char type )
69 {
70   long    last_sec;
71   long    last_msec;
72   long    diff_sec;
73   long    diff_msec;
74   long    time_offset_msec  = 0;
75 
76   struct timeval  cur_time;
77   struct timezone zoneData;
78 
79   xnee_verbose ((xd, " --- xnee_get_elapsed_time\n"));
80 
81 
82   /* determine what value to get difference from */
83   if ( type == XNEE_FROM_LAST_READ )
84     {
85       last_sec  = last_read_sec;
86       last_msec = last_read_msecec;
87     }
88   else
89     {
90       last_sec  = first_read_sec;
91       last_msec = first_read_msecec;
92     }
93 
94   /* get current time */
95   if(  gettimeofday( &cur_time, &zoneData) == 0 )
96     {
97 
98       /* get difference between now and last */
99       diff_sec = cur_time.tv_sec - last_sec;
100       diff_msec = (cur_time.tv_usec/1000) - last_msec;
101 
102       /* convert diff to msec */
103       time_offset_msec = (diff_sec * XNEE_MSEC_PER_SEC) + diff_msec;
104 
105 
106       /* if first time through - save values and return XNEE_OK */
107       if ( last_sec == 0  )
108 	{
109 	  last_read_msecec  = cur_time.tv_usec/1000;
110 	  last_read_sec     = cur_time.tv_sec;
111 	  first_read_msecec = cur_time.tv_usec/1000;
112 	  first_read_sec    = cur_time.tv_sec;
113 /* 	  xnee_verbose ((xd, "1st elapsed time:%c _sec _msec: %d %d timeoffeset = 0\n",  */
114 /* 		       type, cur_time.tv_sec, cur_time.tv_usec )); */
115 	  return XNEE_OK;
116 	}
117 
118       /* update last_read values with the new time */
119       if ( type == XNEE_FROM_LAST_READ )
120 	{
121 	  last_read_msecec = cur_time.tv_usec/1000;
122 	  last_read_sec    = cur_time.tv_sec;
123     	}
124       /*       xnee_verbose ((xd, "elapsed time type:%c current time _sec _msec: %d %d time_offset_msec: %d\n",  */
125       /* 		   type, cur_time.tv_sec, cur_time.tv_usec, time_offset_msec )); */
126       return time_offset_msec;
127     }
128 
129 
130 
131   /* Shouldn't reach this point.... silent the compiler */
132   return 0;
133 }
134 
135 
136 
137 
138 
139 /**************************************************************
140  *                                                            *
141  * xnee_calc_sleep_amount                                     *
142  *                                                            *
143  *                                                            *
144  **************************************************************/
145 long
xnee_calc_sleep_amount(xnee_data * xd,unsigned long last_diff,unsigned long first_diff,unsigned long record_last_diff,unsigned long recordFirst_diff)146 xnee_calc_sleep_amount(xnee_data *xd,
147 		       unsigned long last_diff,
148 		       unsigned long first_diff,
149 		       unsigned long record_last_diff,
150 		       unsigned long recordFirst_diff )
151 {
152   /* Time sleep_amt; */
153   unsigned long out_of_wack_amt = 0;
154   int           out_of_wack     = 0;
155   float tmp;
156   float start_diff_percent ;
157   float compensation_factor ;
158   float sleep_amt ;
159   static unsigned long stored_recordFirst_diff;
160 
161   xnee_verbose ((xd, "xnee_calc_sleep_amount last_diff: %lu first_diff: %lu record_last_diff:"
162 		 "%lu recordFirst_diff: %lu\n",
163 		 last_diff, first_diff, record_last_diff, recordFirst_diff ));
164 
165   if ( stored_recordFirst_diff != 0 )
166     {
167       start_diff_percent = ((double)stored_recordFirst_diff / (double) first_diff);
168       if ( start_diff_percent < 0.99 )
169 	{
170 	  if ( start_diff_percent < 0.70 )
171 	    {
172 	      compensation_factor=0.5;
173 	    }
174 	  else if ( start_diff_percent < 0.80 )
175 	    {
176 	      compensation_factor=0.8;
177 	    }
178 	  else
179 	    {
180 	      compensation_factor=0.9;
181 	    }
182 	}
183       else if ( start_diff_percent > 1.01 )
184 	{
185 	  if ( start_diff_percent > 1.3 )
186 	    {
187 	      compensation_factor=1.5;
188 	    }
189 	  else if ( start_diff_percent > 1.2 )
190 	    {
191 	      compensation_factor=1.2;
192 	    }
193 	  else
194 	    {
195 	      compensation_factor=1.1;
196 	    }
197 	}
198       else
199 	{
200 	  compensation_factor=1.0;
201 	}
202     }
203   else
204     {
205       compensation_factor=1.0;
206     }
207   /* compensation_factor=1.0;       */
208 
209   sleep_amt= (record_last_diff*compensation_factor);
210 
211   if (sleep_amt > 5.0)
212     {
213       sleep_amt = sleep_amt - 1.0;
214     }
215 
216   stored_recordFirst_diff = recordFirst_diff;
217   return ( sleep_amt );
218 
219   /* printf ("\n\t%d  compensation: %f \n\n", record_last_diff, compensation_factor); */
220   return record_last_diff*compensation_factor;
221 
222   /* determine where we are from first read
223    * either too fast or too slow */
224   if (recordFirst_diff > first_diff)
225     {
226       out_of_wack=1;
227     }
228   else if (recordFirst_diff < first_diff)
229     {
230       out_of_wack=-1;
231     }
232   /* else we keep =0 */
233 
234 
235 
236   if ( out_of_wack==1 )
237     {
238 
239       xnee_verbose (( xd, "xnee_calc_sleep_amount: too fast\n" ));
240       /* too fast - we should slow down a bit */
241       if ( record_last_diff > last_diff )
242 	{
243 	  xnee_verbose (( xd, "xnee_calc_sleep_amount: too fast 1\n" ));
244 	  /* recorded wait more than we have waited so far */
245 
246 	  /* find amount that we are too fast or too slow */
247 	  out_of_wack_amt = recordFirst_diff - first_diff;
248 
249 	  /* if the amount we are out of wack is more than the recorded wait */
250 	  /* then sleep the full recorded difference */
251 	  if ( out_of_wack_amt > record_last_diff )
252 	    {
253 	      xnee_verbose (( xd, "xnee_calc_sleep_amount: 1.1\n" ));
254 	      //	      sleep_amt = record_last_diff;
255 	      sleep_amt = out_of_wack_amt ;
256 	    }
257 	  else
258 	    {
259 	      xnee_verbose (( xd, "xnee_calc_sleep_amount: 1.2\n" ));
260 	      /* otherwise sleep the amount out of wack */
261 	      sleep_amt = out_of_wack_amt;
262 	    }
263 	}
264       else
265 	{
266 	  xnee_verbose (( xd, "xnee_calc_sleep_amount: too fast 2 \n" ));
267 	  /* we have already waited the recorded amount of time */
268 	  /* but since we are still too fast -
269 	     sleep a percentage of recorded wait time */
270 	  tmp = (float)record_last_diff * XNEE_TOO_FAST_ADJ_PERCENTAGE/100;
271 	  sleep_amt = ( long ) tmp;
272 	}
273     }
274   else if ( out_of_wack == -1 )
275     {
276       xnee_verbose (( xd, "xnee_calc_sleep_amount: too slown" ));
277       if ( record_last_diff > last_diff )
278 	{
279 	  /* recorded wait more than we have waited so far */
280 	  /* amount of wait left */
281 	  sleep_amt = (record_last_diff - last_diff) / 8 ;
282 	}
283       else
284 	{
285 	  /* we have already waited the recorded amount of time */
286 	  sleep_amt = 0;
287 	}
288     }
289   else
290     {
291       xnee_verbose (( xd, "xnee_calc_sleep_amount: on time\n" ));
292       sleep_amt=2;
293     }
294 
295   xnee_verbose (( xd, "xnee_calc_sleep_amount: %d\n", (int)sleep_amt ));
296   return ( sleep_amt );
297 }
298 
299 
300 
301 
302 /**************************************************************
303  *                                                            *
304  * xnee_calc_sleep_amount                                     *
305  *                                                            *
306  *                                                            *
307  **************************************************************/
308 long
xnee_calc_sleep_amount_slow(xnee_data * xd,unsigned long last_diff,unsigned long first_diff,unsigned long record_last_diff,unsigned long recordFirst_diff)309 xnee_calc_sleep_amount_slow(xnee_data *xd,
310 			unsigned long  last_diff,
311 			unsigned long first_diff,
312 			unsigned long record_last_diff,
313 			unsigned long recordFirst_diff )
314 {
315   Time sleep_amt;
316   unsigned long out_of_wack_amt = 0;
317   int           out_of_wack     = 0;
318   float tmp;
319 
320 
321   recordFirst_diff =
322     recordFirst_diff * xnee_get_speed(xd) / 100;
323   record_last_diff =
324     record_last_diff * xnee_get_speed(xd) / 100;
325 
326   xnee_verbose ((xd, "xnee_calc_sleep_amount_slow last_diff: %lu first_diff: %lu record_last_diff: %lu recordFirst_diff: %lu\n",
327 		 last_diff, first_diff, record_last_diff, recordFirst_diff ));
328 /*   printf ("xnee_calc_sleep_amount last_diff: %lu first_diff: %lu record_last_diff: %lu recordFirst_diff: %lu\t",    */
329 /*  	  last_diff, first_diff, record_last_diff, recordFirst_diff );   */
330 
331 
332   /* determine where we are from first read
333    * either too fast or too slow */
334   if (recordFirst_diff > first_diff)
335     {
336       out_of_wack=1;
337     }
338   else if (recordFirst_diff < first_diff)
339     {
340       out_of_wack=-1;
341     }
342   /* else we keep =0 */
343 
344 
345 
346   if ( out_of_wack==1 )
347     {
348       /* too fast - we should slow down a bit */
349       if ( record_last_diff > last_diff )
350 	{
351 	  /* recorded wait more than we have waited so far */
352 
353 	  /* find amount that we are too fast or too slow */
354 	  out_of_wack_amt = recordFirst_diff - first_diff;
355 
356 	  /* if the amount we are out of wack is more than the recorded wait */
357 	  /* then sleep the full recorded difference */
358 	  if ( out_of_wack_amt > record_last_diff )
359 	    {
360 	      sleep_amt = record_last_diff;
361 	    }
362 	  else
363 	    {
364 	      /* otherwise sleep the amount out of wack */
365 	      sleep_amt = out_of_wack_amt;
366 	    }
367 	}
368       else
369 	{
370 	  /* we have already waited the recorded amount of time */
371 	  /* but since we are still too fast -
372 	     sleep a percentage of recorded wait time */
373 	  tmp = (float)record_last_diff * XNEE_TOO_FAST_ADJ_PERCENTAGE/100;
374 	  sleep_amt = ( long ) tmp;
375 	}
376     }
377   else if ( out_of_wack == -1 )
378     {
379       if ( record_last_diff > last_diff )
380 	{
381 	  /* recorded wait more than we have waited so far */
382 	  /* amount of wait left */
383 	    sleep_amt = (record_last_diff - last_diff) / 8  ;
384 	}
385       else
386 	{
387 	  /* we have already waited the recorded amount of time */
388 	    sleep_amt = 0;
389 	}
390     }
391   else
392     {
393       sleep_amt=0;
394     }
395 
396 /*   printf ("xnee_calc_sleep_amount: %d\n", (int)sleep_amt);  */
397   xnee_verbose (( xd, "xnee_calc_sleep_amount: %d\n", (int)sleep_amt ));
398 
399   return ( sleep_amt );
400 
401 }
402 
403 
404 
405 
406 
407 /**************************************************************
408  *                                                            *
409  * xnee_calc_sleep_amount                                     *
410  *                                                            *
411  *                                                            *
412  **************************************************************/
413 long
xnee_calc_sleep_amount_fast(xnee_data * xd,unsigned long last_diff,unsigned long first_diff,unsigned long record_last_diff,unsigned long recordFirst_diff)414 xnee_calc_sleep_amount_fast(xnee_data *xd,
415 			    unsigned long last_diff,
416 			    unsigned long first_diff,
417 			    unsigned long record_last_diff,
418 			    unsigned long recordFirst_diff )
419 {
420   Time sleep_amt;
421   unsigned long out_of_wack_amt = 0;
422   int           out_of_wack     = 0;
423 
424   recordFirst_diff =
425     recordFirst_diff * xnee_get_speed(xd) / 100;
426   record_last_diff =
427     record_last_diff * xnee_get_speed(xd) / 100;
428 
429 
430   /* determine where we are from first read
431    * either too fast or too slow */
432   if (recordFirst_diff > first_diff)
433     {
434       out_of_wack=1;
435     }
436   else if (recordFirst_diff < first_diff)
437     {
438       out_of_wack=-1;
439     }
440   /* else we keep =0 */
441 
442 
443 
444   if ( out_of_wack==1 )
445     {
446       /* too fast - we should slow down a bit */
447       if ( record_last_diff > last_diff )
448 	{
449 	  /* recorded wait more than we have waited so far */
450 
451 	  /* find amount that we are too fast or too slow */
452 	  out_of_wack_amt = recordFirst_diff - first_diff;
453 
454 	  /* if the amount we are out of wack is more than the
455 	   * recorded wait then sleep the full recorded difference */
456 	  if ( out_of_wack_amt > record_last_diff )
457 	    {
458 	      sleep_amt = record_last_diff ;
459 	    }
460 	  else
461 	    {
462 	      /* otherwise sleep the amount out of wack */
463 	      sleep_amt = out_of_wack_amt;
464 	    }
465 	}
466       else
467 	{
468 	  /* we have already waited the recorded amount of time */
469 	  /* but since we are still too fast -
470 	     sleep a percentage of recorded wait time */
471 	  sleep_amt = record_last_diff ;
472 	}
473     }
474   else if ( out_of_wack == -1 )
475     {
476 
477 
478       /* we have already waited the recorded amount of time */
479       sleep_amt = 10;
480     }
481   else
482     {
483       /* right on time */
484       sleep_amt=0;
485     }
486     xnee_verbose (( xd, "xnee_calc_sleep_amount: %d\n", (int)sleep_amt ));
487 
488   return ( sleep_amt );
489 }
490 
491 
492 
493 
494