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