~macslow/notify-osd/mouse-movement-monitor

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
#include <stdlib.h>
#include <glib.h>
#include <egg/egg-hack.h>

/* We ask for 1 frame per millisecond.
 * Whenever this rate can't be achieved then the timeline
 * will interpolate the number frames that should have
 * passed between timeouts. */
#define TEST_TIMELINE_FPS 1000
#define TEST_TIMELINE_FRAME_COUNT 5000

/* We are at the mercy of the system scheduler so this
 * may not be a very reliable tolerance. */
#define TEST_ERROR_TOLERANCE 20

typedef struct _TestState {
    EggTimeline *timeline;
    GTimeVal start_time;
    guint new_frame_counter;
    gint expected_frame;
    gint completion_count;
    gboolean passed;
}TestState;


static void
new_frame_cb (EggTimeline *timeline,
              gint frame_num,
	      TestState *state)
{
  GTimeVal current_time;
  gint current_frame;
  glong msec_diff;
  gint loop_overflow = 0;
  static gint step = 1;
  
  g_get_current_time (&current_time);

  current_frame = egg_timeline_get_current_frame (state->timeline);
  
  msec_diff = (current_time.tv_sec - state->start_time.tv_sec) * 1000;
  msec_diff += (current_time.tv_usec - state->start_time.tv_usec)/1000;
  
  /* If we expect to have interpolated past the end of the timeline
   * we keep track of the overflow so we can determine when
   * the next timeout will happen. We then clip expected_frames
   * to TEST_TIMELINE_FRAME_COUNT since egg-timeline
   * semantics guaranty this frame is always signaled before
   * looping */
  if (state->expected_frame > TEST_TIMELINE_FRAME_COUNT)
    {
	loop_overflow = state->expected_frame - TEST_TIMELINE_FRAME_COUNT;
	state->expected_frame = TEST_TIMELINE_FRAME_COUNT;
    }

  if (current_frame >= (state->expected_frame-TEST_ERROR_TOLERANCE)
      && current_frame <= (state->expected_frame+TEST_ERROR_TOLERANCE))
    {
      g_print ("\nelapsed milliseconds=%-5li expected frame=%-4i actual frame=%-4i (OK)\n",
              msec_diff,
              state->expected_frame,
              current_frame);
    }
  else
    {
      g_print ("\nelapsed milliseconds=%-5li expected frame=%-4i actual frame=%-4i (FAILED)\n",
              msec_diff,
              state->expected_frame,
              current_frame);
      state->passed = FALSE;
    }
    
  if (step>0)
    {
      state->expected_frame = current_frame + (TEST_TIMELINE_FPS / 4);
      g_print ("Sleeping for 250ms so next frame should be (%i + %i) = %i\n",
             current_frame, (TEST_TIMELINE_FPS / 4), state->expected_frame);
      g_usleep (250000);
    }
  else
    {
      state->expected_frame = current_frame + TEST_TIMELINE_FPS;
      g_print ("Sleeping for 1sec so next frame should be (%i + %i) = %i\n",
             current_frame, TEST_TIMELINE_FPS, state->expected_frame);
      g_usleep (1000000);
    }
  
  if (current_frame >= TEST_TIMELINE_FRAME_COUNT)
    {
      state->expected_frame += loop_overflow;
      state->expected_frame -= TEST_TIMELINE_FRAME_COUNT;
      g_print ("End of timeline reached: Wrapping expected frame too %i\n",
	       state->expected_frame);
    }

  state->new_frame_counter++;
  step = -step;
}


static void
completed_cb (EggTimeline *timeline,
              TestState *state)
{
    state->completion_count++;

    if (state->completion_count == 2)
      {
	  if (state->passed)
	    {
	      g_print("Passed\n");
	      exit(EXIT_SUCCESS);
	    }
	  else
	    {
	      g_print("Failed\n");
	      exit(EXIT_FAILURE);
	    }
      }
}


int
main (int argc, char **argv)
{
  TestState state;

  egg_init (&argc, &argv);

  state.timeline = 
    egg_timeline_new (TEST_TIMELINE_FRAME_COUNT,
                          TEST_TIMELINE_FPS);
  egg_timeline_set_loop (state.timeline, TRUE);
  g_signal_connect (G_OBJECT(state.timeline),
                    "new-frame",
                    G_CALLBACK(new_frame_cb),
                    &state);
  g_signal_connect (G_OBJECT(state.timeline),
                    "completed",
                    G_CALLBACK(completed_cb),
                    &state);

  state.completion_count = 0;
  state.new_frame_counter = 0;
  state.passed = TRUE;
  state.expected_frame = 0;

  g_get_current_time (&state.start_time);
  egg_timeline_start (state.timeline);

  egg_main();

  return EXIT_FAILURE;
}