/usr/share/pyshared/OpenGL/GLUT/special.py is in python-opengl 3.0.1-1.
This file is owned by root:root, with mode 0o644.
The actual contents of the file can be viewed below.
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 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 | """GLUT functions requiring special handling to provide Pythonic wrappers
Note:
GLUT callbacks are controlled by a flag in the platform module. The
GLUT_GUARD_CALLBACKS flag controls whether to wrap passed functions
with error-checking and context-validity checking code so that the
callbacks will only trigger if there is a valid context. This is done
so that systems such as Win32 will not continue running GLUT callbacks
after the system has exited.
Note:
This is not a problem with FreeGLUT on Linux, so Linux does not
add the extra overhead of the wrapper function.
Note:
This hack does *not* prevent hanging if there is no GLUT callback
being triggered. I.e. if you create a GLUT program that doesn't
explicitly call exit and doesn't call display or the like in a timer
then your app will hang on exit on Win32.
XXX the platform-specific stuff should be getting done in the
platform module *not* in the module here!
"""
from OpenGL.platform import GLUT, CurrentContextIsValid, GLUT_GUARD_CALLBACKS
from OpenGL import contextdata, error, platform, logs
from OpenGL.raw import GLUT as simple
import ctypes, os, sys, traceback
PLATFORM = platform.PLATFORM
FUNCTION_TYPE = simple.CALLBACK_FUNCTION_TYPE
log = logs.getLog( 'OpenGL.GLUT.special' )
if os.name == "nt":
log.info( """Using NT-specific GLUT calls with exit callbacks""" )
_exitfunctype = FUNCTION_TYPE( None, ctypes.c_int )
__glutInitWithExit = platform.createBaseFunction(
'__glutInitWithExit', dll=platform.GLUT, resultType=None,
argTypes=[ctypes.POINTER(ctypes.c_int),ctypes.POINTER(ctypes.c_char_p),_exitfunctype],
doc='glutInit( POINTER(c_int)(pargc), POINTER(STRING)(argv) ) -> None',
argNames=('pargc', 'argv'),
)
__glutCreateWindowWithExit = platform.createBaseFunction(
'__glutCreateWindowWithExit', dll=platform.GLUT, resultType=ctypes.c_int,
argTypes=[ctypes.c_char_p,_exitfunctype],
doc='glutCreateWindow( STRING(title) ) -> c_int',
argNames=('title',),
)
__glutCreateMenuWithExit = platform.createBaseFunction(
'__glutCreateMenuWithExit', dll=platform.GLUT, resultType=ctypes.c_int,
argTypes=[FUNCTION_TYPE(None, ctypes.c_int),_exitfunctype],
doc='glutCreateMenu( FUNCTION_TYPE(None, c_int)(callback) ) -> c_int',
argNames=('callback',),
)
else:
# Linux, OSX, etceteras
__glutInitWithExit = None
if __glutInitWithExit:
# Normal platforms + Win32 w/ FreeGLUT (SF#2813722)
import sys
_exitfunc = _exitfunctype(sys.exit)
def _base_glutInit(pargc, argv):
"""Overrides base glut init with exit-function-aware version"""
return __glutInitWithExit(pargc, argv, _exitfunc)
def glutCreateWindow(title):
"""Create window with given title
This is the Win32-specific version that handles
registration of an exit-function handler
"""
return __glutCreateWindowWithExit(title, _exitfunc)
def glutCreateMenu(callback):
"""Create menu with given callback
This is the Win32-specific version that handles
registration of an exit-function callback.
"""
return __glutCreateMenuWithExit(callback, _exitfunc)
else:
_base_glutInit = getattr(GLUT, 'glutInit', None)
##_base_glutDisplayFunc = GLUT.glutDisplayFunc
##_base_glutIdleFunc = GLUT.glutIdleFunc
##_base_glutEntryFunc = GLUT.glutEntryFunc
##_base_glutReshapeFunc = GLUT.glutReshapeFunc
_base_glutDestroyWindow = getattr(GLUT, 'glutDestroyWindow', None)
class GLUTCallback( object ):
"""Class implementing GLUT Callback registration functions"""
def __init__( self, typeName, parameterTypes, parameterNames ):
"""Initialise the glut callback instance"""
self.typeName = typeName
def describe( typ, name ):
return '(int) %s'%(name)
self.__doc__ = """Specify handler for GLUT %r events
def handler( %s ):
return None"""%( typeName, ", ".join([
describe( typ,name )
for (typ,name) in zip( parameterTypes, parameterNames )
]))
try:
self.wrappedOperation = getattr( GLUT, 'glut%sFunc'%(typeName) )
except AttributeError, err:
def failFunction( *args, **named ):
from OpenGL import error
raise error.NullFunctionError(
"""Undefined GLUT callback function %s, check for bool(%s) before calling"""%(
typeName, 'glut%sFunc'%(typeName),
)
)
self.wrappedOperation = failFunction
self.callbackType = FUNCTION_TYPE( None, *parameterTypes )
self.CONTEXT_DATA_KEY = 'glut%sFunc'%(typeName, )
argNames = ('function',)
def __call__( self, function, *args ):
if GLUT_GUARD_CALLBACKS and hasattr( function,'__call__' ):
def safeCall( *args, **named ):
"""Safe calling of GUI callbacks, exits on failures"""
try:
if not CurrentContextIsValid():
raise RuntimeError( """No valid context!""" )
return function( *args, **named )
except Exception, err:
traceback.print_exc()
sys.stderr.write( """GLUT %s callback %s with %s,%s failed: returning None %s\n"""%(
self.typeName, function, args, named, err,
))
os._exit(1)
#return None
finalFunction = safeCall
else:
finalFunction = function
if hasattr( finalFunction,'__call__' ):
cCallback = self.callbackType( finalFunction )
else:
cCallback = function
# keep the function alive as long as the cCallback is...
#cCallback.function = function
contextdata.setValue( self.CONTEXT_DATA_KEY, cCallback )
self.wrappedOperation( cCallback, *args )
return cCallback
class GLUTTimerCallback( GLUTCallback ):
"""GLUT timer callbacks (completely nonstandard wrt other GLUT callbacks)"""
def __call__( self, milliseconds, function, value ):
cCallback = self.callbackType( function )
# timers should de-register as soon as they are called...
# Note: there's no good key to use! we want to allow for
# multiple instances of the same function with the same value
# which means we have nothing that can store it properly...
callbacks = contextdata.getValue( self.CONTEXT_DATA_KEY )
if callbacks is None:
callbacks = []
contextdata.setValue( self.CONTEXT_DATA_KEY, callbacks )
def deregister( value ):
try:
function( value )
finally:
for item in callbacks:
if item.function is deregister:
callbacks.remove( item )
item.function = None
break
if not callbacks:
contextdata.delValue( self.CONTEXT_DATA_KEY )
cCallback = self.callbackType( deregister )
cCallback.function = deregister
callbacks.append( cCallback )
self.wrappedOperation( milliseconds, cCallback, value )
return cCallback
class GLUTMenuCallback( object ):
"""Place to collect the GLUT Menu manipulation special code"""
callbackType = FUNCTION_TYPE( ctypes.c_int, ctypes.c_int )
def glutCreateMenu( cls, func ):
"""Create a new (current) menu, return small integer identifier
func( int ) -- Function taking a single integer reflecting
the user's choice, the value passed to glutAddMenuEntry
return menuID (small integer)
"""
cCallback = cls.callbackType( func )
menu = simple.glutCreateMenu( cCallback )
contextdata.setValue( ('menucallback',menu), (cCallback,func) )
return menu
glutCreateMenu.argNames = [ 'func' ]
glutCreateMenu = classmethod( glutCreateMenu )
def glutDestroyMenu( cls, menu ):
"""Destroy (cleanup) the given menu
Deregister's the interal pointer to the menu callback
returns None
"""
result = simple.glutDestroyMenu( menu )
contextdata.delValue( ('menucallback',menu) )
return result
glutDestroyMenu.argNames = [ 'menu' ]
glutDestroyMenu = classmethod( glutDestroyMenu )
glutCreateMenu = GLUTMenuCallback.glutCreateMenu
#glutCreateMenu.wrappedOperation = simple.glutCreateMenu
glutDestroyMenu = GLUTMenuCallback.glutDestroyMenu
#glutDestroyMenu.wrappedOperation = simple.glutDestroyMenu
glutButtonBoxFunc = GLUTCallback(
'ButtonBox', (ctypes.c_int,ctypes.c_int), ('button','state'),
)
glutDialsFunc = GLUTCallback(
'Dials', (ctypes.c_int,ctypes.c_int), ('dial','value'),
)
glutDisplayFunc = GLUTCallback(
'Display', (), (),
)
glutEntryFunc = GLUTCallback(
'Entry', (ctypes.c_int,), ('state',),
)
glutIdleFunc = GLUTCallback(
'Idle', (), (),
)
glutJoystickFunc = GLUTCallback(
'Joystick', (ctypes.c_uint,ctypes.c_int,ctypes.c_int,ctypes.c_int), ('buttonMask','x','y','z'),
)
glutKeyboardFunc = GLUTCallback(
'Keyboard', (ctypes.c_char,ctypes.c_int,ctypes.c_int), ('key','x','y'),
)
glutKeyboardUpFunc = GLUTCallback(
'KeyboardUp', (ctypes.c_char,ctypes.c_int,ctypes.c_int), ('key','x','y'),
)
glutMenuStatusFunc = GLUTCallback(
'MenuStatus', (ctypes.c_int,ctypes.c_int,ctypes.c_int), ('status','x','y'),
)
glutMenuStateFunc = GLUTCallback(
'MenuState', (ctypes.c_int,), ('status',),
)
glutMotionFunc = GLUTCallback(
'Motion', (ctypes.c_int,ctypes.c_int), ('x','y'),
)
glutMouseFunc = GLUTCallback(
'Mouse', (ctypes.c_int,ctypes.c_int,ctypes.c_int,ctypes.c_int), ('button','state','x','y'),
)
glutOverlayDisplayFunc = GLUTCallback(
'OverlayDisplay', (), (),
)
glutPassiveMotionFunc = GLUTCallback(
'PassiveMotion', (ctypes.c_int,ctypes.c_int), ('x','y'),
)
glutReshapeFunc = GLUTCallback(
'Reshape', (ctypes.c_int,ctypes.c_int), ('width','height'),
)
glutSpaceballButtonFunc = GLUTCallback(
'SpaceballButton', (ctypes.c_int,ctypes.c_int), ('button','state'),
)
glutSpaceballMotionFunc = GLUTCallback(
'SpaceballMotion', (ctypes.c_int,ctypes.c_int,ctypes.c_int), ('x','y','z'),
)
glutSpaceballRotateFunc = GLUTCallback(
'SpaceballRotate', (ctypes.c_int,ctypes.c_int,ctypes.c_int), ('x','y','z'),
)
glutSpecialFunc = GLUTCallback(
'Special', (ctypes.c_int,ctypes.c_int,ctypes.c_int), ('key','x','y'),
)
glutSpecialUpFunc = GLUTCallback(
'SpecialUp', (ctypes.c_int,ctypes.c_int,ctypes.c_int), ('key','x','y'),
)
glutTabletButtonFunc = GLUTCallback(
'TabletButton', (ctypes.c_int,ctypes.c_int,ctypes.c_int,ctypes.c_int), ('button','state','x','y',),
)
glutTabletButtonFunc = GLUTCallback(
'TabletButton', (ctypes.c_int,ctypes.c_int,ctypes.c_int,ctypes.c_int), ('button','state','x','y',),
)
glutTabletMotionFunc = GLUTCallback(
'TabletMotion', (ctypes.c_int,ctypes.c_int), ('x','y',),
)
glutVisibilityFunc = GLUTCallback(
'Visibility', (ctypes.c_int,), ('state',),
)
glutWindowStatusFunc = GLUTCallback(
'WindowStatus', (ctypes.c_int,), ('state',),
)
# glutTimerFunc is unlike any other GLUT callback-registration...
glutTimerFunc = GLUTTimerCallback(
'Timer', (ctypes.c_int,), ('value',),
)
INITIALIZED = False
def glutInit( *args ):
"""Initialise the GLUT library"""
global INITIALIZED
if INITIALIZED:
return args
INITIALIZED = True
if args:
arg,args = args[0],args[1:]
count = None
if isinstance(arg, (int,long)):
# raw API style, (count, values)
count = arg
if count != len(args):
raise ValueError( """Specified count of %s does not match length (%s) of argument list %s"""%(
count, len(args), args,
))
elif isinstance( arg, (str,unicode)):
# passing in a sequence of strings as individual arguments
args = (arg,)+args
count = len(args)
else:
args = arg
count = len(args)
else:
count=0
args = []
args = [str(x) for x in args]
if not count:
count, args = 1, ['foo']
holder = (ctypes.c_char_p * len(args))()
for i,arg in enumerate(args):
holder[i] = arg
count = ctypes.c_int( count )
import os
currentDirectory = os.getcwd()
try:
# XXX need to check for error condition here...
_base_glutInit( ctypes.byref(count), holder )
finally:
os.chdir( currentDirectory )
return [
str(holder[i]) for i in range( count.value )
]
glutInit.wrappedOperation = simple.glutInit
def glutDestroyWindow( window ):
"""Want to destroy the window, we need to do some cleanup..."""
context = 0
try:
GLUT.glutSetWindow(window)
context = contextdata.getContext()
result = contextdata.cleanupContext( context )
log.info( """Cleaning up context data for window %s: %s""", window, result )
except Exception, err:
log.error( """Error attempting to clean up context data for GLUT window %s: %s""", window, result )
return _base_glutDestroyWindow( window )
glutDestroyWindow.wrappedOperation = simple.glutDestroyWindow
|