1# This script generates a Python interface for an Apple Macintosh Manager.
2# It uses the "bgen" package to generate C code.
3# The function specifications are generated by scanning the mamager's header file,
4# using the "scantools" package (customized for this particular manager).
5
6#error missing SetActionFilter
7
8import string
9
10# Declarations that change for each manager
11MACHEADERFILE = 'Movies.h'              # The Apple header file
12MODNAME = '_Qt'                         # The name of the module
13OBJECTNAME = 'Movie'                    # The basic name of the objects used here
14
15# The following is *usually* unchanged but may still require tuning
16MODPREFIX = 'Qt'                        # The prefix for module-wide routines
17OBJECTTYPE = "Movie"            # The C type used to represent them
18OBJECTPREFIX = MODPREFIX + 'Obj'        # The prefix for object methods
19INPUTFILE = string.lower(MODPREFIX) + 'gen.py' # The file generated by the scanner
20OUTPUTFILE = MODNAME + "module.c"       # The file generated by this program
21
22from macsupport import *
23
24# Create the type objects
25
26includestuff = includestuff + """
27#include <QuickTime/QuickTime.h>
28
29
30#ifdef USE_TOOLBOX_OBJECT_GLUE
31extern PyObject *_TrackObj_New(Track);
32extern int _TrackObj_Convert(PyObject *, Track *);
33extern PyObject *_MovieObj_New(Movie);
34extern int _MovieObj_Convert(PyObject *, Movie *);
35extern PyObject *_MovieCtlObj_New(MovieController);
36extern int _MovieCtlObj_Convert(PyObject *, MovieController *);
37extern PyObject *_TimeBaseObj_New(TimeBase);
38extern int _TimeBaseObj_Convert(PyObject *, TimeBase *);
39extern PyObject *_UserDataObj_New(UserData);
40extern int _UserDataObj_Convert(PyObject *, UserData *);
41extern PyObject *_MediaObj_New(Media);
42extern int _MediaObj_Convert(PyObject *, Media *);
43
44#define TrackObj_New _TrackObj_New
45#define TrackObj_Convert _TrackObj_Convert
46#define MovieObj_New _MovieObj_New
47#define MovieObj_Convert _MovieObj_Convert
48#define MovieCtlObj_New _MovieCtlObj_New
49#define MovieCtlObj_Convert _MovieCtlObj_Convert
50#define TimeBaseObj_New _TimeBaseObj_New
51#define TimeBaseObj_Convert _TimeBaseObj_Convert
52#define UserDataObj_New _UserDataObj_New
53#define UserDataObj_Convert _UserDataObj_Convert
54#define MediaObj_New _MediaObj_New
55#define MediaObj_Convert _MediaObj_Convert
56#endif
57
58/* Macro to allow us to GetNextInterestingTime without duration */
59#define GetMediaNextInterestingTimeOnly(media, flags, time, rate, rv) \
60                        GetMediaNextInterestingTime(media, flags, time, rate, rv, NULL)
61
62/*
63** Parse/generate time records
64*/
65static PyObject *
66QtTimeRecord_New(TimeRecord *itself)
67{
68        if (itself->base)
69                return Py_BuildValue("O&lO&", PyMac_Buildwide, &itself->value, itself->scale,
70                        TimeBaseObj_New, itself->base);
71        else
72                return  Py_BuildValue("O&lO", PyMac_Buildwide, &itself->value, itself->scale,
73                        Py_None);
74}
75
76static int
77QtTimeRecord_Convert(PyObject *v, TimeRecord *p_itself)
78{
79        PyObject *base = NULL;
80        if( !PyArg_ParseTuple(v, "O&l|O", PyMac_Getwide, &p_itself->value, &p_itself->scale,
81                        &base) )
82                return 0;
83        if ( base == NULL || base == Py_None )
84                p_itself->base = NULL;
85        else
86                if ( !TimeBaseObj_Convert(base, &p_itself->base) )
87                        return 0;
88        return 1;
89}
90
91static int
92QtMusicMIDIPacket_Convert(PyObject *v, MusicMIDIPacket *p_itself)
93{
94        int dummy;
95
96        if( !PyArg_ParseTuple(v, "hls#", &p_itself->length, &p_itself->reserved, p_itself->data, dummy) )
97                return 0;
98        return 1;
99}
100
101
102
103"""
104
105initstuff = initstuff + """
106        PyMac_INIT_TOOLBOX_OBJECT_NEW(Track, TrackObj_New);
107        PyMac_INIT_TOOLBOX_OBJECT_CONVERT(Track, TrackObj_Convert);
108        PyMac_INIT_TOOLBOX_OBJECT_NEW(Movie, MovieObj_New);
109        PyMac_INIT_TOOLBOX_OBJECT_CONVERT(Movie, MovieObj_Convert);
110        PyMac_INIT_TOOLBOX_OBJECT_NEW(MovieController, MovieCtlObj_New);
111        PyMac_INIT_TOOLBOX_OBJECT_CONVERT(MovieController, MovieCtlObj_Convert);
112        PyMac_INIT_TOOLBOX_OBJECT_NEW(TimeBase, TimeBaseObj_New);
113        PyMac_INIT_TOOLBOX_OBJECT_CONVERT(TimeBase, TimeBaseObj_Convert);
114        PyMac_INIT_TOOLBOX_OBJECT_NEW(UserData, UserDataObj_New);
115        PyMac_INIT_TOOLBOX_OBJECT_CONVERT(UserData, UserDataObj_Convert);
116        PyMac_INIT_TOOLBOX_OBJECT_NEW(Media, MediaObj_New);
117        PyMac_INIT_TOOLBOX_OBJECT_CONVERT(Media, MediaObj_Convert);
118"""
119
120# Our (opaque) objects
121Movie = OpaqueByValueType('Movie', 'MovieObj')
122NullMovie = FakeType("(Movie)0")
123Track = OpaqueByValueType('Track', 'TrackObj')
124Media = OpaqueByValueType('Media', 'MediaObj')
125UserData = OpaqueByValueType('UserData', 'UserDataObj')
126TimeBase = OpaqueByValueType('TimeBase', 'TimeBaseObj')
127MovieController = OpaqueByValueType('MovieController', 'MovieCtlObj')
128IdleManager = OpaqueByValueType('IdleManager', 'IdleManagerObj')
129SGOutput = OpaqueByValueType('SGOutput', 'SGOutputObj')
130
131# Other opaque objects
132Component = OpaqueByValueType('Component', 'CmpObj')
133MediaHandlerComponent = OpaqueByValueType('MediaHandlerComponent', 'CmpObj')
134DataHandlerComponent = OpaqueByValueType('DataHandlerComponent', 'CmpObj')
135CompressorComponent = OpaqueByValueType('CompressorComponent', 'CmpObj')
136DecompressorComponent = OpaqueByValueType('DecompressorComponent', 'CmpObj')
137CodecComponent = OpaqueByValueType('CodecComponent', 'CmpObj')
138
139# Despite their names, these are all ComponentInstance types
140GraphicsImportComponent = OpaqueByValueType('GraphicsImportComponent', 'CmpInstObj')
141GraphicsExportComponent = OpaqueByValueType('GraphicsExportComponent', 'CmpInstObj')
142ImageTranscoderComponent = OpaqueByValueType('ImageTranscoderComponent', 'CmpInstObj')
143MovieImportComponent = OpaqueByValueType('MovieImportComponent', 'CmpInstObj')
144MovieExportComponent = OpaqueByValueType('MovieExportComponent', 'CmpInstObj')
145TextExportComponent = OpaqueByValueType('TextExportComponent', 'CmpInstObj')
146GraphicImageMovieImportComponent = OpaqueByValueType('GraphicImageMovieImportComponent', 'CmpInstObj')
147pnotComponent = OpaqueByValueType('pnotComponent', 'CmpInstObj')
148# DataCompressorComponent, DataDecompressorComponent would go here
149DataCodecComponent = OpaqueByValueType('DataCodecComponent', 'CmpInstObj')
150TweenerComponent = OpaqueByValueType('TweenerComponent', 'CmpInstObj')
151QTVideoOutputComponent = OpaqueByValueType('QTVideoOutputComponent', 'CmpInstObj')
152SeqGrabComponent = OpaqueByValueType('SeqGrabComponent', 'CmpInstObj')
153VideoDigitizerComponent = OpaqueByValueType('VideoDigitizerComponent', 'CmpInstObj')
154
155ComponentInstance = OpaqueByValueType('ComponentInstance', 'CmpInstObj')
156MediaHandler = OpaqueByValueType('MediaHandler', 'CmpInstObj')
157DataHandler = OpaqueByValueType('DataHandler', 'CmpInstObj')
158SGChannel = OpaqueByValueType('SGChannel', 'CmpInstObj')
159TunePlayer = OpaqueByValueType('TunePlayer', 'CmpInstObj')
160MusicComponent = OpaqueByValueType('MusicComponent', 'CmpInstObj')
161NoteAllocator = OpaqueByValueType('NoteAllocator', 'CmpInstObj')
162QTMIDIComponent = OpaqueByValueType('QTMIDIComponent', 'CmpInstObj')
163
164ConstFSSpecPtr = FSSpec_ptr
165GrafPtr = OpaqueByValueType("GrafPtr", "GrafObj")
166Byte = Boolean # XXXX For GetPaused and SetPaused
167
168RgnHandle = OpaqueByValueType("RgnHandle", "ResObj")
169PicHandle = OpaqueByValueType("PicHandle", "ResObj")
170CTabHandle = OpaqueByValueType("CTabHandle", "ResObj")
171PixMapHandle = OpaqueByValueType("PixMapHandle", "ResObj")
172SampleDescriptionHandle = OpaqueByValueType("SampleDescriptionHandle", "ResObj")
173ImageDescriptionHandle = OpaqueByValueType("ImageDescriptionHandle", "ResObj")
174TextDescriptionHandle = OpaqueByValueType("TextDescriptionHandle", "ResObj")
175TEHandle = OpaqueByValueType("TEHandle", "ResObj")
176CGrafPtr = OpaqueByValueType("CGrafPtr", "GrafObj")
177GDHandle = OpaqueByValueType("GDHandle", "OptResObj")
178AliasHandle = OpaqueByValueType("AliasHandle", "ResObj")
179SoundDescriptionHandle = OpaqueByValueType("SoundDescriptionHandle", "ResObj")
180VdigBufferRecListHandle = OpaqueByValueType("VdigBufferRecListHandle", "ResObj")
181VDCompressionListHandle = OpaqueByValueType("VDCompressionListHandle", "ResObj")
182TimeCodeDescriptionHandle = OpaqueByValueType("TimeCodeDescriptionHandle", "ResObj")
183DataHFileTypeOrderingHandle = OpaqueByValueType("DataHFileTypeOrderingHandle", "ResObj")
184QTMIDIPortListHandle = OpaqueByValueType("QTMIDIPortListHandle", "ResObj")
185GenericKnobDescriptionListHandle =  OpaqueByValueType("GenericKnobDescriptionListHandle", "ResObj")
186InstrumentInfoListHandle = OpaqueByValueType("InstrumentInfoListHandle", "ResObj")
187# Silly Apple, passing an OStype by reference...
188OSType_ptr = OpaqueType("OSType", "PyMac_BuildOSType", "PyMac_GetOSType")
189# And even sillier: passing floats by address
190float_ptr = ByAddressType("float", "f")
191
192RGBColor = OpaqueType("RGBColor", "QdRGB")
193RGBColor_ptr = RGBColor
194TimeRecord = OpaqueType("TimeRecord", "QtTimeRecord")
195TimeRecord_ptr = TimeRecord
196MusicMIDIPacket = OpaqueType("MusicMIDIPacket", "QtMusicMIDIPacket")
197MusicMIDIPacket_ptr = MusicMIDIPacket
198
199# Non-opaque types, mostly integer-ish
200TimeValue = Type("TimeValue", "l")
201TimeScale = Type("TimeScale", "l")
202TimeBaseFlags = Type("TimeBaseFlags", "l")
203QTCallBackFlags = Type("QTCallBackFlags", "H")
204TimeBaseStatus = Type("TimeBaseStatus", "l")
205QTCallBackType = Type("QTCallBackType", "H")
206nextTimeFlagsEnum = Type("nextTimeFlagsEnum", "H")
207createMovieFileFlagsEnum = Type("createMovieFileFlagsEnum", "l")
208movieFlattenFlagsEnum = Type("movieFlattenFlagsEnum", "l")
209dataRefAttributesFlags = Type("dataRefAttributesFlags", "l")
210playHintsEnum = Type("playHintsEnum", "l")
211mediaHandlerFlagsEnum = Type("mediaHandlerFlagsEnum", "l")
212ComponentResult = Type("ComponentResult", "l")
213VideoDigitizerError = Type("ComponentResult", "l")
214HandlerError = Type("HandlerError", "l")
215Ptr = InputOnlyType("Ptr", "s")
216StringPtr = Type("StringPtr", "s")
217UnsignedLongPtr = Type("unsigned long *", "s")
218mcactionparams = InputOnlyType("void *", "s")
219QTParameterDialog = Type("QTParameterDialog", "l")
220QTAtomID = Type("QTAtomID", "l")
221MCInterfaceElement = Type("MCInterfaceElement", "l")
222CodecType = OSTypeType("CodecType")
223GWorldPtr = OpaqueByValueType("GWorldPtr", "GWorldObj")
224QTFloatSingle = Type("QTFloatSingle", "f")
225CodecQ = Type("CodecQ", "l")
226MusicController = Type("MusicController", "l")
227
228# Could-not-be-bothered-types (NewMovieFromFile)
229dummyshortptr = FakeType('(short *)0')
230dummyStringPtr = FakeType('(StringPtr)0')
231
232# Not-quite-sure-this-is-okay types
233AtomicInstrument = OpaqueByValueType("AtomicInstrument", "ResObj")
234AtomicInstrumentPtr = InputOnlyType("AtomicInstrumentPtr", "s")
235
236# XXXX Need to override output_tp_newBody() to allow for None initializer.
237class QtGlobalObjectDefinition(PEP253Mixin, GlobalObjectDefinition):
238    def outputCheckNewArg(self):
239        # We don't allow NULL pointers to be returned by QuickTime API calls,
240        # in stead we raise an exception
241        Output("""if (itself == NULL) {
242                                PyErr_SetString(Qt_Error,"Cannot create %s from NULL pointer");
243                                return NULL;
244                        }""", self.name)
245
246    def outputCheckConvertArg(self):
247        # But what we do allow is passing None whereever a quicktime object is
248        # expected, and pass this as NULL to the API routines. Note you can
249        # call methods too by creating an object with None as the initializer.
250        Output("if (v == Py_None)")
251        OutLbrace()
252        Output("*p_itself = NULL;")
253        Output("return 1;")
254        OutRbrace()
255
256class MovieObjectDefinition(QtGlobalObjectDefinition):
257    def outputFreeIt(self, itselfname):
258        Output("if (%s) DisposeMovie(%s);", itselfname, itselfname)
259
260class TrackObjectDefinition(QtGlobalObjectDefinition):
261    def outputFreeIt(self, itselfname):
262        Output("if (%s) DisposeMovieTrack(%s);", itselfname, itselfname)
263
264class MediaObjectDefinition(QtGlobalObjectDefinition):
265    def outputFreeIt(self, itselfname):
266        Output("if (%s) DisposeTrackMedia(%s);", itselfname, itselfname)
267
268class UserDataObjectDefinition(QtGlobalObjectDefinition):
269    def outputFreeIt(self, itselfname):
270        Output("if (%s) DisposeUserData(%s);", itselfname, itselfname)
271
272class TimeBaseObjectDefinition(QtGlobalObjectDefinition):
273    pass
274
275class MovieCtlObjectDefinition(QtGlobalObjectDefinition):
276    def outputFreeIt(self, itselfname):
277        Output("if (%s) DisposeMovieController(%s);", itselfname, itselfname)
278
279class IdleManagerObjectDefinition(QtGlobalObjectDefinition):
280    pass
281
282class SGOutputObjectDefinition(QtGlobalObjectDefinition):
283    # XXXX I'm not sure I fully understand how SGOutput works. It seems it's always tied
284    # to a specific SeqGrabComponent, but I'm not 100% sure. Also, I'm not sure all the
285    # routines that return an SGOutput actually return a *new* SGOutput. Need to read up on
286    # this.
287    pass
288
289
290# From here on it's basically all boiler plate...
291
292# Create the generator groups and link them
293module = MacModule(MODNAME, MODPREFIX, includestuff, finalstuff, initstuff)
294Movie_object = MovieObjectDefinition('Movie', 'MovieObj', 'Movie')
295Track_object = TrackObjectDefinition('Track', 'TrackObj', 'Track')
296Media_object = MediaObjectDefinition('Media', 'MediaObj', 'Media')
297UserData_object = UserDataObjectDefinition('UserData', 'UserDataObj', 'UserData')
298TimeBase_object = TimeBaseObjectDefinition('TimeBase', 'TimeBaseObj', 'TimeBase')
299MovieController_object = MovieCtlObjectDefinition('MovieController', 'MovieCtlObj', 'MovieController')
300IdleManager_object = IdleManagerObjectDefinition('IdleManager', 'IdleManagerObj', 'IdleManager')
301SGOutput_object = SGOutputObjectDefinition('SGOutput', 'SGOutputObj', 'SGOutput')
302
303module.addobject(IdleManager_object)
304module.addobject(MovieController_object)
305module.addobject(TimeBase_object)
306module.addobject(UserData_object)
307module.addobject(Media_object)
308module.addobject(Track_object)
309module.addobject(Movie_object)
310module.addobject(SGOutput_object)
311
312# Test which types we are still missing.
313execfile(string.lower(MODPREFIX) + 'typetest.py')
314
315# Create the generator classes used to populate the lists
316Function = OSErrWeakLinkFunctionGenerator
317Method = OSErrWeakLinkMethodGenerator
318
319# Create and populate the lists
320functions = []
321IdleManager_methods = []
322MovieController_methods = []
323TimeBase_methods = []
324UserData_methods = []
325Media_methods = []
326Track_methods = []
327Movie_methods = []
328SGOutput_methods = []
329execfile(INPUTFILE)
330
331#
332# Some functions from ImageCompression.h that we need:
333ICMAlignmentProcRecordPtr = FakeType('(ICMAlignmentProcRecordPtr)0')
334dummyRect = FakeType('(Rect *)0')
335
336f = Function(void, 'AlignWindow',
337        (WindowPtr, 'wp', InMode),
338        (Boolean, 'front', InMode),
339        (dummyRect, 'alignmentRect', InMode),
340        (ICMAlignmentProcRecordPtr, 'alignmentProc', InMode),
341)
342functions.append(f)
343
344f = Function(void, 'DragAlignedWindow',
345        (WindowPtr, 'wp', InMode),
346        (Point, 'startPt', InMode),
347        (Rect_ptr, 'boundsRect', InMode),
348        (dummyRect, 'alignmentRect', InMode),
349        (ICMAlignmentProcRecordPtr, 'alignmentProc', InMode),
350)
351functions.append(f)
352
353# And we want the version of MoviesTask without a movie argument
354f = Function(void, 'MoviesTask',
355    (NullMovie, 'theMovie', InMode),
356    (long, 'maxMilliSecToUse', InMode),
357)
358functions.append(f)
359
360# And we want a GetMediaNextInterestingTime without duration
361f = Method(void, 'GetMediaNextInterestingTimeOnly',
362    (Media, 'theMedia', InMode),
363    (short, 'interestingTimeFlags', InMode),
364    (TimeValue, 'time', InMode),
365    (Fixed, 'rate', InMode),
366    (TimeValue, 'interestingTime', OutMode),
367)
368Media_methods.append(f)
369
370# add the populated lists to the generator groups
371# (in a different wordl the scan program would generate this)
372for f in functions: module.add(f)
373for f in MovieController_methods: MovieController_object.add(f)
374for f in TimeBase_methods: TimeBase_object.add(f)
375for f in UserData_methods: UserData_object.add(f)
376for f in Media_methods: Media_object.add(f)
377for f in Track_methods: Track_object.add(f)
378for f in Movie_methods: Movie_object.add(f)
379
380# generate output (open the output file as late as possible)
381SetOutputFileName(OUTPUTFILE)
382module.generate()
383