##// END OF EJS Templates
Remove 5s wait on inactivity on GUI inputhook loops...
Jonah Graham -
Show More
@@ -1,175 +1,172 b''
1 1 # coding: utf-8
2 2 """
3 3 GLUT Inputhook support functions
4 4 """
5 5
6 6 #-----------------------------------------------------------------------------
7 7 # Copyright (C) 2008-2011 The IPython Development Team
8 8 #
9 9 # Distributed under the terms of the BSD License. The full license is in
10 10 # the file COPYING, distributed as part of this software.
11 11 #-----------------------------------------------------------------------------
12 12
13 13 # GLUT is quite an old library and it is difficult to ensure proper
14 14 # integration within IPython since original GLUT does not allow to handle
15 15 # events one by one. Instead, it requires for the mainloop to be entered
16 16 # and never returned (there is not even a function to exit he
17 17 # mainloop). Fortunately, there are alternatives such as freeglut
18 18 # (available for linux and windows) and the OSX implementation gives
19 19 # access to a glutCheckLoop() function that blocks itself until a new
20 20 # event is received. This means we have to setup the idle callback to
21 21 # ensure we got at least one event that will unblock the function.
22 22 #
23 23 # Furthermore, it is not possible to install these handlers without a window
24 24 # being first created. We choose to make this window invisible. This means that
25 25 # display mode options are set at this level and user won't be able to change
26 26 # them later without modifying the code. This should probably be made available
27 27 # via IPython options system.
28 28
29 29 #-----------------------------------------------------------------------------
30 30 # Imports
31 31 #-----------------------------------------------------------------------------
32 32 import os
33 33 import sys
34 34 import time
35 35 import signal
36 36 import OpenGL.GLUT as glut
37 37 import OpenGL.platform as platform
38 38 from timeit import default_timer as clock
39 39
40 40 #-----------------------------------------------------------------------------
41 41 # Constants
42 42 #-----------------------------------------------------------------------------
43 43
44 44 # Frame per second : 60
45 45 # Should probably be an IPython option
46 46 glut_fps = 60
47 47
48 48
49 49 # Display mode : double buffeed + rgba + depth
50 50 # Should probably be an IPython option
51 51 glut_display_mode = (glut.GLUT_DOUBLE |
52 52 glut.GLUT_RGBA |
53 53 glut.GLUT_DEPTH)
54 54
55 55 glutMainLoopEvent = None
56 56 if sys.platform == 'darwin':
57 57 try:
58 58 glutCheckLoop = platform.createBaseFunction(
59 59 'glutCheckLoop', dll=platform.GLUT, resultType=None,
60 60 argTypes=[],
61 61 doc='glutCheckLoop( ) -> None',
62 62 argNames=(),
63 63 )
64 64 except AttributeError:
65 65 raise RuntimeError(
66 66 '''Your glut implementation does not allow interactive sessions'''
67 67 '''Consider installing freeglut.''')
68 68 glutMainLoopEvent = glutCheckLoop
69 69 elif glut.HAVE_FREEGLUT:
70 70 glutMainLoopEvent = glut.glutMainLoopEvent
71 71 else:
72 72 raise RuntimeError(
73 73 '''Your glut implementation does not allow interactive sessions. '''
74 74 '''Consider installing freeglut.''')
75 75
76 76
77 77 #-----------------------------------------------------------------------------
78 78 # Platform-dependent imports and functions
79 79 #-----------------------------------------------------------------------------
80 80
81 81 if os.name == 'posix':
82 82 import select
83 83
84 84 def stdin_ready():
85 85 infds, outfds, erfds = select.select([sys.stdin],[],[],0)
86 86 if infds:
87 87 return True
88 88 else:
89 89 return False
90 90
91 91 elif sys.platform == 'win32':
92 92 import msvcrt
93 93
94 94 def stdin_ready():
95 95 return msvcrt.kbhit()
96 96
97 97 #-----------------------------------------------------------------------------
98 98 # Callback functions
99 99 #-----------------------------------------------------------------------------
100 100
101 101 def glut_display():
102 102 # Dummy display function
103 103 pass
104 104
105 105 def glut_idle():
106 106 # Dummy idle function
107 107 pass
108 108
109 109 def glut_close():
110 110 # Close function only hides the current window
111 111 glut.glutHideWindow()
112 112 glutMainLoopEvent()
113 113
114 114 def glut_int_handler(signum, frame):
115 115 # Catch sigint and print the defautl message
116 116 signal.signal(signal.SIGINT, signal.default_int_handler)
117 117 print '\nKeyboardInterrupt'
118 118 # Need to reprint the prompt at this stage
119 119
120 120
121 121
122 122 #-----------------------------------------------------------------------------
123 123 # Code
124 124 #-----------------------------------------------------------------------------
125 125 def inputhook_glut():
126 126 """Run the pyglet event loop by processing pending events only.
127 127
128 128 This keeps processing pending events until stdin is ready. After
129 129 processing all pending events, a call to time.sleep is inserted. This is
130 130 needed, otherwise, CPU usage is at 100%. This sleep time should be tuned
131 131 though for best performance.
132 132 """
133 133 # We need to protect against a user pressing Control-C when IPython is
134 134 # idle and this is running. We trap KeyboardInterrupt and pass.
135 135
136 136 signal.signal(signal.SIGINT, glut_int_handler)
137 137
138 138 try:
139 139 t = clock()
140 140
141 141 # Make sure the default window is set after a window has been closed
142 142 if glut.glutGetWindow() == 0:
143 143 glut.glutSetWindow( 1 )
144 144 glutMainLoopEvent()
145 145 return 0
146 146
147 147 while not stdin_ready():
148 148 glutMainLoopEvent()
149 149 # We need to sleep at this point to keep the idle CPU load
150 150 # low. However, if sleep to long, GUI response is poor. As
151 151 # a compromise, we watch how often GUI events are being processed
152 152 # and switch between a short and long sleep time. Here are some
153 153 # stats useful in helping to tune this.
154 154 # time CPU load
155 155 # 0.001 13%
156 156 # 0.005 3%
157 157 # 0.01 1.5%
158 158 # 0.05 0.5%
159 159 used_time = clock() - t
160 if used_time > 5*60.0:
161 # print 'Sleep for 5 s' # dbg
162 time.sleep(5.0)
163 elif used_time > 10.0:
160 if used_time > 10.0:
164 161 # print 'Sleep for 1 s' # dbg
165 162 time.sleep(1.0)
166 163 elif used_time > 0.1:
167 164 # Few GUI events coming in, so we can sleep longer
168 165 # print 'Sleep for 0.05 s' # dbg
169 166 time.sleep(0.05)
170 167 else:
171 168 # Many GUI events coming in, so sleep only very little
172 169 time.sleep(0.001)
173 170 except KeyboardInterrupt:
174 171 pass
175 172 return 0
@@ -1,114 +1,111 b''
1 1 # encoding: utf-8
2 2 """
3 3 Enable pyglet to be used interacive by setting PyOS_InputHook.
4 4
5 5 Authors
6 6 -------
7 7
8 8 * Nicolas P. Rougier
9 9 * Fernando Perez
10 10 """
11 11
12 12 #-----------------------------------------------------------------------------
13 13 # Copyright (C) 2008-2011 The IPython Development Team
14 14 #
15 15 # Distributed under the terms of the BSD License. The full license is in
16 16 # the file COPYING, distributed as part of this software.
17 17 #-----------------------------------------------------------------------------
18 18
19 19 #-----------------------------------------------------------------------------
20 20 # Imports
21 21 #-----------------------------------------------------------------------------
22 22
23 23 import os
24 24 import sys
25 25 import time
26 26 from timeit import default_timer as clock
27 27 import pyglet
28 28
29 29 #-----------------------------------------------------------------------------
30 30 # Platform-dependent imports and functions
31 31 #-----------------------------------------------------------------------------
32 32
33 33 if os.name == 'posix':
34 34 import select
35 35
36 36 def stdin_ready():
37 37 infds, outfds, erfds = select.select([sys.stdin],[],[],0)
38 38 if infds:
39 39 return True
40 40 else:
41 41 return False
42 42
43 43 elif sys.platform == 'win32':
44 44 import msvcrt
45 45
46 46 def stdin_ready():
47 47 return msvcrt.kbhit()
48 48
49 49
50 50 # On linux only, window.flip() has a bug that causes an AttributeError on
51 51 # window close. For details, see:
52 52 # http://groups.google.com/group/pyglet-users/browse_thread/thread/47c1aab9aa4a3d23/c22f9e819826799e?#c22f9e819826799e
53 53
54 54 if sys.platform.startswith('linux'):
55 55 def flip(window):
56 56 try:
57 57 window.flip()
58 58 except AttributeError:
59 59 pass
60 60 else:
61 61 def flip(window):
62 62 window.flip()
63 63
64 64 #-----------------------------------------------------------------------------
65 65 # Code
66 66 #-----------------------------------------------------------------------------
67 67
68 68 def inputhook_pyglet():
69 69 """Run the pyglet event loop by processing pending events only.
70 70
71 71 This keeps processing pending events until stdin is ready. After
72 72 processing all pending events, a call to time.sleep is inserted. This is
73 73 needed, otherwise, CPU usage is at 100%. This sleep time should be tuned
74 74 though for best performance.
75 75 """
76 76 # We need to protect against a user pressing Control-C when IPython is
77 77 # idle and this is running. We trap KeyboardInterrupt and pass.
78 78 try:
79 79 t = clock()
80 80 while not stdin_ready():
81 81 pyglet.clock.tick()
82 82 for window in pyglet.app.windows:
83 83 window.switch_to()
84 84 window.dispatch_events()
85 85 window.dispatch_event('on_draw')
86 86 flip(window)
87 87
88 88 # We need to sleep at this point to keep the idle CPU load
89 89 # low. However, if sleep to long, GUI response is poor. As
90 90 # a compromise, we watch how often GUI events are being processed
91 91 # and switch between a short and long sleep time. Here are some
92 92 # stats useful in helping to tune this.
93 93 # time CPU load
94 94 # 0.001 13%
95 95 # 0.005 3%
96 96 # 0.01 1.5%
97 97 # 0.05 0.5%
98 98 used_time = clock() - t
99 if used_time > 5*60.0:
100 # print 'Sleep for 5 s' # dbg
101 time.sleep(5.0)
102 elif used_time > 10.0:
99 if used_time > 10.0:
103 100 # print 'Sleep for 1 s' # dbg
104 101 time.sleep(1.0)
105 102 elif used_time > 0.1:
106 103 # Few GUI events coming in, so we can sleep longer
107 104 # print 'Sleep for 0.05 s' # dbg
108 105 time.sleep(0.05)
109 106 else:
110 107 # Many GUI events coming in, so sleep only very little
111 108 time.sleep(0.001)
112 109 except KeyboardInterrupt:
113 110 pass
114 111 return 0
@@ -1,170 +1,167 b''
1 1 # encoding: utf-8
2 2
3 3 """
4 4 Enable wxPython to be used interacive by setting PyOS_InputHook.
5 5
6 6 Authors: Robin Dunn, Brian Granger, Ondrej Certik
7 7 """
8 8
9 9 #-----------------------------------------------------------------------------
10 10 # Copyright (C) 2008-2011 The IPython Development Team
11 11 #
12 12 # Distributed under the terms of the BSD License. The full license is in
13 13 # the file COPYING, distributed as part of this software.
14 14 #-----------------------------------------------------------------------------
15 15
16 16 #-----------------------------------------------------------------------------
17 17 # Imports
18 18 #-----------------------------------------------------------------------------
19 19
20 20 import sys
21 21 import signal
22 22 import time
23 23 from timeit import default_timer as clock
24 24 import wx
25 25
26 26 from IPython.lib.inputhook import stdin_ready
27 27
28 28
29 29 #-----------------------------------------------------------------------------
30 30 # Code
31 31 #-----------------------------------------------------------------------------
32 32
33 33 def inputhook_wx1():
34 34 """Run the wx event loop by processing pending events only.
35 35
36 36 This approach seems to work, but its performance is not great as it
37 37 relies on having PyOS_InputHook called regularly.
38 38 """
39 39 try:
40 40 app = wx.GetApp()
41 41 if app is not None:
42 42 assert wx.Thread_IsMain()
43 43
44 44 # Make a temporary event loop and process system events until
45 45 # there are no more waiting, then allow idle events (which
46 46 # will also deal with pending or posted wx events.)
47 47 evtloop = wx.EventLoop()
48 48 ea = wx.EventLoopActivator(evtloop)
49 49 while evtloop.Pending():
50 50 evtloop.Dispatch()
51 51 app.ProcessIdle()
52 52 del ea
53 53 except KeyboardInterrupt:
54 54 pass
55 55 return 0
56 56
57 57 class EventLoopTimer(wx.Timer):
58 58
59 59 def __init__(self, func):
60 60 self.func = func
61 61 wx.Timer.__init__(self)
62 62
63 63 def Notify(self):
64 64 self.func()
65 65
66 66 class EventLoopRunner(object):
67 67
68 68 def Run(self, time):
69 69 self.evtloop = wx.EventLoop()
70 70 self.timer = EventLoopTimer(self.check_stdin)
71 71 self.timer.Start(time)
72 72 self.evtloop.Run()
73 73
74 74 def check_stdin(self):
75 75 if stdin_ready():
76 76 self.timer.Stop()
77 77 self.evtloop.Exit()
78 78
79 79 def inputhook_wx2():
80 80 """Run the wx event loop, polling for stdin.
81 81
82 82 This version runs the wx eventloop for an undetermined amount of time,
83 83 during which it periodically checks to see if anything is ready on
84 84 stdin. If anything is ready on stdin, the event loop exits.
85 85
86 86 The argument to elr.Run controls how often the event loop looks at stdin.
87 87 This determines the responsiveness at the keyboard. A setting of 1000
88 88 enables a user to type at most 1 char per second. I have found that a
89 89 setting of 10 gives good keyboard response. We can shorten it further,
90 90 but eventually performance would suffer from calling select/kbhit too
91 91 often.
92 92 """
93 93 try:
94 94 app = wx.GetApp()
95 95 if app is not None:
96 96 assert wx.Thread_IsMain()
97 97 elr = EventLoopRunner()
98 98 # As this time is made shorter, keyboard response improves, but idle
99 99 # CPU load goes up. 10 ms seems like a good compromise.
100 100 elr.Run(time=10) # CHANGE time here to control polling interval
101 101 except KeyboardInterrupt:
102 102 pass
103 103 return 0
104 104
105 105 def inputhook_wx3():
106 106 """Run the wx event loop by processing pending events only.
107 107
108 108 This is like inputhook_wx1, but it keeps processing pending events
109 109 until stdin is ready. After processing all pending events, a call to
110 110 time.sleep is inserted. This is needed, otherwise, CPU usage is at 100%.
111 111 This sleep time should be tuned though for best performance.
112 112 """
113 113 # We need to protect against a user pressing Control-C when IPython is
114 114 # idle and this is running. We trap KeyboardInterrupt and pass.
115 115 try:
116 116 app = wx.GetApp()
117 117 if app is not None:
118 118 assert wx.Thread_IsMain()
119 119
120 120 # The import of wx on Linux sets the handler for signal.SIGINT
121 121 # to 0. This is a bug in wx or gtk. We fix by just setting it
122 122 # back to the Python default.
123 123 if not callable(signal.getsignal(signal.SIGINT)):
124 124 signal.signal(signal.SIGINT, signal.default_int_handler)
125 125
126 126 evtloop = wx.EventLoop()
127 127 ea = wx.EventLoopActivator(evtloop)
128 128 t = clock()
129 129 while not stdin_ready():
130 130 while evtloop.Pending():
131 131 t = clock()
132 132 evtloop.Dispatch()
133 133 app.ProcessIdle()
134 134 # We need to sleep at this point to keep the idle CPU load
135 135 # low. However, if sleep to long, GUI response is poor. As
136 136 # a compromise, we watch how often GUI events are being processed
137 137 # and switch between a short and long sleep time. Here are some
138 138 # stats useful in helping to tune this.
139 139 # time CPU load
140 140 # 0.001 13%
141 141 # 0.005 3%
142 142 # 0.01 1.5%
143 143 # 0.05 0.5%
144 144 used_time = clock() - t
145 if used_time > 5*60.0:
146 # print 'Sleep for 5 s' # dbg
147 time.sleep(5.0)
148 elif used_time > 10.0:
145 if used_time > 10.0:
149 146 # print 'Sleep for 1 s' # dbg
150 147 time.sleep(1.0)
151 148 elif used_time > 0.1:
152 149 # Few GUI events coming in, so we can sleep longer
153 150 # print 'Sleep for 0.05 s' # dbg
154 151 time.sleep(0.05)
155 152 else:
156 153 # Many GUI events coming in, so sleep only very little
157 154 time.sleep(0.001)
158 155 del ea
159 156 except KeyboardInterrupt:
160 157 pass
161 158 return 0
162 159
163 160 if sys.platform == 'darwin':
164 161 # On OSX, evtloop.Pending() always returns True, regardless of there being
165 162 # any events pending. As such we can't use implementations 1 or 3 of the
166 163 # inputhook as those depend on a pending/dispatch loop.
167 164 inputhook_wx = inputhook_wx2
168 165 else:
169 166 # This is our default implementation
170 167 inputhook_wx = inputhook_wx3
General Comments 0
You need to be logged in to leave comments. Login now