CarbonEvtsupport.py 9.87 KB
Newer Older
1 2 3 4
# IBCarbonsupport.py

from macsupport import *

5
from CarbonEvtscan import RefObjectTypes
6 7 8 9 10 11 12 13

# where should this go? macsupport.py?
CFStringRef = OpaqueByValueType('CFStringRef')

for typ in RefObjectTypes:
	execstr = "%(name)s = OpaqueByValueType('%(name)s')" % {"name": typ}
	exec execstr

14

15 16 17
if 0:
	# these types will have no methods and will merely be opaque blobs
	# should write getattr and setattr for them?
18

19 20 21 22 23
	StructObjectTypes = ["EventTypeSpec",
						"HIPoint",
						"HICommand",
						"EventHotKeyID",
						]
24

25 26 27
	for typ in StructObjectTypes:
		execstr = "%(name)s = OpaqueType('%(name)s')" % {"name": typ}
		exec execstr
28

29
EventHotKeyID = OpaqueByValueType("EventHotKeyID", "EventHotKeyID")
30
EventTypeSpec_ptr = OpaqueType("EventTypeSpec", "EventTypeSpec")
31 32 33 34 35 36

# is this the right type for the void * in GetEventParameter
#void_ptr = FixedInputBufferType(1024)
void_ptr = stringptr
# here are some types that are really other types

37 38 39 40 41 42
class MyVarInputBufferType(VarInputBufferType):
	def passInput(self, name):
		return "%s__len__, %s__in__" % (name, name)

MyInBuffer = MyVarInputBufferType('char', 'long', 'l')		# (buf, len)

43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62
EventTime = double
EventTimeout = EventTime
EventTimerInterval = EventTime
EventAttributes = UInt32
EventParamName = OSType
EventParamType = OSType
EventPriority = SInt16
EventMask = UInt16

EventComparatorUPP = FakeType("(EventComparatorUPP)0")
EventLoopTimerUPP = FakeType("(EventLoopTimerUPP)0")
EventHandlerUPP = FakeType("(EventHandlerUPP)0")
EventHandlerUPP = FakeType("(EventHandlerUPP)0")
EventComparatorProcPtr = FakeType("(EventComparatorProcPtr)0")
EventLoopTimerProcPtr = FakeType("(EventLoopTimerProcPtr)0")
EventHandlerProcPtr = FakeType("(EventHandlerProcPtr)0")

CarbonEventsFunction = OSErrFunctionGenerator
CarbonEventsMethod = OSErrMethodGenerator

63 64 65 66 67 68 69 70
class EventHandlerRefMethod(OSErrMethodGenerator):
	def precheck(self):
		OutLbrace('if (_self->ob_itself == NULL)')
		Output('PyErr_SetString(CarbonEvents_Error, "Handler has been removed");')
		Output('return NULL;')
		OutRbrace()


71 72 73 74 75
RgnHandle = OpaqueByValueType("RgnHandle", "ResObj")
GrafPtr = OpaqueByValueType("GrafPtr", "GrafObj")
MouseTrackingResult = UInt16


76
includestuff = r"""
77 78 79
#ifdef WITHOUT_FRAMEWORKS
#include <CarbonEvents.h>
#else
80
#include <Carbon/Carbon.h>
81 82
#endif

83 84
#include "macglue.h"

85 86
/* Macro to test whether a weak-loaded CFM function exists */
#define PyMac_PRECHECK(rtn) do { if ( &rtn == NULL )  {\
87 88 89 90
		PyErr_SetString(PyExc_NotImplementedError, \
		"Not available in this shared library/OS version"); \
		return; \
	}} while(0)
91 92 93


#define USE_MAC_MP_MULTITHREADING 0
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

#if USE_MAC_MP_MULTITHREADING
static PyThreadState *_save;
static MPCriticalRegionID reentrantLock;
#endif /* USE_MAC_MP_MULTITHREADING */

extern int CFStringRef_New(CFStringRef *);

extern int CFStringRef_Convert(PyObject *, CFStringRef *);
extern int CFBundleRef_Convert(PyObject *, CFBundleRef *);

int EventTargetRef_Convert(PyObject *, EventTargetRef *);
PyObject *EventHandlerCallRef_New(EventHandlerCallRef itself);
PyObject *EventRef_New(EventRef itself);

/********** EventTypeSpec *******/
static PyObject*
EventTypeSpec_New(EventTypeSpec *in)
{
	return Py_BuildValue("ll", in->eventClass, in->eventKind);
}

static int
EventTypeSpec_Convert(PyObject *v, EventTypeSpec *out)
{
119 120 121
	if (PyArg_Parse(v, "(O&l)",
	                PyMac_GetOSType, &(out->eventClass),
	                &(out->eventKind)))
122 123 124 125 126 127 128 129
		return 1;
	return NULL;
}

/********** end EventTypeSpec *******/

/********** HIPoint *******/

130
#if 0  /* XXX doesn't compile */
131 132 133 134 135 136 137 138 139 140 141 142 143
static PyObject*
HIPoint_New(HIPoint *in)
{
	return Py_BuildValue("ff", in->x, in->y);
}

static int
HIPoint_Convert(PyObject *v, HIPoint *out)
{
	if (PyArg_ParseTuple(v, "ff", &(out->x), &(out->y)))
		return 1;
	return NULL;
}
144
#endif
145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165

/********** end HIPoint *******/

/********** EventHotKeyID *******/

static PyObject*
EventHotKeyID_New(EventHotKeyID *in)
{
	return Py_BuildValue("ll", in->signature, in->id);
}

static int
EventHotKeyID_Convert(PyObject *v, EventHotKeyID *out)
{
	if (PyArg_ParseTuple(v, "ll", &out->signature, &out->id))
		return 1;
	return NULL;
}

/********** end EventHotKeyID *******/

166
/******** myEventHandler ***********/
167

168
static EventHandlerUPP myEventHandlerUPP;
169

170 171
static pascal OSStatus
myEventHandler(EventHandlerCallRef handlerRef, EventRef event, void *outPyObject) {
172 173 174 175
	PyObject *retValue;
	int status;

#if USE_MAC_MP_MULTITHREADING
176 177
	MPEnterCriticalRegion(reentrantLock, kDurationForever);
	PyEval_RestoreThread(_save);
178 179
#endif /* USE_MAC_MP_MULTITHREADING */

180 181 182
	retValue = PyObject_CallFunction((PyObject *)outPyObject, "O&O&",
	                                 EventHandlerCallRef_New, handlerRef,
	                                 EventRef_New, event);
183 184 185 186 187 188 189 190 191 192 193 194 195
	if (retValue == NULL) {
		PySys_WriteStderr("Error in event handler callback:\n");
		PyErr_Print();  /* this also clears the error */
		status = noErr; /* complain? how? */
	} else {
		if (retValue == Py_None)
			status = noErr;
		else if (PyInt_Check(retValue)) {
			status = PyInt_AsLong(retValue);
		} else
			status = noErr; /* wrong object type, complain? */
		Py_DECREF(retValue);
	}
196 197

#if USE_MAC_MP_MULTITHREADING
198 199
	_save = PyEval_SaveThread();
	MPExitCriticalRegion(reentrantLock);
200 201
#endif /* USE_MAC_MP_MULTITHREADING */

202
	return status;
203 204
}

205
/******** end myEventHandler ***********/
206 207 208

"""

209
initstuff = initstuff + """
210 211
PyMac_PRECHECK(NewEventHandlerUPP); /* This can fail if CarbonLib is too old */
myEventHandlerUPP = NewEventHandlerUPP(myEventHandler);
212 213
"""
module = MacModule('_CarbonEvt', 'CarbonEvents', includestuff, finalstuff, initstuff)
214

215 216 217



218
class EventHandlerRefObjectDefinition(PEP253Mixin, GlobalObjectDefinition):
219 220 221 222 223 224 225 226 227 228 229
	def outputStructMembers(self):
		Output("%s ob_itself;", self.itselftype)
		Output("PyObject *ob_callback;")
	def outputInitStructMembers(self):
		Output("it->ob_itself = %sitself;", self.argref)
		Output("it->ob_callback = NULL;")
	def outputFreeIt(self, name):
		OutLbrace("if (self->ob_itself != NULL)")
		Output("RemoveEventHandler(self->ob_itself);")
		Output("Py_DECREF(self->ob_callback);")
		OutRbrace()
230
		
231
class MyGlobalObjectDefinition(PEP253Mixin, GlobalObjectDefinition):
232
	pass
233 234

for typ in RefObjectTypes:
235 236 237
	if typ == 'EventHandlerRef':
		EventHandlerRefobject = EventHandlerRefObjectDefinition('EventHandlerRef')
	else:
238
		execstr = typ + 'object = MyGlobalObjectDefinition(typ)'
239
		exec execstr
240 241
	module.addobject(eval(typ + 'object'))

242

243
functions = []
244
for typ in RefObjectTypes: ## go thru all ObjectTypes as defined in CarbonEventsscan.py
245 246 247 248 249 250
	# initialize the lists for carbongen to fill
	execstr = typ + 'methods = []'
	exec execstr

execfile('CarbonEventsgen.py')

251 252


253
for f in functions: module.add(f)	# add all the functions carboneventsgen put in the list
254

255
for typ in RefObjectTypes:				 ## go thru all ObjectTypes as defined in CarbonEventsscan.py
256
	methods = eval(typ + 'methods')  ## get a reference to the method list from the main namespace
257 258
	obj = eval(typ + 'object')		  ## get a reference to the object
	for m in methods: obj.add(m)	## add each method in the list to the object
259

260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282

removeeventhandler = """
OSStatus _err;
if (_self->ob_itself == NULL) {
	PyErr_SetString(CarbonEvents_Error, "Handler has been removed");
	return NULL;
}
if (!PyArg_ParseTuple(_args, ""))
	return NULL;
_err = RemoveEventHandler(_self->ob_itself);
if (_err != noErr) return PyMac_Error(_err);
_self->ob_itself = NULL;
Py_DECREF(_self->ob_callback);
_self->ob_callback = NULL;
Py_INCREF(Py_None);
_res = Py_None;
return _res;"""

f = ManualGenerator("RemoveEventHandler", removeeventhandler);
f.docstring = lambda: "() -> None"
EventHandlerRefobject.add(f)


283 284 285 286 287 288 289 290 291
installeventhandler = """
EventTypeSpec inSpec;
PyObject *callback;
EventHandlerRef outRef;
OSStatus _err;

if (!PyArg_ParseTuple(_args, "O&O", EventTypeSpec_Convert, &inSpec, &callback))
	return NULL;

292
_err = InstallEventHandler(_self->ob_itself, myEventHandlerUPP, 1, &inSpec, (void *)callback, &outRef);
293 294
if (_err != noErr) return PyMac_Error(_err);

295 296 297 298 299 300
_res = EventHandlerRef_New(outRef);
if (_res != NULL) {
	((EventHandlerRefObject*)_res)->ob_callback = callback;
	Py_INCREF(callback);
}
return _res;"""
301 302

f = ManualGenerator("InstallEventHandler", installeventhandler);
303
f.docstring = lambda: "(EventTypeSpec inSpec, Method callback) -> (EventHandlerRef outRef)"
304 305
EventTargetRefobject.add(f)

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
# This may not be the best, but at least it lets you get the raw data back into python as a string. You'll have to cut it up yourself and parse the result.

geteventparameter = """
UInt32 bufferSize;
EventParamName inName;
EventParamType inType;
OSErr _err;
void * buffer;

if (!PyArg_ParseTuple(_args, "O&O&", PyMac_GetOSType, &inName, PyMac_GetOSType, &inType))
      return NULL;

/* Figure out the size by passing a null buffer to GetEventParameter */
_err = GetEventParameter(_self->ob_itself, inName, inType, NULL, 0, &bufferSize, NULL);

if (_err != noErr)
      return PyMac_Error(_err);
buffer = PyMem_NEW(char, bufferSize);
if (buffer == NULL)
      return PyErr_NoMemory();

_err = GetEventParameter(_self->ob_itself, inName, inType, NULL, bufferSize, NULL, buffer);

if (_err != noErr) {
      PyMem_DEL(buffer);
      return PyMac_Error(_err);
}
_res = Py_BuildValue("s#", buffer, bufferSize);
PyMem_DEL(buffer);
return _res;
"""

f = ManualGenerator("GetEventParameter", geteventparameter);
f.docstring = lambda: "(EventParamName eventName, EventParamType eventType) -> (String eventParamData)"
EventRefobject.add(f)

342 343 344
runappeventloop = """
#if USE_MAC_MP_MULTITHREADING
if (MPCreateCriticalRegion(&reentrantLock) != noErr) {
345
	PySys_WriteStderr("lock failure\\n");
346 347 348 349 350 351 352 353 354 355 356 357 358 359
	return NULL;
}
_save = PyEval_SaveThread();
#endif /* USE_MAC_MP_MULTITHREADING */

RunApplicationEventLoop();

#if USE_MAC_MP_MULTITHREADING
PyEval_RestoreThread(_save);

MPDeleteCriticalRegion(reentrantLock);
#endif /* USE_MAC_MP_MULTITHREADING */

Py_INCREF(Py_None);
360 361
_res = Py_None;
return _res;
362 363 364 365 366 367
"""			

f = ManualGenerator("RunApplicationEventLoop", runappeventloop);
f.docstring = lambda: "() -> ()"
module.add(f)

368
SetOutputFileName('_CarbonEvtmodule.c')
369 370
module.generate()

371 372
##import os
##os.system("python setup.py build")