1/*
2 * Wrappers for callback functions.
3 *
4 * XXX: Definitely need tests for these.
5 */
6#include <Python.h>
7#include "pyobjc-api.h"
8
9#import <ApplicationServices/ApplicationServices.h>
10
11
12/*
13 *
14 * CGDataConsumerCreate
15 *
16 */
17
18static size_t
19m_CGDataConsumerPutBytesCallback(void* _info, const void* buffer, size_t count)
20{
21	size_t    retval;
22	PyObject* info = (PyObject*)_info;
23
24	PyGILState_STATE   state = PyGILState_Ensure();
25
26	PyObject* result = PyObject_CallFunction(
27			PyTuple_GET_ITEM(info, 0), "Os#l",
28			PyTuple_GET_ITEM(info, 2), buffer, count, count);
29	if (result == NULL) {
30		PyObjCErr_ToObjCWithGILState(&state);
31	}
32
33	if (PyObjC_PythonToObjC(@encode(size_t), result, &retval) < 0) {
34		Py_DECREF(result);
35		PyObjCErr_ToObjCWithGILState(&state);
36	}
37	Py_DECREF(result);
38	PyGILState_Release(state);
39	return retval;
40}
41
42static void
43m_CGDataConsumerReleaseInfoCallback(void* _info)
44{
45	PyObject* info = (PyObject*)_info;
46
47	PyGILState_STATE   state = PyGILState_Ensure();
48
49	if (PyTuple_GET_ITEM(info, 1) != Py_None) {
50		PyObject* result = PyObject_CallFunction(
51			PyTuple_GET_ITEM(info, 1), "O",
52			PyTuple_GET_ITEM(info, 2));
53		if (result == NULL) {
54			PyObjCErr_ToObjCWithGILState(&state);
55		}
56		Py_DECREF(result);
57	}
58
59	Py_DECREF(info);
60
61	PyGILState_Release(state);
62}
63
64static CGDataConsumerCallbacks
65m_CGDataConsumerCallbacks = {
66	m_CGDataConsumerPutBytesCallback,	/* putBytes */
67	m_CGDataConsumerReleaseInfoCallback	/* releaseConsumer */
68};
69
70PyDoc_STRVAR(doc_CGDataConsumerCreate,
71	"CGDataConsumerCreate(info, (putBytes, release)) -> object\n"
72	"\n"
73	"putBytes and release are callback functions. Release may be None");
74static PyObject*
75m_CGDataConsumerCreate(PyObject* self __attribute__((__unused__)),
76		PyObject* args)
77{
78	PyObject* info;
79	PyObject* putBytes;
80	PyObject* release;
81
82	if (!PyArg_ParseTuple(args, "O(OO)", &info, &putBytes, &release)) {
83		return NULL;
84	}
85
86	if (!PyCallable_Check(putBytes)) {
87		PyErr_SetString(PyExc_TypeError, "putBytes is not callable");
88		return NULL;
89	}
90	if (release != Py_None && !PyCallable_Check(release)) {
91		PyErr_SetString(PyExc_TypeError, "release is not callable");
92		return NULL;
93	}
94
95	PyObject* real_info = Py_BuildValue("OOO", putBytes, release, info);
96	if (real_info == NULL) {
97		return NULL;
98	}
99
100	CGDataConsumerRef result;
101	PyObjC_DURING
102		result = CGDataConsumerCreate(real_info,
103				&m_CGDataConsumerCallbacks);
104
105	PyObjC_HANDLER
106		result = NULL;
107		PyObjCErr_FromObjC(localException);
108	PyObjC_ENDHANDLER
109
110	if (result == NULL && PyErr_Occurred()) {
111		Py_DECREF(real_info);
112		return NULL;
113	}
114
115	if (result == NULL)  {
116		Py_DECREF(real_info);
117		Py_INCREF(Py_None);
118		return Py_None;
119	}
120
121	PyObject* retval = PyObjC_ObjCToPython(
122			@encode(CGDataConsumerRef), &result);
123	/* CGDataConsumerCreate donated a reference, we therefore now have
124	 * one too many, release a reference.
125	 */
126	CGDataConsumerRelease(result);
127	return retval;
128}
129
130/*
131 *
132 * CGDataProviderCreate*
133 *
134 */
135
136static size_t
137m_CGDataProviderGetBytesCallback(
138		void* _info,
139		void* buffer,
140		size_t count)
141{
142	PyObject* info = (PyObject*)_info;
143
144	PyGILState_STATE   state = PyGILState_Ensure();
145
146	PyObject* buf = PyBuffer_FromReadWriteMemory(buffer, count);
147	if (buf == NULL) {
148		PyObjCErr_ToObjCWithGILState(&state);
149	}
150
151	PyObject* result = PyObject_CallFunction(
152			PyTuple_GET_ITEM(info, 1),
153			"OOl",
154			PyTuple_GET_ITEM(info, 0),
155			buf,
156			count);
157	if (result == NULL) {
158		Py_DECREF(result);
159		Py_DECREF(buf);
160		PyObjCErr_ToObjCWithGILState(&state);
161	}
162
163	if (!PyTuple_Check(result) || PyTuple_GET_SIZE(result) != 2) {
164		PyErr_Format(PyExc_TypeError,
165			"Expecting result of type tuple of 2, got %s",
166			result->ob_type->tp_name);
167		Py_DECREF(result);
168		Py_DECREF(buf);
169		PyObjCErr_ToObjCWithGILState(&state);
170	}
171
172	size_t c_result;
173	if (PyObjC_PythonToObjC(@encode(size_t), PyTuple_GET_ITEM(result, 0), &c_result) < 0) {
174		Py_DECREF(result);
175		Py_DECREF(buf);
176		PyObjCErr_ToObjCWithGILState(&state);
177	}
178
179	if (PyTuple_GET_ITEM(result, 1) != buf) {
180		const void* b;
181		Py_ssize_t c;
182
183		if (PyObject_AsReadBuffer(PyTuple_GET_ITEM(result, 1),
184					&b, &c) < 0) {
185			Py_DECREF(result);
186			Py_DECREF(buf);
187			PyObjCErr_ToObjCWithGILState(&state);
188		}
189
190		if (c < c_result || c > count) {
191			PyErr_SetString(PyExc_ValueError,
192				"Inconsistent size");
193			Py_DECREF(result);
194			Py_DECREF(buf);
195			PyObjCErr_ToObjCWithGILState(&state);
196		}
197		memcpy(buffer, b, c_result);
198	} else {
199		/* Assume that the user knows what he's doing and has
200		 * filled the right bit of the buffer.
201		 */
202	}
203
204	Py_DECREF(buf);
205	Py_DECREF(result);
206
207	PyGILState_Release(state);
208	return c_result;
209}
210
211static void
212m_CGDataProviderRewindCallback(void* _info)
213{
214	PyObject* info = (PyObject*)_info;
215
216	PyGILState_STATE   state = PyGILState_Ensure();
217
218	PyObject* result = PyObject_CallFunction(PyTuple_GET_ITEM(info, 3),
219			"O", PyTuple_GET_ITEM(info, 0));
220	if (result == NULL) {
221		PyObjCErr_ToObjCWithGILState(&state);
222	}
223	Py_DECREF(result);
224
225	PyGILState_Release(state);
226}
227
228static void
229m_CGDataProviderReleaseInfoCallback(void* _info)
230{
231	PyObject* info = (PyObject*)_info;
232
233	PyGILState_STATE   state = PyGILState_Ensure();
234
235	if (PyTuple_GET_ITEM(info, 3) != Py_None) {
236		PyObject* result = PyObject_CallFunction(PyTuple_GET_ITEM(info, 4),
237				"O", PyTuple_GET_ITEM(info, 0));
238		if (result == NULL) {
239			PyObjCErr_ToObjCWithGILState(&state);
240		}
241		Py_DECREF(result);
242	}
243
244	/* Cleanup up the callback info */
245	Py_DECREF(info);
246
247	PyGILState_Release(state);
248}
249
250
251
252
253#ifndef OS_TIGER
254
255static off_t
256m_CGDataProviderSkipForwardCallback(void* _info, off_t count)
257{
258	PyObject* info = (PyObject*)_info;
259	off_t retval;
260
261	PyGILState_STATE   state = PyGILState_Ensure();
262
263	PyObject* result = PyObject_CallFunction(PyTuple_GET_ITEM(info, 2),
264			"Ol", PyTuple_GET_ITEM(info, 0), count);
265	if (result == NULL) {
266		PyObjCErr_ToObjCWithGILState(&state);
267	}
268
269	if (PyObjC_PythonToObjC(@encode(off_t), result, &retval) < 0) {
270		Py_DECREF(result);
271		PyObjCErr_ToObjCWithGILState(&state);
272	}
273	Py_DECREF(result);
274	PyGILState_Release(state);
275
276	return retval;
277}
278
279
280static CGDataProviderSequentialCallbacks m_CGDataProviderSequentialCallbacks = {
281	0,					/* version */
282	m_CGDataProviderGetBytesCallback,	/* getBytes */
283	m_CGDataProviderSkipForwardCallback,	/* skipForward */
284	m_CGDataProviderRewindCallback,		/* rewind */
285	m_CGDataProviderReleaseInfoCallback	/* releaseInfo */
286
287};
288
289PyDoc_STRVAR(doc_CGDataProviderCreateSequential,
290	"CGDataConsumerCreateSequential(info, (getBytes, skipForward, rewind, releaseProvider)) -> object\n"
291	"\n"
292	"getBytes, skipForward, rewind and release are callback functions. Release may be None");
293static PyObject*
294m_CGDataProviderCreateSequential(PyObject* self __attribute__((__unused__)),
295		PyObject* args)
296{
297	PyObject* info;
298	PyObject* getBytes;
299	PyObject* skipForward;
300	PyObject* rewind;
301	PyObject* release;
302
303	if (!PyArg_ParseTuple(args, "O(OOOO)", &info, &getBytes, &skipForward, &rewind, &release)) {
304		return NULL;
305	}
306
307	if (!PyCallable_Check(getBytes)) {
308		PyErr_SetString(PyExc_TypeError, "getBytes is not callable");
309		return NULL;
310	}
311	if (!PyCallable_Check(skipForward)) {
312		PyErr_SetString(PyExc_TypeError, "skipForward is not callable");
313		return NULL;
314	}
315	if (!PyCallable_Check(rewind)) {
316		PyErr_SetString(PyExc_TypeError, "rewind is not callable");
317		return NULL;
318	}
319	if (release != Py_None && !PyCallable_Check(release)) {
320		PyErr_SetString(PyExc_TypeError, "release is not callable");
321		return NULL;
322	}
323
324	PyObject* real_info = Py_BuildValue("OOOOO", info, getBytes, skipForward, rewind, release);
325	if (real_info == NULL) {
326		return NULL;
327	}
328
329	CGDataProviderRef result;
330	PyObjC_DURING
331		result = CGDataProviderCreateSequential(real_info,
332				&m_CGDataProviderSequentialCallbacks);
333
334	PyObjC_HANDLER
335		result = NULL;
336		PyObjCErr_FromObjC(localException);
337	PyObjC_ENDHANDLER
338
339	if (result == NULL && PyErr_Occurred()) {
340		Py_DECREF(real_info);
341		return NULL;
342	}
343
344	if (result == NULL)  {
345		Py_DECREF(real_info);
346		Py_INCREF(Py_None);
347		return Py_None;
348	}
349
350	PyObject* retval = PyObjC_ObjCToPython(
351			@encode(CGDataProviderRef), &result);
352	/* CGDataProviderCreate donated a reference, we therefore now have
353	 * one too many, release a reference.
354	 */
355	CGDataProviderRelease(result);
356	return retval;
357}
358
359#endif
360
361/*
362 * CGDataProviderCreateWithData
363 */
364
365static void
366m_releaseData(void* _info, const void* data, size_t size)
367{
368	PyObject* info = (PyObject*)_info;
369	int tag;
370
371	PyGILState_STATE   state = PyGILState_Ensure();
372
373	tag = PyInt_AsLong(PyTuple_GET_ITEM(info, 2));
374
375	if (PyTuple_GET_ITEM(info, 1) != Py_None) {
376		PyObject* result = PyObject_CallFunction(
377				PyTuple_GET_ITEM(info, 1),
378				"O", PyTuple_GET_ITEM(info, 0));
379		if (result == NULL) {
380			PyObjC_FreeCArray(tag, (void*)data);
381			Py_DECREF(info);
382			PyObjCErr_ToObjCWithGILState(&state);
383		}
384		Py_DECREF(result);
385
386	}
387
388	PyObjC_FreeCArray(tag, (void*)data);
389	Py_DECREF(info);
390
391	PyGILState_Release(state);
392}
393
394PyDoc_STRVAR(doc_CGDataProviderCreateWithData,
395	"CGDataProviderCreateWithData(info, data, size, release) -> object");
396static PyObject*
397m_CGDataProviderCreateWithData(PyObject* self __attribute__((__unused__)),
398		PyObject* args)
399{
400	PyObject* info;
401	PyObject* data;
402	long      size;
403	PyObject* release;
404
405	if (!PyArg_ParseTuple(args, "OOlO", &info, &data, &size, &release)) {
406		return NULL;
407	}
408
409	if (release != Py_None && !PyCallable_Check(release)) {
410		PyErr_SetString(PyExc_TypeError, "release not callable");
411		return NULL;
412	}
413
414	int tag;
415	PyObject* bufobj = NULL;
416	Py_ssize_t sz = (Py_ssize_t)size;
417	void* arr;
418
419	tag = PyObjC_PythonToCArray(NO, YES,
420			@encode(char), data, &arr, &sz, &bufobj);
421	if (tag < 0) {
422		return NULL;
423	}
424
425	PyObject* real_info;
426	if (bufobj != NULL) {
427		real_info = Py_BuildValue("OOlOO", info, release, tag, bufobj);
428	} else {
429		real_info = Py_BuildValue("OOlO", info, release, tag);
430	}
431
432	CGDataProviderRef result;
433
434	PyObjC_DURING
435		result = CGDataProviderCreateWithData(
436				real_info, arr, size, m_releaseData);
437
438	PyObjC_HANDLER
439		result = NULL;
440		PyObjCErr_FromObjC(localException);
441	PyObjC_ENDHANDLER
442
443	if (PyErr_Occurred()) {
444		PyObjC_FreeCArray(tag, arr);
445		Py_DECREF(info);
446		return NULL;
447	}
448
449	PyObject* retval = PyObjC_ObjCToPython(
450			@encode(CGDataProviderRef), &result);
451	CFRelease(result);
452	return retval;
453}
454
455/*
456 *  CGFunctionCreate
457 */
458
459static void
460m_CGFunctionEvaluateCallback(void* _info, const float* inData, float* outData)
461{
462	PyObject* info = (PyObject*)_info;
463	long      domdim;
464	long      rangedim;
465
466	PyGILState_STATE   state = PyGILState_Ensure();
467
468	domdim = PyInt_AsLong(PyTuple_GET_ITEM(info, 2));
469	rangedim = PyInt_AsLong(PyTuple_GET_ITEM(info, 3));
470
471	PyObject* input;
472	if (inData) {
473		input = PyObjC_CArrayToPython(@encode(float), (void*)inData, domdim);
474	} else {
475		input = Py_None;
476		Py_INCREF(Py_None);
477	}
478
479
480	PyObject* result = PyObject_CallFunction(PyTuple_GET_ITEM(info, 1),
481			"OOO",
482			PyTuple_GET_ITEM(info, 0),
483			input,
484			Py_None);
485	Py_DECREF(input);
486	if (result == NULL) {
487		PyObjCErr_ToObjCWithGILState(&state);
488	}
489
490	if (PyObjC_DepythonifyCArray(@encode(float), rangedim, NO, result, (void*)outData) < 0) {
491		Py_DECREF(result);
492		PyObjCErr_ToObjCWithGILState(&state);
493	}
494	Py_DECREF(result);
495
496	PyGILState_Release(state);
497}
498
499static void
500m_CGFunctionReleaseInfoCallback(void* _info)
501{
502	PyObject* info = (PyObject*)_info;
503
504	PyGILState_STATE   state = PyGILState_Ensure();
505
506	Py_DECREF(info);
507
508	PyGILState_Release(state);
509}
510
511static CGFunctionCallbacks m_CGFunctionCallbacks = {
512	0, 				/*  version */
513   	m_CGFunctionEvaluateCallback,	/* evaluate */
514	m_CGFunctionReleaseInfoCallback	/* releaseInfo */
515};
516
517PyDoc_STRVAR(doc_CGFunctionCreate,
518	"CGFunctionCreate(info, domainDimension, domain, rangeDimension, range, evaluate) -> functionref");
519static PyObject*
520m_CGFunctionCreate(PyObject* self __attribute__((__unused__)),
521		PyObject* args)
522{
523	PyObject* info;
524	PyObject* domDim;
525	PyObject* domain;
526	PyObject* rangeDim;
527	PyObject* range;
528	PyObject* evaluate;
529	size_t domainDimension;
530	size_t rangeDimension;
531	float* domainArr;
532	float* rangeArr;
533	CGFunctionRef result = NULL;
534	PyObject* domainBuf = NULL;
535	PyObject* rangeBuf = NULL;
536	int rangeTag;
537	int domainTag;
538
539	if (!PyArg_ParseTuple(args, "OOOOOO",
540			&info, &domDim, &domain, &rangeDim,
541			&range, &evaluate)) {
542		return NULL;
543	}
544
545	if (PyObjC_PythonToObjC(@encode(size_t), domDim, &domainDimension) < 0){
546		return NULL;
547	}
548	if (PyObjC_PythonToObjC(@encode(size_t), rangeDim, &rangeDimension) < 0){
549		return NULL;
550	}
551	if (domain == Py_None) {
552		domainArr = NULL;
553		domainTag = -1;
554
555	} else  {
556		/*  Parse Array */
557		Py_ssize_t cnt = domainDimension * 2;
558		domainTag = PyObjC_PythonToCArray(NO, NO, @encode(float),
559				domain, (void**)&domainArr, &cnt, &domainBuf);
560		if (domainTag < 0) {
561			return NULL;
562		}
563	}
564
565	if (range == Py_None) {
566		rangeArr = NULL;
567		rangeTag = -1;
568
569	} else  {
570		Py_ssize_t cnt = rangeDimension * 2;
571
572		/*  Parse Array */
573		rangeTag = PyObjC_PythonToCArray(NO, NO, @encode(float),
574				range, (void**)&rangeArr, &cnt, &rangeBuf);
575		if (rangeTag < 0) {
576			if (domainTag != -1) {
577				PyObjC_FreeCArray(domainTag, domainArr);
578				Py_XDECREF(domainBuf);
579			}
580			return NULL;
581		}
582	}
583
584	if (!PyCallable_Check(evaluate)) {
585		PyErr_SetString(PyExc_TypeError, "evaluate not callable");
586		if (domainTag != -1) {
587			PyObjC_FreeCArray(domainTag, domainArr);
588			Py_XDECREF(domainBuf);
589		}
590		if (rangeTag != -1) {
591			PyObjC_FreeCArray(rangeTag, rangeArr);
592			Py_XDECREF(rangeBuf);
593		}
594		return NULL;
595	}
596
597
598	PyObject* real_info;
599
600	real_info = Py_BuildValue("OOll",
601		info, evaluate, domainDimension, rangeDimension);
602	if (real_info == NULL) {
603		return NULL;
604	}
605
606	PyObjC_DURING
607		result = CGFunctionCreate(
608				real_info,
609				domainDimension,
610				domainArr,
611				rangeDimension,
612				rangeArr,
613				&m_CGFunctionCallbacks);
614
615	PyObjC_HANDLER
616		result = NULL;
617		PyObjCErr_FromObjC(localException);
618	PyObjC_ENDHANDLER
619
620	/* cleanup domainArr, rangeArr */
621	if (domainTag != -1) {
622		Py_XDECREF(domainBuf);
623		PyObjC_FreeCArray(domainTag, domainArr);
624	}
625	if (rangeTag != -1) {
626		Py_XDECREF(rangeBuf);
627		PyObjC_FreeCArray(rangeTag, rangeArr);
628	}
629
630	if (result == NULL) {
631		Py_DECREF(real_info);
632		if (PyErr_Occurred()) {
633			return NULL;
634		}
635		Py_INCREF(Py_None);
636		return Py_None;
637	}
638
639	PyObject* func = PyObjC_ObjCToPython(@encode(CGFunctionRef), &result);
640	CGFunctionRelease(result); /* Adjust reference count */
641
642	return func;
643}
644
645
646/*
647 * - CGDisplayRegisterReconfigurationCallback
648 * - CGDisplayRemoveReconfigurationCallback
649 */
650
651struct callback_struct {
652	PyObject*	callback;
653	PyObject*	user_info;
654	PyObject*	real_info;
655};
656struct callback_info {
657	struct callback_struct* list;
658	size_t                  count;
659};
660
661struct callback_info display_reconfig_callback = { NULL, 0 };
662
663static int
664insert_callback_info(
665	struct callback_info* info,
666	PyObject* callback,
667	PyObject* user_info,
668	PyObject* real_info)
669{
670	size_t i;
671
672	for (i = 0; i < info->count; i++) {
673		if (info->list[i].callback == NULL) {
674			info->list[i].callback = callback;
675			info->list[i].user_info = user_info;
676			info->list[i].real_info = real_info;
677			Py_INCREF(callback);
678			Py_INCREF(user_info);
679			Py_INCREF(real_info);
680			return 0;
681		}
682	}
683
684	/* No free space found, increase the list */
685	if (info->list == NULL) {
686		info->list = PyMem_Malloc(sizeof(*info->list));
687		if (info->list == NULL) {
688			PyErr_NoMemory();
689			return -1;
690		}
691		info->list[0].callback = callback;
692		info->list[0].user_info = user_info;
693		info->list[0].real_info = real_info;
694		Py_INCREF(callback);
695		Py_INCREF(user_info);
696		Py_INCREF(real_info);
697		info->count = 1;
698	} else {
699		struct callback_struct* tmp;
700
701		tmp = PyMem_Realloc(info->list, sizeof(*info->list) * (info->count+1));
702		if (tmp == NULL) {
703			PyErr_NoMemory();
704			return -1;
705		}
706		info->list = tmp;
707		info->list[info->count].callback = callback;
708		info->list[info->count].user_info = user_info;
709		info->list[info->count].real_info = real_info;
710		Py_INCREF(callback);
711		Py_INCREF(user_info);
712		Py_INCREF(real_info);
713		info->count++;
714	}
715	return 0;
716}
717
718static PyObject*
719find_callback_info(
720	struct callback_info* info,
721	PyObject* callback,
722	PyObject* user_info)
723{
724	size_t i;
725
726	for (i = 0; i < info->count; i++) {
727		if (info->list[i].callback == NULL) continue;
728
729		if (!PyObject_RichCompareBool(info->list[i].callback, callback, Py_EQ)) {
730			continue;
731		}
732		if (!PyObject_RichCompareBool(info->list[i].user_info, user_info, Py_EQ)) {
733			continue;
734		}
735
736		return info->list[i].real_info;
737	}
738	PyErr_SetString(PyExc_ValueError, "Cannot find callback info");
739	return NULL;
740}
741
742static void
743remove_callback_info(
744	struct callback_info* info,
745	PyObject* callback,
746	PyObject* user_info)
747{
748	size_t i;
749
750	for (i = 0; i < info->count; i++) {
751		if (info->list[i].callback == NULL) continue;
752
753		if (!PyObject_RichCompareBool(info->list[i].callback, callback, Py_EQ)) {
754			continue;
755		}
756		if (!PyObject_RichCompareBool(info->list[i].user_info, user_info, Py_EQ)) {
757			continue;
758		}
759
760		Py_DECREF(info->list[i].callback);
761		Py_DECREF(info->list[i].user_info);
762		info->list[i].callback = NULL;
763		info->list[i].user_info = NULL;
764	}
765}
766
767
768static void m_CGDisplayReconfigurationCallBack(
769		CGDirectDisplayID display,
770		CGDisplayChangeSummaryFlags flags,
771		void* _userInfo)
772{
773	PyObject* info = (PyObject*)_userInfo;
774
775	PyGILState_STATE   state = PyGILState_Ensure();
776
777	PyObject* py_display = PyObjC_ObjCToPython(
778		@encode(CGDirectDisplayID), &display);
779	if (py_display == NULL) {
780		PyObjCErr_ToObjCWithGILState(&state);
781	}
782
783	PyObject* py_flags = PyObjC_ObjCToPython(
784		@encode(CGDisplayChangeSummaryFlags), &flags);
785	if (py_flags == NULL) {
786		Py_DECREF(py_display);
787		PyObjCErr_ToObjCWithGILState(&state);
788	}
789
790
791
792	PyObject* result = PyObject_CallFunction(
793			PyTuple_GET_ITEM(info, 0), "OOO",
794			py_display,
795			py_flags,
796			PyTuple_GET_ITEM(info, 1));
797	Py_DECREF(py_display);
798	Py_DECREF(py_flags);
799	if (result == NULL) {
800		PyObjCErr_ToObjCWithGILState(&state);
801	}
802
803	Py_DECREF(result);
804	PyGILState_Release(state);
805}
806
807static PyObject*
808m_CGDisplayRegisterReconfigurationCallback(
809	PyObject* self __attribute__((__unused__)),
810	PyObject* args)
811{
812	PyObject* callback;
813	PyObject* userinfo;
814	CGError err;
815
816
817	if (!PyArg_ParseTuple(args, "OO", &callback, &userinfo)) {
818		return NULL;
819	}
820	if (!PyCallable_Check(callback)) {
821		PyErr_SetString(PyExc_TypeError, "callback not callable");
822		return NULL;
823	}
824
825	PyObject* real_info = Py_BuildValue("OO", callback, userinfo);
826
827	err = -1;
828	PyObjC_DURING
829		err = CGDisplayRegisterReconfigurationCallback(
830			m_CGDisplayReconfigurationCallBack, real_info);
831
832
833	PyObjC_HANDLER
834		err = -1;
835		PyObjCErr_FromObjC(localException);
836
837	PyObjC_ENDHANDLER
838
839	if (PyErr_Occurred()) {
840		Py_DECREF(real_info);
841		return NULL;
842	}
843
844	if (insert_callback_info(&display_reconfig_callback,
845				callback, userinfo, real_info) == -1) {
846		CGDisplayRemoveReconfigurationCallback(
847			m_CGDisplayReconfigurationCallBack,
848			real_info);
849		Py_DECREF(real_info);
850		return NULL;
851	}
852
853	return PyObjC_ObjCToPython(@encode(CGError), &err);
854}
855
856static PyObject*
857m_CGDisplayRemoveReconfigurationCallback(
858	PyObject* self __attribute__((__unused__)),
859	PyObject* args)
860{
861	PyObject* callback;
862	PyObject* userinfo;
863
864	if (!PyArg_ParseTuple(args, "OO", &callback, &userinfo)) {
865		return NULL;
866	}
867
868	PyObject* real_info = find_callback_info(&display_reconfig_callback, callback, userinfo);
869
870	if (real_info == NULL) {
871		return NULL;
872	}
873
874	CGError err = -1;
875	PyObjC_DURING
876		err = CGDisplayRemoveReconfigurationCallback(
877			m_CGDisplayReconfigurationCallBack,
878			real_info);
879
880	PyObjC_HANDLER
881		PyObjCErr_FromObjC(localException);
882
883	PyObjC_ENDHANDLER
884
885	if (PyErr_Occurred()) {
886		return NULL;
887	}
888
889	remove_callback_info(&display_reconfig_callback, callback, userinfo);
890
891	return PyObjC_ObjCToPython(@encode(CGError), &err);
892}
893
894/*
895 * CGScreenUpdateMove
896 */
897
898struct callback_info screen_move_callback = { NULL, 0 };
899
900static void
901m_CGScreenUpdateMoveCallback(
902	CGScreenUpdateMoveDelta delta,
903	size_t count,
904	const CGRect* rectArray,
905	void* _userInfo)
906{
907	PyObject* info = (PyObject*)_userInfo;
908
909	PyGILState_STATE   state = PyGILState_Ensure();
910
911	PyObject* py_delta = PyObjC_ObjCToPython(
912		@encode(CGScreenUpdateMoveDelta), &delta);
913	if (py_delta == NULL) {
914		PyObjCErr_ToObjCWithGILState(&state);
915	}
916	PyObject* py_rectarray = PyObjC_CArrayToPython(@encode(CGRect),
917			(void*)rectArray, count);
918	if (py_rectarray == NULL) {
919		Py_DECREF(py_delta);
920		PyObjCErr_ToObjCWithGILState(&state);
921	}
922
923	PyObject* result = PyObject_CallFunction(
924			PyTuple_GET_ITEM(info, 0), "OlOO",
925			py_delta,
926			(long)count,
927			py_rectarray,
928			PyTuple_GET_ITEM(info, 1));
929	Py_DECREF(py_delta);
930	Py_DECREF(py_rectarray);
931	if (result == NULL) {
932		PyObjCErr_ToObjCWithGILState(&state);
933	}
934
935	Py_DECREF(result);
936	PyGILState_Release(state);
937}
938
939static PyObject*
940m_CGScreenRegisterMoveCallback(
941	PyObject* self __attribute__((__unused__)),
942	PyObject* args)
943{
944	PyObject* callback;
945	PyObject* userinfo;
946
947
948	if (PyArg_ParseTuple(args, "OO", &callback, &userinfo)) {
949		return NULL;
950	}
951	if (!PyCallable_Check(callback)) {
952		PyErr_SetString(PyExc_TypeError, "callback not callable");
953		return NULL;
954	}
955
956	PyObject* real_info = Py_BuildValue("OO", callback, userinfo);
957
958	PyObjC_DURING
959		CGScreenRegisterMoveCallback(
960			m_CGScreenUpdateMoveCallback, real_info);
961
962	PyObjC_HANDLER
963		PyObjCErr_FromObjC(localException);
964
965	PyObjC_ENDHANDLER
966
967	if (PyErr_Occurred()) {
968		Py_DECREF(real_info);
969		return NULL;
970	}
971
972	if (insert_callback_info(&screen_move_callback,
973				callback, userinfo, real_info) < 0) {
974		CGScreenUnregisterMoveCallback(
975			m_CGScreenUpdateMoveCallback,
976			real_info);
977		Py_DECREF(real_info);
978		return NULL;
979	}
980
981	Py_INCREF(Py_None);
982	return Py_None;
983}
984
985static PyObject*
986m_CGScreenUnregisterMoveCallback(
987	PyObject* self __attribute__((__unused__)),
988	PyObject* args)
989{
990	PyObject* callback;
991	PyObject* userinfo;
992
993	if (!PyArg_ParseTuple(args, "OO", &callback, &userinfo)) {
994		return NULL;
995	}
996
997	PyObject* real_info = find_callback_info(&screen_move_callback, callback, userinfo);
998
999	if (real_info == NULL) {
1000		return NULL;
1001	}
1002
1003	PyObjC_DURING
1004		CGScreenUnregisterMoveCallback(
1005			m_CGScreenUpdateMoveCallback,
1006			real_info);
1007
1008	PyObjC_HANDLER
1009		PyObjCErr_FromObjC(localException);
1010
1011	PyObjC_ENDHANDLER
1012
1013	if (PyErr_Occurred()) {
1014		return NULL;
1015	}
1016
1017	remove_callback_info(&screen_move_callback, callback, userinfo);
1018
1019	Py_INCREF(Py_None);
1020	return Py_None;
1021}
1022
1023/*
1024 * CGScreenRefresh
1025 */
1026
1027struct callback_info screen_refresh_callback = { NULL, 0 };
1028
1029static void m_CGScreenRefreshCallback(
1030		CGRectCount count,
1031		const CGRect* rectArray,
1032		void* _userInfo)
1033{
1034	PyObject* info = (PyObject*)_userInfo;
1035
1036	PyGILState_STATE   state = PyGILState_Ensure();
1037
1038	PyObject* py_rectarray = PyObjC_CArrayToPython(@encode(CGRect),
1039			(void*)rectArray, count);
1040	if (py_rectarray == NULL) {
1041		PyObjCErr_ToObjCWithGILState(&state);
1042	}
1043
1044	PyObject* result = PyObject_CallFunction(
1045			PyTuple_GET_ITEM(info, 0), "lOO",
1046			(long)count,
1047			py_rectarray,
1048			PyTuple_GET_ITEM(info, 1));
1049	Py_DECREF(py_rectarray);
1050	if (result == NULL) {
1051		PyObjCErr_ToObjCWithGILState(&state);
1052	}
1053
1054	Py_DECREF(result);
1055	PyGILState_Release(state);
1056}
1057
1058static PyObject*
1059m_CGRegisterScreenRefreshCallback(
1060	PyObject* self __attribute__((__unused__)),
1061	PyObject* args)
1062{
1063	PyObject* callback;
1064	PyObject* userinfo;
1065
1066
1067	if (!PyArg_ParseTuple(args, "OO", &callback, &userinfo)) {
1068		return NULL;
1069	}
1070	if (!PyCallable_Check(callback)) {
1071		PyErr_SetString(PyExc_TypeError, "callback not callable");
1072		return NULL;
1073	}
1074
1075	PyObject* real_info = Py_BuildValue("OO", callback, userinfo);
1076
1077	CGError err = -1;
1078	PyObjC_DURING
1079		err = CGRegisterScreenRefreshCallback(
1080			m_CGScreenRefreshCallback, real_info);
1081
1082	PyObjC_HANDLER
1083		PyObjCErr_FromObjC(localException);
1084
1085	PyObjC_ENDHANDLER
1086
1087	if (PyErr_Occurred()) {
1088		Py_DECREF(real_info);
1089		return NULL;
1090	}
1091
1092	if (insert_callback_info(&screen_refresh_callback,
1093				callback, userinfo, real_info) < 0) {
1094		CGUnregisterScreenRefreshCallback(
1095			m_CGScreenRefreshCallback,
1096			real_info);
1097		Py_DECREF(real_info);
1098		return NULL;
1099	}
1100
1101	return PyObjC_ObjCToPython(@encode(CGError), &err);
1102}
1103
1104static PyObject*
1105m_CGUnregisterScreenRefreshCallback(
1106	PyObject* self __attribute__((__unused__)),
1107	PyObject* args)
1108{
1109	PyObject* callback;
1110	PyObject* userinfo;
1111
1112	if (!PyArg_ParseTuple(args, "OO", &callback, &userinfo)) {
1113		return NULL;
1114	}
1115
1116	PyObject* real_info = find_callback_info(&screen_refresh_callback, callback, userinfo);
1117
1118	if (real_info == NULL) {
1119		return NULL;
1120	}
1121
1122	PyObjC_DURING
1123		CGUnregisterScreenRefreshCallback(
1124			m_CGScreenRefreshCallback,
1125			real_info);
1126
1127	PyObjC_HANDLER
1128		PyObjCErr_FromObjC(localException);
1129
1130	PyObjC_ENDHANDLER
1131
1132	if (PyErr_Occurred()) {
1133		return NULL;
1134	}
1135
1136	remove_callback_info(&screen_refresh_callback, callback, userinfo);
1137
1138	Py_INCREF(Py_None);
1139	return Py_None;
1140}
1141
1142
1143/*
1144 * CGEventTapCreate
1145 * CGEventTapCreateForPSN
1146 *
1147 * Note that these wrappers leak some memory: the 'refcon' info passed to the
1148 * C code will never be deallocated. This is too bad, but can't be avoided with
1149 * the current CoreGraphics API.
1150 */
1151
1152static CGEventRef
1153m_CGEventTapCallBack(
1154	CGEventTapProxy proxy,
1155	CGEventType type,
1156	CGEventRef event,
1157	void * _info)
1158{
1159	PyObject* info = (PyObject*)_info;
1160
1161	PyGILState_STATE   state = PyGILState_Ensure();
1162
1163	PyObject* py_proxy;
1164	PyObject* py_type;
1165	PyObject* py_event;
1166
1167	py_proxy = PyObjC_ObjCToPython(@encode(CGEventTapProxy), &proxy);
1168	if (py_proxy == NULL) {
1169		PyObjCErr_ToObjCWithGILState(&state);
1170	}
1171
1172	py_type = PyObjC_ObjCToPython(@encode(CGEventType), &type);
1173	if (py_type == NULL) {
1174		Py_DECREF(py_proxy);
1175		PyObjCErr_ToObjCWithGILState(&state);
1176	}
1177
1178	py_event = PyObjC_ObjCToPython(@encode(CGEventRef), &event);
1179	if (py_event == NULL) {
1180		Py_DECREF(py_proxy);
1181		Py_DECREF(py_type);
1182		PyObjCErr_ToObjCWithGILState(&state);
1183	}
1184
1185	PyObject* result = PyObject_CallFunction(
1186			PyTuple_GET_ITEM(info, 0),
1187			"NNNO",
1188			py_proxy, py_type, py_event,  PyTuple_GET_ITEM(info, 1)
1189		);
1190	if (result == NULL) {
1191		PyObjCErr_ToObjCWithGILState(&state);
1192	}
1193
1194	if (PyObjC_PythonToObjC(@encode(CGEventRef), result, &event) < 0) {
1195		PyObjCErr_ToObjCWithGILState(&state);
1196	}
1197
1198	PyGILState_Release(state);
1199
1200	return event;
1201}
1202
1203static PyObject*
1204m_CGEventTapCreate(
1205	PyObject* self __attribute__((__unused__)),
1206	PyObject* args)
1207{
1208	PyObject* py_tap;
1209	PyObject* py_place;
1210	PyObject* py_options;
1211	PyObject* py_eventsOfInterest;
1212	PyObject* callback;
1213	PyObject* info;
1214	CGEventTapLocation tap;
1215	CGEventTapPlacement place;
1216	CGEventTapOptions options;
1217	CGEventMask eventsOfInterest;
1218	CFMachPortRef result = NULL;
1219
1220	if (!PyArg_ParseTuple(args, "OOOOO",
1221		&py_tap, &py_place, &py_options, &py_eventsOfInterest,
1222		&callback, &info)) {
1223
1224		return NULL;
1225	}
1226
1227	if (PyObjC_PythonToObjC(@encode(CGEventTapLocation), py_tap, &tap)<0) {
1228		return NULL;
1229	}
1230	if (PyObjC_PythonToObjC(@encode(CGEventTapPlacement), py_place, &place)<0) {
1231		return NULL;
1232	}
1233	if (PyObjC_PythonToObjC(@encode(CGEventTapOptions), py_options, &options)<0) {
1234		return NULL;
1235	}
1236	if (PyObjC_PythonToObjC(@encode(CGEventMask), py_eventsOfInterest, &eventsOfInterest)<0) {
1237		return NULL;
1238	}
1239
1240	PyObject* real_info = Py_BuildValue("OO", callback, info);
1241	if (real_info == NULL) {
1242		return NULL;
1243	}
1244
1245	PyObjC_DURING
1246		result = CGEventTapCreate(
1247				tap,
1248				place,
1249				options,
1250				eventsOfInterest,
1251				m_CGEventTapCallBack,
1252				(void*)real_info);
1253
1254	PyObjC_HANDLER
1255		PyObjCErr_FromObjC(localException);
1256	PyObjC_ENDHANDLER
1257
1258	if (PyErr_Occurred()) {
1259		return NULL;
1260	}
1261
1262	PyObject* retval = PyObjC_ObjCToPython(@encode(CFMachPortRef), &result);
1263	CFRelease(retval); /* Compensate for donated ref */
1264	return retval;
1265}
1266
1267static PyObject*
1268m_CGEventTapCreateForPSN(
1269	PyObject* self __attribute__((__unused__)),
1270	PyObject* args)
1271{
1272	PyObject* py_psn;
1273	PyObject* py_place;
1274	PyObject* py_options;
1275	PyObject* py_eventsOfInterest;
1276	PyObject* callback;
1277	PyObject* info;
1278	ProcessSerialNumber psn;
1279	CGEventTapPlacement place;
1280	CGEventTapOptions options;
1281	CGEventMask eventsOfInterest;
1282	CFMachPortRef result = NULL;
1283
1284	if (!PyArg_ParseTuple(args, "OOOOO",
1285		&py_psn, &py_place, &py_options, &py_eventsOfInterest,
1286		&callback, &info)) {
1287
1288		return NULL;
1289	}
1290
1291	if (PyObjC_PythonToObjC(@encode(ProcessSerialNumber), py_psn, &psn)<0) {
1292		return NULL;
1293	}
1294	if (PyObjC_PythonToObjC(@encode(CGEventTapPlacement), py_place, &place)<0) {
1295		return NULL;
1296	}
1297	if (PyObjC_PythonToObjC(@encode(CGEventTapOptions), py_options, &options)<0) {
1298		return NULL;
1299	}
1300	if (PyObjC_PythonToObjC(@encode(CGEventMask), py_eventsOfInterest, &eventsOfInterest)<0) {
1301		return NULL;
1302	}
1303
1304	PyObject* real_info = Py_BuildValue("OO", callback, info);
1305	if (real_info == NULL) {
1306		return NULL;
1307	}
1308
1309	PyObjC_DURING
1310		result = CGEventTapCreateForPSN(
1311				(void*)&psn,
1312				place,
1313				options,
1314				eventsOfInterest,
1315				m_CGEventTapCallBack,
1316				(void*)real_info);
1317
1318	PyObjC_HANDLER
1319		PyObjCErr_FromObjC(localException);
1320	PyObjC_ENDHANDLER
1321
1322	if (PyErr_Occurred()) {
1323		return NULL;
1324	}
1325
1326	PyObject* retval = PyObjC_ObjCToPython(@encode(CFMachPortRef), &result);
1327	CFRelease(retval); /* Compensate for donated ref */
1328	return retval;
1329}
1330
1331/*
1332 * CGPatternCreate
1333 */
1334
1335static void
1336m_CGPatternDrawPatternCallback(
1337	void* _info,
1338	CGContextRef context)
1339{
1340	PyObject* info = (PyObject*)_info;
1341
1342	PyGILState_STATE   state = PyGILState_Ensure();
1343
1344	PyObject* ctx = PyObjC_ObjCToPython(@encode(CGContextRef), &context);
1345	if (context == NULL) {
1346		PyObjCErr_ToObjCWithGILState(&state);
1347	}
1348
1349	PyObject* result = PyObject_CallFunction(
1350			PyTuple_GET_ITEM(info, 0),
1351			"ON",
1352			PyTuple_GET_ITEM(info, 1),
1353			ctx);
1354	if (result == NULL) {
1355		PyObjCErr_ToObjCWithGILState(&state);
1356	}
1357	Py_DECREF(result);
1358	PyGILState_Release(state);
1359}
1360
1361static void
1362m_CGPatternReleaseInfoCallback(void* _info)
1363{
1364	PyObject* info = (PyObject*)_info;
1365
1366	PyGILState_STATE   state = PyGILState_Ensure();
1367	Py_DECREF(info);
1368
1369	PyGILState_Release(state);
1370}
1371
1372static CGPatternCallbacks m_CGPatternCallbacks = {
1373	0,
1374	m_CGPatternDrawPatternCallback,		/* drawPattern */
1375	m_CGPatternReleaseInfoCallback,		/* releaseInfo */
1376};
1377
1378static PyObject*
1379m_CGPatternCreate(PyObject* self __attribute__((__unused__)),
1380		PyObject* args)
1381{
1382	PyObject* info;
1383	PyObject* py_bounds;
1384	PyObject* py_matrix;
1385	float xStep, yStep;
1386	PyObject* py_tiling;
1387	PyObject* py_isColored;
1388	PyObject* draw;
1389	CGRect bounds;
1390	CGAffineTransform matrix;
1391	CGPatternTiling tiling;
1392	int isColored;
1393
1394
1395	if (!PyArg_ParseTuple(args, "OOOffOOO",
1396		&info, &py_bounds, &py_matrix, &xStep, &yStep,
1397		&py_tiling, &py_isColored, &draw)) {
1398
1399		return NULL;
1400	}
1401	if (!PyCallable_Check(draw)) {
1402		PyErr_SetString(PyExc_TypeError, "drawPattern is not callable");
1403		return NULL;
1404	}
1405	if (PyObjC_PythonToObjC(@encode(CGRect), py_bounds, &bounds) < 0) {
1406		return NULL;
1407	}
1408	if (PyObjC_PythonToObjC(@encode(CGAffineTransform), py_matrix, &matrix) < 0) {
1409		return NULL;
1410	}
1411	if (PyObjC_PythonToObjC(@encode(CGPatternTiling), py_tiling, &tiling) < 0) {
1412		return NULL;
1413	}
1414	if (PyObject_IsTrue(py_isColored)) {
1415		isColored = true;
1416	} else {
1417		isColored = false;
1418	}
1419
1420	PyObject* real_info = Py_BuildValue("OO", draw, info);
1421	if (real_info == NULL) {
1422		return NULL;
1423	}
1424
1425	CGPatternRef result = NULL;
1426
1427	PyObjC_DURING
1428		result = CGPatternCreate(
1429			(void*)real_info,
1430			bounds,
1431			matrix,
1432			xStep,
1433			yStep,
1434			tiling,
1435			isColored,
1436			&m_CGPatternCallbacks);
1437
1438	PyObjC_HANDLER
1439		PyObjCErr_FromObjC(localException);
1440	PyObjC_ENDHANDLER
1441
1442	if (PyErr_Occurred()) {
1443		Py_DECREF(real_info);
1444		return NULL;
1445	}
1446
1447	PyObject* retval = PyObjC_ObjCToPython(@encode(CGPatternRef), &result);
1448	CFRelease(result);
1449	return retval;
1450}
1451
1452/*
1453 * CGPSConverterCreate
1454 */
1455
1456static void
1457m_CGPSConverterBeginDocumentCallback(void* _info)
1458{
1459	PyObject* info = (PyObject*)_info;
1460
1461	PyGILState_STATE   state = PyGILState_Ensure();
1462
1463	PyObject* result = PyObject_CallFunction(
1464		PyTuple_GET_ITEM(info, 1),
1465		"O", PyTuple_GET_ITEM(info, 0));
1466
1467	if (result == NULL) {
1468		PyObjCErr_ToObjCWithGILState(&state);
1469	}
1470	Py_DECREF(result);
1471
1472	PyGILState_Release(state);
1473}
1474
1475static void
1476m_CGPSConverterBeginPageCallback(void* _info,
1477		size_t pageNumber, CFDictionaryRef pageInfo)
1478{
1479	PyObject* info = (PyObject*)_info;
1480
1481	PyGILState_STATE   state = PyGILState_Ensure();
1482
1483	PyObject* result = PyObject_CallFunction(
1484		PyTuple_GET_ITEM(info, 3),
1485		"OlN",
1486		PyTuple_GET_ITEM(info, 0),
1487		(long)pageNumber,
1488		PyObjC_ObjCToPython(@encode(CFDictionaryRef), &pageInfo));
1489
1490	if (result == NULL) {
1491		PyObjCErr_ToObjCWithGILState(&state);
1492	}
1493	Py_DECREF(result);
1494
1495	PyGILState_Release(state);
1496}
1497
1498static void
1499m_CGPSConverterEndDocumentCallback(void* _info, bool success)
1500{
1501	PyObject* info = (PyObject*)_info;
1502
1503	PyGILState_STATE   state = PyGILState_Ensure();
1504
1505
1506	PyObject* result = PyObject_CallFunction(
1507		PyTuple_GET_ITEM(info, 2),
1508		"ON", PyTuple_GET_ITEM(info, 0),
1509		PyBool_FromLong(success));
1510
1511	if (result == NULL) {
1512		PyObjCErr_ToObjCWithGILState(&state);
1513	}
1514	Py_DECREF(result);
1515
1516	PyGILState_Release(state);
1517}
1518
1519static void
1520m_CGPSConverterEndPageCallback(void* _info, size_t pageNumber,
1521		CFDictionaryRef pageInfo)
1522{
1523	PyObject* info = (PyObject*)_info;
1524
1525	PyGILState_STATE   state = PyGILState_Ensure();
1526
1527	PyObject* result = PyObject_CallFunction(
1528		PyTuple_GET_ITEM(info, 4),
1529		"OlN",
1530		PyTuple_GET_ITEM(info, 0),
1531		(long)pageNumber,
1532		PyObjC_ObjCToPython(@encode(CFDictionaryRef), &pageInfo));
1533
1534	if (result == NULL) {
1535		PyObjCErr_ToObjCWithGILState(&state);
1536	}
1537	Py_DECREF(result);
1538
1539	PyGILState_Release(state);
1540}
1541
1542static void
1543m_CGPSConverterMessageCallback(void* _info, CFStringRef message)
1544{
1545	PyObject* info = (PyObject*)_info;
1546
1547	PyGILState_STATE   state = PyGILState_Ensure();
1548
1549	PyObject* result = PyObject_CallFunction(
1550		PyTuple_GET_ITEM(info, 6),
1551		"ON",
1552		PyTuple_GET_ITEM(info, 0),
1553		PyObjC_ObjCToPython(@encode(CFStringRef), &message));
1554
1555	if (result == NULL) {
1556		PyObjCErr_ToObjCWithGILState(&state);
1557	}
1558	Py_DECREF(result);
1559
1560	PyGILState_Release(state);
1561}
1562
1563static void
1564m_CGPSConverterProgressCallback(void* _info)
1565{
1566	PyObject* info = (PyObject*)_info;
1567
1568	PyGILState_STATE   state = PyGILState_Ensure();
1569
1570
1571	PyObject* result = PyObject_CallFunction(
1572		PyTuple_GET_ITEM(info, 5),
1573		"O", PyTuple_GET_ITEM(info, 0));
1574
1575	if (result == NULL) {
1576		PyObjCErr_ToObjCWithGILState(&state);
1577	}
1578	Py_DECREF(result);
1579
1580	PyGILState_Release(state);
1581}
1582
1583static void
1584m_CGPSConverterReleaseInfoCallback(void* _info)
1585{
1586	PyObject* info = (PyObject*)_info;
1587
1588	PyGILState_STATE   state = PyGILState_Ensure();
1589
1590	if (PyTuple_GET_ITEM(info, 7) != Py_None) {
1591		PyObject* result = PyObject_CallFunction(
1592			PyTuple_GET_ITEM(info, 7),
1593			"O", PyTuple_GET_ITEM(info, 0));
1594
1595		if (result == NULL) {
1596			Py_DECREF(info);
1597			PyObjCErr_ToObjCWithGILState(&state);
1598		}
1599		Py_DECREF(result);
1600	}
1601	Py_DECREF(info);
1602
1603	PyGILState_Release(state);
1604}
1605
1606
1607static CGPSConverterCallbacks m_CGPSConverterCallbacks = {
1608	0,
1609	m_CGPSConverterBeginDocumentCallback,	/* beginDocument */
1610	m_CGPSConverterEndDocumentCallback,	/* endDocument */
1611	m_CGPSConverterBeginPageCallback,	/* beginPage */
1612	m_CGPSConverterEndPageCallback,		/* endPage */
1613	m_CGPSConverterProgressCallback,	/* noteProgress */
1614	m_CGPSConverterMessageCallback,		/* noteMessage */
1615	m_CGPSConverterReleaseInfoCallback	/* releaseInfo */
1616};
1617
1618static PyObject*
1619m_CGPSConverterCreate(
1620	PyObject* self __attribute__((__unused__)),
1621	PyObject* args)
1622{
1623	PyObject* info;
1624	PyObject* py_options;
1625	PyObject* beginDocument;
1626	PyObject* endDocument;
1627	PyObject* beginPage;
1628	PyObject* endPage;
1629	PyObject* noteProgress;
1630	PyObject* noteMessage;
1631	PyObject* releaseInfo;
1632	CFDictionaryRef options;
1633	CGPSConverterRef result = NULL;
1634
1635	if (!PyArg_ParseTuple(args, "O(OOOOOOO)O",
1636		&info,
1637		&beginDocument, &endDocument,
1638		&beginPage, &endPage,
1639		&noteProgress, &noteMessage,
1640		&releaseInfo, &py_options)) {
1641
1642		return NULL;
1643	}
1644
1645	if (!PyCallable_Check(beginDocument)) {
1646		PyErr_SetString(PyExc_TypeError, "beginDocument not callable");
1647		return NULL;
1648	}
1649	if (!PyCallable_Check(endDocument)) {
1650		PyErr_SetString(PyExc_TypeError, "endDocument not callable");
1651		return NULL;
1652	}
1653	if (!PyCallable_Check(beginPage)) {
1654		PyErr_SetString(PyExc_TypeError, "beginPage not callable");
1655		return NULL;
1656	}
1657	if (!PyCallable_Check(endPage)) {
1658		PyErr_SetString(PyExc_TypeError, "endPage not callable");
1659		return NULL;
1660	}
1661	if (!PyCallable_Check(noteProgress)) {
1662		PyErr_SetString(PyExc_TypeError, "noteProgress not callable");
1663		return NULL;
1664	}
1665	if (!PyCallable_Check(noteMessage)) {
1666		PyErr_SetString(PyExc_TypeError, "noteMessage not callable");
1667		return NULL;
1668	}
1669	if (PyObjC_PythonToObjC(@encode(CFDictionaryRef), py_options, &options)<0) {
1670		return NULL;
1671	}
1672
1673	PyObject* real_info = Py_BuildValue("OOOOOOOO",
1674			info,
1675			beginDocument, endDocument,
1676			beginPage, endPage,
1677			noteProgress, noteMessage,
1678			releaseInfo);
1679
1680	PyObjC_DURING
1681		result = CGPSConverterCreate(real_info,
1682				&m_CGPSConverterCallbacks,
1683				options);
1684
1685	PyObjC_HANDLER
1686		PyObjCErr_FromObjC(localException);
1687	PyObjC_ENDHANDLER
1688
1689	if (PyErr_Occurred()) {
1690		Py_DECREF(real_info);
1691		return NULL;
1692	}
1693
1694	PyObject* v = PyObjC_ObjCToPython(@encode(CGPSConverterRef), &result);
1695	CFRelease(result);
1696	return v;
1697}
1698
1699
1700static PyMethodDef m_methods[] = {
1701	{
1702		"CGDataConsumerCreate",
1703		(PyCFunction)m_CGDataConsumerCreate,
1704		METH_VARARGS,
1705		doc_CGDataConsumerCreate
1706	},
1707
1708#ifndef OS_TIGER
1709
1710	{
1711		"CGDataProviderCreateSequential",
1712		(PyCFunction)m_CGDataProviderCreateSequential,
1713		METH_VARARGS,
1714		doc_CGDataProviderCreateSequential
1715	},
1716
1717#endif
1718	{
1719		"CGDataProviderCreateWithData",
1720		(PyCFunction)m_CGDataProviderCreateWithData,
1721		METH_VARARGS,
1722		doc_CGDataProviderCreateWithData
1723	},
1724
1725	{
1726		"CGFunctionCreate",
1727		(PyCFunction)m_CGFunctionCreate,
1728		METH_VARARGS,
1729		doc_CGFunctionCreate
1730	},
1731	{
1732		"CGDisplayRegisterReconfigurationCallback",
1733		(PyCFunction)m_CGDisplayRegisterReconfigurationCallback,
1734		METH_VARARGS,
1735		NULL
1736	},
1737	{
1738		"CGDisplayRemoveReconfigurationCallback",
1739		(PyCFunction)m_CGDisplayRemoveReconfigurationCallback,
1740		METH_VARARGS,
1741		NULL
1742	},
1743	{
1744		"CGScreenRegisterMoveCallback",
1745		(PyCFunction)m_CGScreenRegisterMoveCallback,
1746		METH_VARARGS,
1747		NULL
1748	},
1749	{
1750		"CGScreenUnregisterMoveCallback",
1751		(PyCFunction)m_CGScreenUnregisterMoveCallback,
1752		METH_VARARGS,
1753		NULL
1754	},
1755	{
1756		"CGRegisterScreenRefreshCallback",
1757		(PyCFunction)m_CGRegisterScreenRefreshCallback,
1758		METH_VARARGS,
1759		NULL
1760	},
1761	{
1762		"CGUnregisterScreenRefreshCallback",
1763		(PyCFunction)m_CGUnregisterScreenRefreshCallback,
1764		METH_VARARGS,
1765		NULL
1766	},
1767	{
1768		"CGEventTapCreate",
1769		(PyCFunction)m_CGEventTapCreate,
1770		METH_VARARGS,
1771		NULL
1772	},
1773	{
1774		"CGEventTapCreateForPSN",
1775		(PyCFunction)m_CGEventTapCreateForPSN,
1776		METH_VARARGS,
1777		NULL
1778	},
1779	{
1780		"CGPatternCreate",
1781		(PyCFunction)m_CGPatternCreate,
1782		METH_VARARGS,
1783		NULL
1784	},
1785	{
1786		"CGPSConverterCreate",
1787		(PyCFunction)m_CGPSConverterCreate,
1788		METH_VARARGS,
1789		NULL
1790	},
1791
1792	{ 0, 0, 0, }
1793};
1794
1795void init_callbacks(void);
1796void init_callbacks(void)
1797{
1798	PyObject* m = Py_InitModule4("_callbacks", m_methods,
1799		NULL, NULL, PYTHON_API_VERSION);
1800	PyObject* md = PyModule_GetDict(m);
1801
1802        if (PyObjC_ImportAPI(m) < 0) { return; }
1803
1804#ifndef OS_TIGER
1805	if (CGDataProviderCreateSequential == NULL) {
1806		PyDict_DelItemString(md, "CGDataProviderCreateSequential");
1807	}
1808#endif
1809
1810
1811}
1812