blob: f653e362cb8d189469d9fb48acbd67265196e1d0 [file] [log] [blame]
Guido van Rossum2d167031994-09-16 10:54:21 +00001/***********************************************************
2Copyright 1991, 1992, 1993, 1994 by Stichting Mathematisch Centrum,
3Amsterdam, The Netherlands.
4
5 All Rights Reserved
6
7Permission to use, copy, modify, and distribute this software and its
8documentation for any purpose and without fee is hereby granted,
9provided that the above copyright notice appear in all copies and that
10both that copyright notice and this permission notice appear in
11supporting documentation, and that the names of Stichting Mathematisch
12Centrum or CWI not be used in advertising or publicity pertaining to
13distribution of the software without specific, written prior permission.
14
15STICHTING MATHEMATISCH CENTRUM DISCLAIMS ALL WARRANTIES WITH REGARD TO
16THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND
17FITNESS, IN NO EVENT SHALL STICHTING MATHEMATISCH CENTRUM BE LIABLE
18FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
19WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
20ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT
21OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
22
23******************************************************************/
24
25/* Macintosh OS-specific interface */
26
27#include "Python.h"
28
29#include <stdio.h>
30#include <string.h>
31#include <errno.h>
32
33#include <Resources.h>
34#include <Sound.h>
35
36/*----------------------------------------------------------------------*/
37/* General tools */
38
39static PyObject *MacOS_Error; /* Exception MacOS.Error */
40
41/* Set a MAC-specific error from errno, and return NULL; return None if no error */
42static PyObject *
43Err(OSErr err)
44{
45 char buf[100];
46 PyObject *v;
47 if (err == 0) {
48 Py_INCREF(Py_None);
49 return Py_None;
50 }
51 sprintf(buf, "Mac OS error code %d", (int)err);
52 v = Py_BuildValue("(is)", (int)err, buf);
53 PyErr_SetObject(MacOS_Error, v);
54 Py_DECREF(v);
55 return NULL;
56}
57
58/* Check for a ResType argument */
59static int
60GetOSType(PyObject *v, ResType *pr)
61{
62 if (!PyString_Check(v) || PyString_Size(v) != 4) {
63 PyErr_SetString(MacOS_Error,
64 "OSType arg must be string of 4 chars");
65 return 0;
66 }
67 memcpy((char *)pr, PyString_AsString(v), 4);
68 return 1;
69}
70
71/* Check for a Str255 argument */
72static int
73GetStr255(PyObject *v, Str255 pbuf)
74{
75 int len;
76 if (!PyString_Check(v) || (len = PyString_Size(v)) > 255) {
77 PyErr_SetString(MacOS_Error,
78 "Str255 arg must be string <= 255 chars");
79 return 0;
80 }
81 pbuf[0] = len;
82 memcpy((char *)(pbuf+1), PyString_AsString(v), len);
83 return 1;
84}
85
86/*----------------------------------------------------------------------*/
87/* Resource objects */
88
89typedef struct {
90 OB_HEAD
91 Handle h;
92} RsrcObject;
93
94staticforward PyTypeObject RsrcType;
95
96#define RsrcObject_Check(r) ((r)->ob_type == &RsrcType)
97
98static RsrcObject *
99Rsrc_FromHandle(Handle h)
100{
101 RsrcObject *r;
102 if (h == NULL)
103 return (RsrcObject *)Err(ResError());
104 r = PyObject_NEW(RsrcObject, &RsrcType);
105 if (r != NULL)
106 r->h = h;
107 return r;
108}
109
110static void
111Rsrc_Dealloc(RsrcObject *r)
112{
113 PyMem_DEL(r);
114}
115
116static PyObject *
117Rsrc_GetResInfo(RsrcObject *r, PyObject *args)
118{
119 short id;
120 ResType type;
121 Str255 name;
122 if (!PyArg_Parse(args, "()"))
123 return NULL;
124 GetResInfo(r->h, &id, &type, name);
125 return Py_BuildValue("(is#s#)",
126 (int)id, (char *)&type, 4, name+1, (int)name[0]);
127}
128
129static PyMethodDef Rsrc_Methods[] = {
130 {"GetResInfo", (PyCFunction)Rsrc_GetResInfo, 1},
131 {NULL, NULL} /* Sentinel */
132};
133
134static PyObject *
135Rsrc_GetAttr(PyObject *r, char *name)
136{
137 return Py_FindMethod(Rsrc_Methods, r, name);
138}
139
140static PyTypeObject RsrcType = {
141 PyObject_HEAD_INIT(&PyType_Type)
142 0,
143 "Resource", /*tp_name*/
144 sizeof(RsrcObject), /*tp_basicsize*/
145 0, /*tp_itemsize*/
146 /* methods */
147 (destructor)Rsrc_Dealloc, /*tp_dealloc*/
148 0, /*tp_print*/
149 (getattrfunc)Rsrc_GetAttr, /*tp_getattr*/
150 0, /*tp_setattr*/
151 0, /*tp_compare*/
152 0, /*tp_repr*/
153 0, /*tp_as_number*/
154 0, /*tp_as_sequence*/
155 0, /*tp_as_mapping*/
156 0, /*tp_hash*/
157};
158
159static PyObject *
160MacOS_GetResource(PyObject *self, PyObject *args)
161{
162 ResType rt;
163 int id;
164 Handle h;
165 if (!PyArg_Parse(args, "(O&i)", GetOSType, &rt, &id))
166 return NULL;
167 h = GetResource(rt, id);
168 return (PyObject *)Rsrc_FromHandle(h);
169}
170
171static PyObject *
172MacOS_GetNamedResource(PyObject *self, PyObject *args)
173{
174 ResType rt;
175 Str255 name;
176 Handle h;
177 if (!PyArg_Parse(args, "(O&O&)", GetOSType, &rt, GetStr255, &name))
178 return NULL;
179 h = GetNamedResource(rt, name);
180 return (PyObject *)Rsrc_FromHandle(h);
181}
182
183/*----------------------------------------------------------------------*/
184/* SoundChannel objects */
185
186/* Check for a SndCommand argument */
187static int
188GetSndCommand(PyObject *v, SndCommand *pc)
189{
190 int len;
191 pc->param1 = 0;
192 pc->param2 = 0;
193 if (PyArg_Parse(v, "h", &pc->cmd))
194 return 1;
195 PyErr_Clear();
196 if (PyArg_Parse(v, "(h)", &pc->cmd))
197 return 1;
198 PyErr_Clear();
199 if (PyArg_Parse(v, "(hh)", &pc->cmd, &pc->param1))
200 return 1;
201 PyErr_Clear();
202 if (PyArg_Parse(v, "(hhl)",
203 &pc->cmd, &pc->param1, &pc->param2))
204 return 1;
205 PyErr_Clear();
206 if (PyArg_Parse(v, "(hhs#);SndCommand arg must be 1-3 ints or 2 ints + string",
207 &pc->cmd, &pc->param1, &pc->param2, &len))
208 return 1;
209 return 0;
210}
211
212typedef struct {
213 OB_HEAD
214 SndChannelPtr chan;
215} SndChObject;
216
217staticforward PyTypeObject SndChType;
218
219#define SndChObject_Check(s) ((s)->ob_type == &SndChType)
220
221static SndChObject *
222SndCh_FromSndChannelPtr(SndChannelPtr chan)
223{
224 SndChObject *s = PyObject_NEW(SndChObject, &SndChType);
225 if (s != NULL)
226 s->chan = chan;
227 return s;
228}
229
230static void
231SndCh_Dealloc(SndChObject *s)
232{
233 if (s->chan != NULL) {
234 SndDisposeChannel(s->chan, 1);
235 s->chan = NULL;
236 }
237 PyMem_DEL(s);
238}
239
240static PyObject *
241SndCh_Close(SndChObject *s, PyObject *args)
242{
243 int quietNow = 1;
244 if (args != NULL) {
245 if (!PyArg_Parse(args, "i", &quietNow))
246 return NULL;
247 }
248 if (s->chan != NULL) {
249 SndDisposeChannel(s->chan, quietNow);
250 s->chan = NULL;
251 }
252 Py_INCREF(Py_None);
253 return Py_None;
254}
255
256static PyObject *
257SndCh_SndPlay(SndChObject *s, PyObject *args)
258{
259 RsrcObject *r;
260 int async = 0;
261 if (!PyArg_Parse(args, "(O)", &r)) {
262 PyErr_Clear();
263 if (!PyArg_Parse(args, "(Oi)", &r, &async))
264 return NULL;
265 }
266 if (!RsrcObject_Check(r)) {
267 PyErr_SetString(MacOS_Error,
268 "SndPlay argument must be resource");
269 return NULL;
270 }
271 SndPlay(s->chan, r->h, async);
272 Py_INCREF(Py_None);
273 return Py_None;
274}
275
276static PyObject *
277SndCh_SndDoCommand(SndChObject *s, PyObject *args)
278{
279 SndCommand c;
280 int noWait = 0;
281 OSErr err;
282 if (!PyArg_Parse(args, "(O&)", GetSndCommand, &c)) {
283 PyErr_Clear();
284 if (!PyArg_Parse(args, "(O&i)", GetSndCommand, &c, &noWait))
285 return 0;
286 }
287 err = SndDoCommand(s->chan, &c, noWait);
288 return Err(err);
289}
290
291static PyObject *
292SndCh_SndDoImmediate(SndChObject *s, PyObject *args)
293{
294 SndCommand c;
295 OSErr err;
296 if (!PyArg_Parse(args, "(O&)", GetSndCommand, &c))
297 return 0;
298 err = SndDoImmediate(s->chan, &c);
299 return Err(err);
300}
301
302static PyMethodDef SndCh_Methods[] = {
303 {"close", (PyCFunction)SndCh_Close},
304 {"SndDisposeChannel", (PyCFunction)SndCh_Close},
305 {"SndPlay", (PyCFunction)SndCh_SndPlay, 1},
306 {"SndDoCommand", (PyCFunction)SndCh_SndDoCommand, 1},
307 {"SndDoImmediate", (PyCFunction)SndCh_SndDoImmediate, 1},
308 {NULL, NULL} /* Sentinel */
309};
310
311static PyObject *
312SndCh_GetAttr(PyObject *s, char *name)
313{
314 return Py_FindMethod(SndCh_Methods, s, name);
315}
316
317static PyTypeObject SndChType = {
318 PyObject_HEAD_INIT(&PyType_Type)
319 0,
320 "SoundChannel", /*tp_name*/
321 sizeof(SndChObject), /*tp_basicsize*/
322 0, /*tp_itemsize*/
323 /* methods */
324 (destructor)SndCh_Dealloc, /*tp_dealloc*/
325 0, /*tp_print*/
326 (getattrfunc)SndCh_GetAttr, /*tp_getattr*/
327 0, /*tp_setattr*/
328 0, /*tp_compare*/
329 0, /*tp_repr*/
330 0, /*tp_as_number*/
331 0, /*tp_as_sequence*/
332 0, /*tp_as_mapping*/
333 0, /*tp_hash*/
334};
335
336/*----------------------------------------------------------------------*/
337/* Module */
338
339static PyObject *
340MacOS_SndNewChannel(PyObject *self, PyObject *args)
341{
342 SndChannelPtr chan;
343 short synth;
344 long init = 0;
345 OSErr err;
346 if (!PyArg_Parse(args, "(h)", &synth)) {
347 PyErr_Clear();
348 if (!PyArg_Parse(args, "(hl)", &synth, &init))
349 return NULL;
350 }
351 chan = NULL;
352 err = SndNewChannel(&chan, synth, init, (SndCallBackProcPtr)NULL);
353 if (err)
354 return Err(err);
355 return (PyObject *)SndCh_FromSndChannelPtr(chan);
356}
357
358static PyObject *
359MacOS_SndPlay(PyObject *self, PyObject *args)
360{
361 RsrcObject *r;
362 OSErr err;
363 if (!PyArg_Parse(args, "(O!)", &RsrcType, &r))
364 return NULL;
365 err = SndPlay((SndChannelPtr)NULL, r->h, 0);
366 return Err(err);
367}
368
369static PyObject *
370MacOS_SndControl(PyObject *self, PyObject *args)
371{
372 int id;
373 SndCommand c;
374 OSErr err;
375 if (!PyArg_Parse(args, "(iO&)", &id, GetSndCommand, &c))
376 return NULL;
377 err = SndControl(id, &c);
378 if (err)
379 return Err(err);
380 return Py_BuildValue("(hhl)", c.cmd, c.param1, c.param2);
381}
382
383static PyMethodDef MacOS_Methods[] = {
384 {"GetResource", MacOS_GetResource, 1},
385 {"GetNamedResource", MacOS_GetNamedResource, 1},
386 {"SndNewChannel", MacOS_SndNewChannel, 1},
387 {"SndPlay", MacOS_SndPlay, 1},
388 {"SndControl", MacOS_SndControl, 1},
389 {NULL, NULL} /* Sentinel */
390};
391
392
393void
394MacOS_Init()
395{
396 PyObject *m, *d;
397
398 m = Py_InitModule("MacOS", MacOS_Methods);
399 d = PyModule_GetDict(m);
400
401 /* Initialize MacOS.Error exception */
402 MacOS_Error = PyString_FromString("MacOS.Error");
403 if (MacOS_Error == NULL || PyDict_SetItemString(d, "Error", MacOS_Error) != 0)
404 Py_FatalError("can't define MacOS.Error");
405}