File: | _portaudiomodule.c |
Warning: | line 1847, column 9 PyObject ownership leak with reference count of 1 |
Press '?' to see keyboard shortcuts
Keyboard shortcuts:
1 | /** | ||||
2 | * PyAudio: Python Bindings for PortAudio. | ||||
3 | * | ||||
4 | * Copyright (c) 2006-2012 Hubert Pham | ||||
5 | * | ||||
6 | * Permission is hereby granted, free of charge, to any person | ||||
7 | * obtaining a copy of this software and associated documentation | ||||
8 | * files (the "Software"), to deal in the Software without | ||||
9 | * restriction, including without limitation the rights to use, copy, | ||||
10 | * modify, merge, publish, distribute, sublicense, and/or sell copies | ||||
11 | * of the Software, and to permit persons to whom the Software is | ||||
12 | * furnished to do so, subject to the following conditions: | ||||
13 | * | ||||
14 | * The above copyright notice and this permission notice shall be | ||||
15 | * included in all copies or substantial portions of the Software. | ||||
16 | * | ||||
17 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, | ||||
18 | * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF | ||||
19 | * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND | ||||
20 | * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS | ||||
21 | * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN | ||||
22 | * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN | ||||
23 | * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE | ||||
24 | * SOFTWARE. | ||||
25 | */ | ||||
26 | |||||
27 | #include <stdio.h> | ||||
28 | #include "Python.h" | ||||
29 | #include "portaudio.h" | ||||
30 | #include "_portaudiomodule.h" | ||||
31 | |||||
32 | #ifdef MACOSX | ||||
33 | #include "pa_mac_core.h" | ||||
34 | #endif | ||||
35 | |||||
36 | #define DEFAULT_FRAMES_PER_BUFFER1024 1024 | ||||
37 | /* #define VERBOSE */ | ||||
38 | |||||
39 | #define min(a,b)({ __typeof__ (a) _a = (a); __typeof__ (b) _b = (b); _a < _b ? _a : _b; }) \ | ||||
40 | ({ __typeof__ (a) _a = (a); \ | ||||
41 | __typeof__ (b) _b = (b); \ | ||||
42 | _a < _b ? _a : _b; }) | ||||
43 | |||||
44 | /************************************************************ | ||||
45 | * | ||||
46 | * Table of Contents | ||||
47 | * | ||||
48 | * I. Exportable PortAudio Method Definitions | ||||
49 | * II. Python Object Wrappers | ||||
50 | * - PaDeviceInfo | ||||
51 | * - PaHostInfo | ||||
52 | * - PaStream | ||||
53 | * III. PortAudio Method Implementations | ||||
54 | * - Initialization/Termination | ||||
55 | * - HostAPI | ||||
56 | * - DeviceAPI | ||||
57 | * - Stream Open/Close | ||||
58 | * - Stream Start/Stop/Info | ||||
59 | * - Stream Read/Write | ||||
60 | * IV. Python Module Init | ||||
61 | * - PaHostApiTypeId enum constants | ||||
62 | * | ||||
63 | ************************************************************/ | ||||
64 | |||||
65 | |||||
66 | /************************************************************ | ||||
67 | * | ||||
68 | * I. Exportable Python Methods | ||||
69 | * | ||||
70 | ************************************************************/ | ||||
71 | |||||
72 | static PyMethodDef paMethods[] = { | ||||
73 | |||||
74 | /* version */ | ||||
75 | {"get_version", pa_get_version, METH_VARARGS0x0001, "get version"}, | ||||
76 | {"get_version_text", pa_get_version_text, METH_VARARGS0x0001, | ||||
77 | "get version text"}, | ||||
78 | |||||
79 | /* inits */ | ||||
80 | {"initialize", pa_initialize, METH_VARARGS0x0001, "initialize portaudio"}, | ||||
81 | {"terminate", pa_terminate, METH_VARARGS0x0001, "terminate portaudio"}, | ||||
82 | |||||
83 | /* host api */ | ||||
84 | {"get_host_api_count", pa_get_host_api_count, METH_VARARGS0x0001, | ||||
85 | "get host API count"}, | ||||
86 | |||||
87 | {"get_default_host_api", pa_get_default_host_api, METH_VARARGS0x0001, | ||||
88 | "get default host API index"}, | ||||
89 | |||||
90 | {"host_api_type_id_to_host_api_index", | ||||
91 | pa_host_api_type_id_to_host_api_index, METH_VARARGS0x0001, | ||||
92 | "get default host API index"}, | ||||
93 | |||||
94 | {"host_api_device_index_to_device_index", | ||||
95 | pa_host_api_device_index_to_device_index, | ||||
96 | METH_VARARGS0x0001, | ||||
97 | "get default host API index"}, | ||||
98 | |||||
99 | {"get_host_api_info", pa_get_host_api_info, METH_VARARGS0x0001, | ||||
100 | "get host api information"}, | ||||
101 | |||||
102 | /* device api */ | ||||
103 | {"get_device_count", pa_get_device_count, METH_VARARGS0x0001, | ||||
104 | "get host API count"}, | ||||
105 | |||||
106 | {"get_default_input_device", pa_get_default_input_device, METH_VARARGS0x0001, | ||||
107 | "get default input device index"}, | ||||
108 | |||||
109 | {"get_default_output_device", pa_get_default_output_device, METH_VARARGS0x0001, | ||||
110 | "get default output device index"}, | ||||
111 | |||||
112 | {"get_device_info", pa_get_device_info, METH_VARARGS0x0001, | ||||
113 | "get device information"}, | ||||
114 | |||||
115 | /* stream open/close */ | ||||
116 | {"open", (PyCFunction) pa_open, METH_VARARGS0x0001 | METH_KEYWORDS0x0002, | ||||
117 | "open port audio stream"}, | ||||
118 | {"close", pa_close, METH_VARARGS0x0001, "close port audio stream"}, | ||||
119 | {"get_sample_size", pa_get_sample_size, METH_VARARGS0x0001, | ||||
120 | "get sample size of a format in bytes"}, | ||||
121 | {"is_format_supported", (PyCFunction) pa_is_format_supported, | ||||
122 | METH_VARARGS0x0001 | METH_KEYWORDS0x0002, | ||||
123 | "returns whether specified format is supported"}, | ||||
124 | |||||
125 | /* stream start/stop */ | ||||
126 | {"start_stream", pa_start_stream, METH_VARARGS0x0001, "starts port audio stream"}, | ||||
127 | {"stop_stream", pa_stop_stream, METH_VARARGS0x0001, "stops port audio stream"}, | ||||
128 | {"abort_stream", pa_abort_stream, METH_VARARGS0x0001, "aborts port audio stream"}, | ||||
129 | {"is_stream_stopped", pa_is_stream_stopped, METH_VARARGS0x0001, | ||||
130 | "returns whether stream is stopped"}, | ||||
131 | {"is_stream_active", pa_is_stream_active, METH_VARARGS0x0001, | ||||
132 | "returns whether stream is active"}, | ||||
133 | {"get_stream_time", pa_get_stream_time, METH_VARARGS0x0001, | ||||
134 | "returns stream time"}, | ||||
135 | {"get_stream_cpu_load", pa_get_stream_cpu_load, METH_VARARGS0x0001, | ||||
136 | "returns stream CPU load -- always 0 for blocking mode"}, | ||||
137 | |||||
138 | /* stream read/write */ | ||||
139 | {"write_stream", pa_write_stream, METH_VARARGS0x0001, "write to stream"}, | ||||
140 | {"read_stream", pa_read_stream, METH_VARARGS0x0001, "read from stream"}, | ||||
141 | |||||
142 | {"get_stream_write_available", | ||||
143 | pa_get_stream_write_available, METH_VARARGS0x0001, | ||||
144 | "get buffer available for writing"}, | ||||
145 | |||||
146 | {"get_stream_read_available", | ||||
147 | pa_get_stream_read_available, METH_VARARGS0x0001, | ||||
148 | "get buffer available for reading"}, | ||||
149 | |||||
150 | {NULL((void*)0), NULL((void*)0), 0, NULL((void*)0)} | ||||
151 | }; | ||||
152 | |||||
153 | |||||
154 | /************************************************************ | ||||
155 | * | ||||
156 | * II. Python Object Wrappers | ||||
157 | * | ||||
158 | ************************************************************/ | ||||
159 | |||||
160 | |||||
161 | /************************************************************* | ||||
162 | * PaDeviceInfo Type : Python object wrapper for PaDeviceInfo | ||||
163 | *************************************************************/ | ||||
164 | |||||
165 | typedef struct { | ||||
166 | PyObject_HEADPyObject ob_base; | ||||
167 | PaDeviceInfo *devInfo; | ||||
168 | } _pyAudio_paDeviceInfo; | ||||
169 | |||||
170 | |||||
171 | /* sepcific getters into the PaDeviceInfo struct */ | ||||
172 | |||||
173 | static PyObject * | ||||
174 | _pyAudio_paDeviceInfo_get_structVersion(_pyAudio_paDeviceInfo *self, | ||||
175 | void *closure) | ||||
176 | { | ||||
177 | /* sanity check */ | ||||
178 | if (!self->devInfo) { | ||||
179 | PyErr_SetString(PyExc_AttributeError, | ||||
180 | "No Device Info available"); | ||||
181 | return NULL((void*)0); | ||||
182 | } | ||||
183 | |||||
184 | return PyLong_FromLong(self->devInfo->structVersion); | ||||
185 | } | ||||
186 | |||||
187 | static PyObject * | ||||
188 | _pyAudio_paDeviceInfo_get_name(_pyAudio_paDeviceInfo *self, | ||||
189 | void *closure) | ||||
190 | { | ||||
191 | /* sanity check */ | ||||
192 | if ((!self->devInfo) || (self->devInfo->name == NULL((void*)0))) { | ||||
193 | PyErr_SetString(PyExc_AttributeError, | ||||
194 | "No Device Info available"); | ||||
195 | return NULL((void*)0); | ||||
196 | } | ||||
197 | |||||
198 | return PyBytes_FromString(self->devInfo->name); | ||||
199 | } | ||||
200 | |||||
201 | static PyObject * | ||||
202 | _pyAudio_paDeviceInfo_get_hostApi(_pyAudio_paDeviceInfo *self, | ||||
203 | void *closure) | ||||
204 | { | ||||
205 | /* sanity check */ | ||||
206 | if (!self->devInfo) { | ||||
207 | PyErr_SetString(PyExc_AttributeError, | ||||
208 | "No Device Info available"); | ||||
209 | return NULL((void*)0); | ||||
210 | } | ||||
211 | |||||
212 | return PyLong_FromLong(self->devInfo->hostApi); | ||||
213 | } | ||||
214 | |||||
215 | static PyObject * | ||||
216 | _pyAudio_paDeviceInfo_get_maxInputChannels(_pyAudio_paDeviceInfo *self, | ||||
217 | void *closure) | ||||
218 | { | ||||
219 | /* sanity check */ | ||||
220 | if (!self->devInfo) { | ||||
221 | PyErr_SetString(PyExc_AttributeError, | ||||
222 | "No Device Info available"); | ||||
223 | return NULL((void*)0); | ||||
224 | } | ||||
225 | |||||
226 | return PyLong_FromLong(self->devInfo->maxInputChannels); | ||||
227 | } | ||||
228 | |||||
229 | static PyObject * | ||||
230 | _pyAudio_paDeviceInfo_get_maxOutputChannels(_pyAudio_paDeviceInfo *self, | ||||
231 | void *closure) | ||||
232 | { | ||||
233 | /* sanity check */ | ||||
234 | if (!self->devInfo) { | ||||
235 | PyErr_SetString(PyExc_AttributeError, | ||||
236 | "No Device Info available"); | ||||
237 | return NULL((void*)0); | ||||
238 | } | ||||
239 | |||||
240 | return PyLong_FromLong(self->devInfo->maxOutputChannels); | ||||
241 | } | ||||
242 | |||||
243 | static PyObject * | ||||
244 | _pyAudio_paDeviceInfo_get_defaultLowInputLatency(_pyAudio_paDeviceInfo *self, | ||||
245 | void *closure) | ||||
246 | { | ||||
247 | /* sanity check */ | ||||
248 | if (!self->devInfo) { | ||||
249 | PyErr_SetString(PyExc_AttributeError, | ||||
250 | "No Device Info available"); | ||||
251 | return NULL((void*)0); | ||||
252 | } | ||||
253 | |||||
254 | return PyFloat_FromDouble(self->devInfo->defaultLowInputLatency); | ||||
255 | } | ||||
256 | |||||
257 | static PyObject * | ||||
258 | _pyAudio_paDeviceInfo_get_defaultLowOutputLatency(_pyAudio_paDeviceInfo *self, | ||||
259 | void *closure) | ||||
260 | { | ||||
261 | /* sanity check */ | ||||
262 | if (!self->devInfo) { | ||||
263 | PyErr_SetString(PyExc_AttributeError, | ||||
264 | "No Device Info available"); | ||||
265 | return NULL((void*)0); | ||||
266 | } | ||||
267 | |||||
268 | return PyFloat_FromDouble(self->devInfo->defaultLowOutputLatency); | ||||
269 | } | ||||
270 | |||||
271 | |||||
272 | static PyObject * | ||||
273 | _pyAudio_paDeviceInfo_get_defaultHighInputLatency(_pyAudio_paDeviceInfo *self, | ||||
274 | void *closure) | ||||
275 | { | ||||
276 | /* sanity check */ | ||||
277 | if (!self->devInfo) { | ||||
278 | PyErr_SetString(PyExc_AttributeError, | ||||
279 | "No Device Info available"); | ||||
280 | return NULL((void*)0); | ||||
281 | } | ||||
282 | |||||
283 | return PyFloat_FromDouble(self->devInfo->defaultHighInputLatency); | ||||
284 | } | ||||
285 | |||||
286 | static PyObject * | ||||
287 | _pyAudio_paDeviceInfo_get_defaultHighOutputLatency(_pyAudio_paDeviceInfo *self, | ||||
288 | void *closure) | ||||
289 | { | ||||
290 | /* sanity check */ | ||||
291 | if (!self->devInfo) { | ||||
292 | PyErr_SetString(PyExc_AttributeError, | ||||
293 | "No Device Info available"); | ||||
294 | return NULL((void*)0); | ||||
295 | } | ||||
296 | |||||
297 | return PyFloat_FromDouble(self->devInfo->defaultHighOutputLatency); | ||||
298 | } | ||||
299 | |||||
300 | static PyObject * | ||||
301 | _pyAudio_paDeviceInfo_get_defaultSampleRate(_pyAudio_paDeviceInfo *self, | ||||
302 | void *closure) | ||||
303 | { | ||||
304 | /* sanity check */ | ||||
305 | if (!self->devInfo) { | ||||
306 | PyErr_SetString(PyExc_AttributeError, | ||||
307 | "No Device Info available"); | ||||
308 | return NULL((void*)0); | ||||
309 | } | ||||
310 | |||||
311 | return PyFloat_FromDouble(self->devInfo->defaultSampleRate); | ||||
312 | } | ||||
313 | |||||
314 | |||||
315 | |||||
316 | static int | ||||
317 | _pyAudio_paDeviceInfo_antiset(_pyAudio_paDeviceInfo *self, | ||||
318 | PyObject *value, | ||||
319 | void *closure) | ||||
320 | { | ||||
321 | /* read-only: do not allow users to change values */ | ||||
322 | PyErr_SetString(PyExc_AttributeError, | ||||
323 | "Fields read-only: cannot modify values"); | ||||
324 | return -1; | ||||
325 | } | ||||
326 | |||||
327 | static PyGetSetDef _pyAudio_paDeviceInfo_getseters[] = { | ||||
328 | {"name", | ||||
329 | (getter) _pyAudio_paDeviceInfo_get_name, | ||||
330 | (setter) _pyAudio_paDeviceInfo_antiset, | ||||
331 | "device name", | ||||
332 | NULL((void*)0)}, | ||||
333 | |||||
334 | {"structVersion", | ||||
335 | (getter) _pyAudio_paDeviceInfo_get_structVersion, | ||||
336 | (setter) _pyAudio_paDeviceInfo_antiset, | ||||
337 | "struct version", | ||||
338 | NULL((void*)0)}, | ||||
339 | |||||
340 | {"hostApi", | ||||
341 | (getter) _pyAudio_paDeviceInfo_get_hostApi, | ||||
342 | (setter) _pyAudio_paDeviceInfo_antiset, | ||||
343 | "host api index", | ||||
344 | NULL((void*)0)}, | ||||
345 | |||||
346 | {"maxInputChannels", | ||||
347 | (getter) _pyAudio_paDeviceInfo_get_maxInputChannels, | ||||
348 | (setter) _pyAudio_paDeviceInfo_antiset, | ||||
349 | "max input channels", | ||||
350 | NULL((void*)0)}, | ||||
351 | |||||
352 | {"maxOutputChannels", | ||||
353 | (getter) _pyAudio_paDeviceInfo_get_maxOutputChannels, | ||||
354 | (setter) _pyAudio_paDeviceInfo_antiset, | ||||
355 | "max output channels", | ||||
356 | NULL((void*)0)}, | ||||
357 | |||||
358 | {"defaultLowInputLatency", | ||||
359 | (getter) _pyAudio_paDeviceInfo_get_defaultLowInputLatency, | ||||
360 | (setter) _pyAudio_paDeviceInfo_antiset, | ||||
361 | "default low input latency", | ||||
362 | NULL((void*)0)}, | ||||
363 | |||||
364 | {"defaultLowOutputLatency", | ||||
365 | (getter) _pyAudio_paDeviceInfo_get_defaultLowOutputLatency, | ||||
366 | (setter) _pyAudio_paDeviceInfo_antiset, | ||||
367 | "default low output latency", | ||||
368 | NULL((void*)0)}, | ||||
369 | |||||
370 | {"defaultHighInputLatency", | ||||
371 | (getter) _pyAudio_paDeviceInfo_get_defaultHighInputLatency, | ||||
372 | (setter) _pyAudio_paDeviceInfo_antiset, | ||||
373 | "default high input latency", | ||||
374 | NULL((void*)0)}, | ||||
375 | |||||
376 | {"defaultHighOutputLatency", | ||||
377 | (getter) _pyAudio_paDeviceInfo_get_defaultHighOutputLatency, | ||||
378 | (setter) _pyAudio_paDeviceInfo_antiset, | ||||
379 | "default high output latency", | ||||
380 | NULL((void*)0)}, | ||||
381 | |||||
382 | {"defaultSampleRate", | ||||
383 | (getter) _pyAudio_paDeviceInfo_get_defaultSampleRate, | ||||
384 | (setter) _pyAudio_paDeviceInfo_antiset, | ||||
385 | "default sample rate", | ||||
386 | NULL((void*)0)}, | ||||
387 | |||||
388 | {NULL((void*)0)} | ||||
389 | }; | ||||
390 | |||||
391 | static void | ||||
392 | _pyAudio_paDeviceInfo_dealloc(_pyAudio_paDeviceInfo* self) | ||||
393 | { | ||||
394 | /* reset the pointer */ | ||||
395 | self->devInfo = NULL((void*)0); | ||||
396 | |||||
397 | /* free the object */ | ||||
398 | Py_TYPE(self)(((PyObject*)(self))->ob_type)->tp_free((PyObject*) self); | ||||
399 | } | ||||
400 | |||||
401 | static PyTypeObject _pyAudio_paDeviceInfoType = { | ||||
402 | PyVarObject_HEAD_INIT(NULL, 0){ { 1, ((void*)0) }, 0 }, | ||||
403 | "_portaudio.paDeviceInfo", /*tp_name*/ | ||||
404 | sizeof(_pyAudio_paDeviceInfo), /*tp_basicsize*/ | ||||
405 | 0, /*tp_itemsize*/ | ||||
406 | (destructor) _pyAudio_paDeviceInfo_dealloc, /*tp_dealloc*/ | ||||
407 | 0, /*tp_print*/ | ||||
408 | 0, /*tp_getattr*/ | ||||
409 | 0, /*tp_setattr*/ | ||||
410 | 0, /*tp_compare*/ | ||||
411 | 0, /*tp_repr*/ | ||||
412 | 0, /*tp_as_number*/ | ||||
413 | 0, /*tp_as_sequence*/ | ||||
414 | 0, /*tp_as_mapping*/ | ||||
415 | 0, /*tp_hash */ | ||||
416 | 0, /*tp_call*/ | ||||
417 | 0, /*tp_str*/ | ||||
418 | 0, /*tp_getattro*/ | ||||
419 | 0, /*tp_setattro*/ | ||||
420 | 0, /*tp_as_buffer*/ | ||||
421 | Py_TPFLAGS_DEFAULT( 0 | (1UL << 18) | 0), /*tp_flags*/ | ||||
422 | "Port Audio Device Info", /* tp_doc */ | ||||
423 | 0, /* tp_traverse */ | ||||
424 | 0, /* tp_clear */ | ||||
425 | 0, /* tp_richcompare */ | ||||
426 | 0, /* tp_weaklistoffset */ | ||||
427 | 0, /* tp_iter */ | ||||
428 | 0, /* tp_iternext */ | ||||
429 | 0, /* tp_methods */ | ||||
430 | 0, /* tp_members */ | ||||
431 | _pyAudio_paDeviceInfo_getseters, /* tp_getset */ | ||||
432 | 0, /* tp_base */ | ||||
433 | 0, /* tp_dict */ | ||||
434 | 0, /* tp_descr_get */ | ||||
435 | 0, /* tp_descr_set */ | ||||
436 | 0, /* tp_dictoffset */ | ||||
437 | 0, /* tp_init */ | ||||
438 | 0, /* tp_alloc */ | ||||
439 | 0, /* tp_new */ | ||||
440 | }; | ||||
441 | |||||
442 | static _pyAudio_paDeviceInfo * | ||||
443 | _create_paDeviceInfo_object(void) | ||||
444 | { | ||||
445 | _pyAudio_paDeviceInfo *obj; | ||||
446 | |||||
447 | /* don't allow subclassing? */ | ||||
448 | obj = (_pyAudio_paDeviceInfo *) PyObject_New(_pyAudio_paDeviceInfo,( (_pyAudio_paDeviceInfo *) _PyObject_New(&_pyAudio_paDeviceInfoType ) ) | ||||
449 | &_pyAudio_paDeviceInfoType)( (_pyAudio_paDeviceInfo *) _PyObject_New(&_pyAudio_paDeviceInfoType ) ); | ||||
450 | |||||
451 | /* obj = (_pyAudio_Stream*) | ||||
452 | _pyAudio_StreamType.tp_alloc(&_pyAudio_StreamType, 0); */ | ||||
453 | return obj; | ||||
454 | } | ||||
455 | |||||
456 | |||||
457 | |||||
458 | |||||
459 | /************************************************************* | ||||
460 | * PaHostApi Info Python Object | ||||
461 | *************************************************************/ | ||||
462 | |||||
463 | typedef struct { | ||||
464 | PyObject_HEADPyObject ob_base; | ||||
465 | PaHostApiInfo *apiInfo; | ||||
466 | } _pyAudio_paHostApiInfo; | ||||
467 | |||||
468 | /* sepcific getters into the PaDeviceInfo struct */ | ||||
469 | |||||
470 | static PyObject * | ||||
471 | _pyAudio_paHostApiInfo_get_structVersion(_pyAudio_paHostApiInfo *self, | ||||
472 | void *closure) | ||||
473 | { | ||||
474 | /* sanity check */ | ||||
475 | if ((!self->apiInfo)) { | ||||
476 | PyErr_SetString(PyExc_AttributeError, | ||||
477 | "No HostApi Info available"); | ||||
478 | return NULL((void*)0); | ||||
479 | } | ||||
480 | |||||
481 | return PyLong_FromLong(self->apiInfo->structVersion); | ||||
482 | } | ||||
483 | |||||
484 | static PyObject * | ||||
485 | _pyAudio_paHostApiInfo_get_type(_pyAudio_paHostApiInfo *self, | ||||
486 | void *closure) | ||||
487 | { | ||||
488 | /* sanity check */ | ||||
489 | if ((!self->apiInfo)) { | ||||
490 | PyErr_SetString(PyExc_AttributeError, | ||||
491 | "No HostApi Info available"); | ||||
492 | return NULL((void*)0); | ||||
493 | } | ||||
494 | |||||
495 | return PyLong_FromLong((long) self->apiInfo->type); | ||||
496 | } | ||||
497 | |||||
498 | static PyObject * | ||||
499 | _pyAudio_paHostApiInfo_get_name(_pyAudio_paHostApiInfo *self, | ||||
500 | void *closure) | ||||
501 | { | ||||
502 | /* sanity check */ | ||||
503 | if ((!self->apiInfo) || (self->apiInfo->name == NULL((void*)0))) { | ||||
504 | PyErr_SetString(PyExc_AttributeError, | ||||
505 | "No HostApi Info available"); | ||||
506 | return NULL((void*)0); | ||||
507 | } | ||||
508 | |||||
509 | return PyUnicode_FromString(self->apiInfo->name); | ||||
510 | } | ||||
511 | |||||
512 | static PyObject * | ||||
513 | _pyAudio_paHostApiInfo_get_deviceCount(_pyAudio_paHostApiInfo *self, | ||||
514 | void *closure) | ||||
515 | { | ||||
516 | /* sanity check */ | ||||
517 | if ((!self->apiInfo)) { | ||||
518 | PyErr_SetString(PyExc_AttributeError, | ||||
519 | "No HostApi Info available"); | ||||
520 | return NULL((void*)0); | ||||
521 | } | ||||
522 | |||||
523 | return PyLong_FromLong(self->apiInfo->deviceCount); | ||||
524 | } | ||||
525 | |||||
526 | static PyObject * | ||||
527 | _pyAudio_paHostApiInfo_get_defaultInputDevice(_pyAudio_paHostApiInfo *self, | ||||
528 | void *closure) | ||||
529 | { | ||||
530 | /* sanity check */ | ||||
531 | if ((!self->apiInfo)) { | ||||
532 | PyErr_SetString(PyExc_AttributeError, | ||||
533 | "No HostApi Info available"); | ||||
534 | return NULL((void*)0); | ||||
535 | } | ||||
536 | |||||
537 | return PyLong_FromLong(self->apiInfo->defaultInputDevice); | ||||
538 | } | ||||
539 | |||||
540 | static PyObject * | ||||
541 | _pyAudio_paHostApiInfo_get_defaultOutputDevice(_pyAudio_paHostApiInfo *self, | ||||
542 | void *closure) | ||||
543 | { | ||||
544 | /* sanity check */ | ||||
545 | if ((!self->apiInfo)) { | ||||
546 | PyErr_SetString(PyExc_AttributeError, | ||||
547 | "No HostApi Info available"); | ||||
548 | return NULL((void*)0); | ||||
549 | } | ||||
550 | |||||
551 | return PyLong_FromLong(self->apiInfo->defaultOutputDevice); | ||||
552 | } | ||||
553 | |||||
554 | static int | ||||
555 | _pyAudio_paHostApiInfo_antiset(_pyAudio_paDeviceInfo *self, | ||||
556 | PyObject *value, | ||||
557 | void *closure) | ||||
558 | { | ||||
559 | /* read-only: do not allow users to change values */ | ||||
560 | PyErr_SetString(PyExc_AttributeError, | ||||
561 | "Fields read-only: cannot modify values"); | ||||
562 | return -1; | ||||
563 | } | ||||
564 | |||||
565 | static void | ||||
566 | _pyAudio_paHostApiInfo_dealloc(_pyAudio_paHostApiInfo* self) | ||||
567 | { | ||||
568 | /* reset the pointer */ | ||||
569 | self->apiInfo = NULL((void*)0); | ||||
570 | |||||
571 | /* free the object */ | ||||
572 | Py_TYPE(self)(((PyObject*)(self))->ob_type)->tp_free((PyObject*) self); | ||||
573 | } | ||||
574 | |||||
575 | static PyGetSetDef _pyAudio_paHostApiInfo_getseters[] = { | ||||
576 | {"name", | ||||
577 | (getter) _pyAudio_paHostApiInfo_get_name, | ||||
578 | (setter) _pyAudio_paHostApiInfo_antiset, | ||||
579 | "host api name", | ||||
580 | NULL((void*)0)}, | ||||
581 | |||||
582 | {"structVersion", | ||||
583 | (getter) _pyAudio_paHostApiInfo_get_structVersion, | ||||
584 | (setter) _pyAudio_paHostApiInfo_antiset, | ||||
585 | "struct version", | ||||
586 | NULL((void*)0)}, | ||||
587 | |||||
588 | {"type", | ||||
589 | (getter) _pyAudio_paHostApiInfo_get_type, | ||||
590 | (setter) _pyAudio_paHostApiInfo_antiset, | ||||
591 | "host api type", | ||||
592 | NULL((void*)0)}, | ||||
593 | |||||
594 | {"deviceCount", | ||||
595 | (getter) _pyAudio_paHostApiInfo_get_deviceCount, | ||||
596 | (setter) _pyAudio_paHostApiInfo_antiset, | ||||
597 | "number of devices", | ||||
598 | NULL((void*)0)}, | ||||
599 | |||||
600 | {"defaultInputDevice", | ||||
601 | (getter) _pyAudio_paHostApiInfo_get_defaultInputDevice, | ||||
602 | (setter) _pyAudio_paHostApiInfo_antiset, | ||||
603 | "default input device index", | ||||
604 | NULL((void*)0)}, | ||||
605 | |||||
606 | {"defaultOutputDevice", | ||||
607 | (getter) _pyAudio_paHostApiInfo_get_defaultOutputDevice, | ||||
608 | (setter) _pyAudio_paDeviceInfo_antiset, | ||||
609 | "default output device index", | ||||
610 | NULL((void*)0)}, | ||||
611 | |||||
612 | {NULL((void*)0)} | ||||
613 | }; | ||||
614 | |||||
615 | static PyTypeObject _pyAudio_paHostApiInfoType = { | ||||
616 | PyVarObject_HEAD_INIT(NULL, 0){ { 1, ((void*)0) }, 0 }, | ||||
617 | "_portaudio.paHostApiInfo", /*tp_name*/ | ||||
618 | sizeof(_pyAudio_paHostApiInfo), /*tp_basicsize*/ | ||||
619 | 0, /*tp_itemsize*/ | ||||
620 | (destructor) _pyAudio_paHostApiInfo_dealloc, /*tp_dealloc*/ | ||||
621 | 0, /*tp_print*/ | ||||
622 | 0, /*tp_getattr*/ | ||||
623 | 0, /*tp_setattr*/ | ||||
624 | 0, /*tp_compare*/ | ||||
625 | 0, /*tp_repr*/ | ||||
626 | 0, /*tp_as_number*/ | ||||
627 | 0, /*tp_as_sequence*/ | ||||
628 | 0, /*tp_as_mapping*/ | ||||
629 | 0, /*tp_hash */ | ||||
630 | 0, /*tp_call*/ | ||||
631 | 0, /*tp_str*/ | ||||
632 | 0, /*tp_getattro*/ | ||||
633 | 0, /*tp_setattro*/ | ||||
634 | 0, /*tp_as_buffer*/ | ||||
635 | Py_TPFLAGS_DEFAULT( 0 | (1UL << 18) | 0), /*tp_flags*/ | ||||
636 | "Port Audio HostApi Info", /* tp_doc */ | ||||
637 | 0, /* tp_traverse */ | ||||
638 | 0, /* tp_clear */ | ||||
639 | 0, /* tp_richcompare */ | ||||
640 | 0, /* tp_weaklistoffset */ | ||||
641 | 0, /* tp_iter */ | ||||
642 | 0, /* tp_iternext */ | ||||
643 | 0, /* tp_methods */ | ||||
644 | 0, /* tp_members */ | ||||
645 | _pyAudio_paHostApiInfo_getseters, /* tp_getset */ | ||||
646 | 0, /* tp_base */ | ||||
647 | 0, /* tp_dict */ | ||||
648 | 0, /* tp_descr_get */ | ||||
649 | 0, /* tp_descr_set */ | ||||
650 | 0, /* tp_dictoffset */ | ||||
651 | 0, /* tp_init */ | ||||
652 | 0, /* tp_alloc */ | ||||
653 | 0, /* tp_new */ | ||||
654 | }; | ||||
655 | |||||
656 | static _pyAudio_paHostApiInfo * | ||||
657 | _create_paHostApiInfo_object(void) | ||||
658 | { | ||||
659 | _pyAudio_paHostApiInfo *obj; | ||||
660 | |||||
661 | /* don't allow subclassing? */ | ||||
662 | obj = (_pyAudio_paHostApiInfo *) PyObject_New(_pyAudio_paHostApiInfo,( (_pyAudio_paHostApiInfo *) _PyObject_New(&_pyAudio_paHostApiInfoType ) ) | ||||
663 | &_pyAudio_paHostApiInfoType)( (_pyAudio_paHostApiInfo *) _PyObject_New(&_pyAudio_paHostApiInfoType ) ); | ||||
664 | return obj; | ||||
665 | } | ||||
666 | |||||
667 | /************************************************************* | ||||
668 | * Host-Specific Objects | ||||
669 | *************************************************************/ | ||||
670 | |||||
671 | /************************************************************* | ||||
672 | * --> Mac OS X | ||||
673 | *************************************************************/ | ||||
674 | |||||
675 | #ifdef MACOSX | ||||
676 | typedef struct { | ||||
677 | PyObject_HEADPyObject ob_base; | ||||
678 | PaMacCoreStreamInfo *paMacCoreStreamInfo; | ||||
679 | int flags; | ||||
680 | SInt32 *channelMap; | ||||
681 | int channelMapSize; | ||||
682 | } _pyAudio_MacOSX_hostApiSpecificStreamInfo; | ||||
683 | |||||
684 | typedef _pyAudio_MacOSX_hostApiSpecificStreamInfo _pyAudio_Mac_HASSI; | ||||
685 | |||||
686 | static void | ||||
687 | _pyAudio_MacOSX_hostApiSpecificStreamInfo_cleanup(_pyAudio_Mac_HASSI *self) | ||||
688 | { | ||||
689 | if (self->paMacCoreStreamInfo != NULL((void*)0)) { | ||||
690 | free(self->paMacCoreStreamInfo); | ||||
691 | self->paMacCoreStreamInfo = NULL((void*)0); | ||||
692 | } | ||||
693 | |||||
694 | if (self->channelMap != NULL((void*)0)) { | ||||
695 | free(self->channelMap); | ||||
696 | self->channelMap = NULL((void*)0); | ||||
697 | } | ||||
698 | |||||
699 | self->flags = paMacCorePlayNice; | ||||
700 | self->channelMapSize = 0; | ||||
701 | } | ||||
702 | |||||
703 | static void | ||||
704 | _pyAudio_MacOSX_hostApiSpecificStreamInfo_dealloc(_pyAudio_Mac_HASSI *self) | ||||
705 | { | ||||
706 | _pyAudio_MacOSX_hostApiSpecificStreamInfo_cleanup(self); | ||||
707 | Py_TYPE(self)(((PyObject*)(self))->ob_type)->tp_free((PyObject *) self); | ||||
708 | } | ||||
709 | |||||
710 | static int | ||||
711 | _pyAudio_MacOSX_hostApiSpecificStreamInfo_init(PyObject *_self, | ||||
712 | PyObject *args, | ||||
713 | PyObject *kwargs) | ||||
714 | { | ||||
715 | _pyAudio_Mac_HASSI *self = (_pyAudio_Mac_HASSI *) _self; | ||||
716 | PyObject *channel_map = NULL((void*)0); | ||||
717 | int flags = paMacCorePlayNice; | ||||
718 | |||||
719 | static char *kwlist[] = {"flags", "channel_map", NULL((void*)0)}; | ||||
720 | |||||
721 | if (! PyArg_ParseTupleAndKeywords(args, kwargs, "|iO", kwlist, | ||||
722 | &flags, &channel_map)) { | ||||
723 | return -1; | ||||
724 | } | ||||
725 | |||||
726 | // cleanup (just in case) | ||||
727 | _pyAudio_MacOSX_hostApiSpecificStreamInfo_cleanup(self); | ||||
728 | |||||
729 | if (channel_map != NULL((void*)0)) { | ||||
730 | // ensure channel_map is an array | ||||
731 | if (! PyTuple_Check(channel_map)((((((PyObject*)(channel_map))->ob_type))->tp_flags & ((1UL << 26))) != 0)) { | ||||
732 | PyErr_SetString(PyExc_ValueError, "Channel map must be a tuple"); | ||||
733 | return -1; | ||||
734 | } | ||||
735 | |||||
736 | // generate SInt32 channelMap | ||||
737 | self->channelMapSize = (int) PyTuple_Size(channel_map); | ||||
738 | |||||
739 | self->channelMap = (SInt32 *) malloc(sizeof(SInt32) * self->channelMapSize); | ||||
740 | |||||
741 | if (self->channelMap == NULL((void*)0)) { | ||||
742 | PyErr_SetString(PyExc_SystemError, "Out of memory"); | ||||
743 | _pyAudio_MacOSX_hostApiSpecificStreamInfo_cleanup(self); | ||||
744 | return -1; | ||||
745 | } | ||||
746 | |||||
747 | PyObject *element; | ||||
748 | int i; | ||||
749 | for (i = 0; i < self->channelMapSize; ++i) { | ||||
750 | element = PyTuple_GetItem(channel_map, i); | ||||
751 | if (element == NULL((void*)0)) { | ||||
752 | // error condition | ||||
753 | PyErr_SetString(PyExc_ValueError, | ||||
754 | "Internal error: out of bounds index"); | ||||
755 | _pyAudio_MacOSX_hostApiSpecificStreamInfo_cleanup(self); | ||||
756 | return -1; | ||||
757 | } | ||||
758 | |||||
759 | // make sure element is an integer | ||||
760 | if (!PyNumber_Check(element)) { | ||||
761 | PyErr_SetString(PyExc_ValueError, | ||||
762 | "Channel Map must consist of integer elements"); | ||||
763 | _pyAudio_MacOSX_hostApiSpecificStreamInfo_cleanup(self); | ||||
764 | return -1; | ||||
765 | } | ||||
766 | |||||
767 | PyObject *long_element = PyNumber_Long(element); | ||||
768 | |||||
769 | // OK, looks good | ||||
770 | self->channelMap[i] = (SInt32) PyLong_AsLong(long_element); | ||||
771 | Py_DECREF(long_element)_Py_DECREF(((PyObject*)(long_element))); | ||||
772 | } | ||||
773 | } | ||||
774 | |||||
775 | // malloc self->paMacCoreStreamInfo | ||||
776 | self->paMacCoreStreamInfo = | ||||
777 | (PaMacCoreStreamInfo *) malloc(sizeof(PaMacCoreStreamInfo)); | ||||
778 | |||||
779 | if (self->paMacCoreStreamInfo == NULL((void*)0)) { | ||||
780 | PyErr_SetString(PyExc_SystemError, "Out of memeory"); | ||||
781 | _pyAudio_MacOSX_hostApiSpecificStreamInfo_cleanup(self); | ||||
782 | return -1; | ||||
783 | } | ||||
784 | |||||
785 | PaMacCore_SetupStreamInfo(self->paMacCoreStreamInfo, flags); | ||||
786 | |||||
787 | if (self->channelMap) { | ||||
788 | PaMacCore_SetupChannelMap(self->paMacCoreStreamInfo, | ||||
789 | self->channelMap, | ||||
790 | self->channelMapSize); | ||||
791 | } | ||||
792 | |||||
793 | self->flags = flags; | ||||
794 | |||||
795 | return 0; | ||||
796 | } | ||||
797 | |||||
798 | static PyObject * | ||||
799 | _pyAudio_MacOSX_hostApiSpecificStreamInfo_get_flags(_pyAudio_Mac_HASSI *self, | ||||
800 | void *closure) | ||||
801 | { | ||||
802 | return PyLong_FromLong(self->flags); | ||||
803 | } | ||||
804 | |||||
805 | static PyObject * | ||||
806 | _pyAudio_MacOSX_hostApiSpecificStreamInfo_get_channel_map( | ||||
807 | _pyAudio_Mac_HASSI *self, | ||||
808 | void *closure) | ||||
809 | { | ||||
810 | if (self->channelMap == NULL((void*)0) || self->channelMapSize == 0) { | ||||
811 | Py_INCREF(Py_None)_Py_INCREF(((PyObject*)((&_Py_NoneStruct)))); | ||||
812 | return Py_None(&_Py_NoneStruct); | ||||
813 | } | ||||
814 | |||||
815 | int i; | ||||
816 | PyObject *channelMapTuple = PyTuple_New(self->channelMapSize); | ||||
817 | for (i = 0; i < self->channelMapSize; ++i) { | ||||
818 | PyObject *element = PyLong_FromLong(self->channelMap[i]); | ||||
819 | if (!element) { | ||||
820 | PyErr_SetString(PyExc_SystemError, "Invalid channel map"); | ||||
821 | return NULL((void*)0); | ||||
822 | } | ||||
823 | |||||
824 | if (PyTuple_SetItem(channelMapTuple, | ||||
825 | i, | ||||
826 | PyLong_FromLong(self->channelMap[i]))) { | ||||
827 | // non-zero on error | ||||
828 | PyErr_SetString(PyExc_SystemError, "Can't create channel map."); | ||||
829 | return NULL((void*)0); | ||||
830 | } | ||||
831 | } | ||||
832 | return channelMapTuple; | ||||
833 | } | ||||
834 | |||||
835 | static int | ||||
836 | _pyAudio_MacOSX_hostApiSpecificStreamInfo_antiset(_pyAudio_Mac_HASSI *self, | ||||
837 | PyObject *value, | ||||
838 | void *closure) | ||||
839 | { | ||||
840 | /* read-only: do not allow users to change values */ | ||||
841 | PyErr_SetString(PyExc_AttributeError, | ||||
842 | "Fields read-only: cannot modify values"); | ||||
843 | return -1; | ||||
844 | } | ||||
845 | |||||
846 | static PyGetSetDef _pyAudio_MacOSX_hostApiSpecificStreamInfo_getseters[] = { | ||||
847 | {"flags", | ||||
848 | (getter) _pyAudio_MacOSX_hostApiSpecificStreamInfo_get_flags, | ||||
849 | (setter) _pyAudio_MacOSX_hostApiSpecificStreamInfo_antiset, | ||||
850 | "flags", | ||||
851 | NULL((void*)0)}, | ||||
852 | |||||
853 | {"channel_map", | ||||
854 | (getter) _pyAudio_MacOSX_hostApiSpecificStreamInfo_get_channel_map, | ||||
855 | (setter) _pyAudio_MacOSX_hostApiSpecificStreamInfo_antiset, | ||||
856 | "channel map", | ||||
857 | NULL((void*)0)}, | ||||
858 | |||||
859 | {NULL((void*)0)} | ||||
860 | }; | ||||
861 | |||||
862 | static PyTypeObject _pyAudio_MacOSX_hostApiSpecificStreamInfoType = { | ||||
863 | PyVarObject_HEAD_INIT(NULL, 0){ { 1, ((void*)0) }, 0 }, | ||||
864 | "_portaudio.PaMacCoreStreamInfo", /*tp_name*/ | ||||
865 | sizeof(_pyAudio_MacOSX_hostApiSpecificStreamInfo), /*tp_basicsize*/ | ||||
866 | 0, /*tp_itemsize*/ | ||||
867 | /*tp_dealloc*/ | ||||
868 | (destructor) _pyAudio_MacOSX_hostApiSpecificStreamInfo_dealloc, | ||||
869 | 0, /*tp_print*/ | ||||
870 | 0, /*tp_getattr*/ | ||||
871 | 0, /*tp_setattr*/ | ||||
872 | 0, /*tp_compare*/ | ||||
873 | 0, /*tp_repr*/ | ||||
874 | 0, /*tp_as_number*/ | ||||
875 | 0, /*tp_as_sequence*/ | ||||
876 | 0, /*tp_as_mapping*/ | ||||
877 | 0, /*tp_hash */ | ||||
878 | 0, /*tp_call*/ | ||||
879 | 0, /*tp_str*/ | ||||
880 | 0, /*tp_getattro*/ | ||||
881 | 0, /*tp_setattro*/ | ||||
882 | 0, /*tp_as_buffer*/ | ||||
883 | Py_TPFLAGS_DEFAULT( 0 | (1UL << 18) | 0), /*tp_flags*/ | ||||
884 | "Mac OS X Specific HostAPI configuration", /* tp_doc */ | ||||
885 | 0, /* tp_traverse */ | ||||
886 | 0, /* tp_clear */ | ||||
887 | 0, /* tp_richcompare */ | ||||
888 | 0, /* tp_weaklistoffset */ | ||||
889 | 0, /* tp_iter */ | ||||
890 | 0, /* tp_iternext */ | ||||
891 | 0, /* tp_methods */ | ||||
892 | 0, /* tp_members */ | ||||
893 | _pyAudio_MacOSX_hostApiSpecificStreamInfo_getseters, /* tp_getset */ | ||||
894 | 0, /* tp_base */ | ||||
895 | 0, /* tp_dict */ | ||||
896 | 0, /* tp_descr_get */ | ||||
897 | 0, /* tp_descr_set */ | ||||
898 | 0, /* tp_dictoffset */ | ||||
899 | (int (*)(PyObject*, PyObject*, PyObject*))_pyAudio_MacOSX_hostApiSpecificStreamInfo_init, /* tp_init */ | ||||
900 | 0, /* tp_alloc */ | ||||
901 | 0, /* tp_new */ | ||||
902 | }; | ||||
903 | #endif | ||||
904 | |||||
905 | |||||
906 | /************************************************************* | ||||
907 | * Stream Wrapper Python Object | ||||
908 | *************************************************************/ | ||||
909 | |||||
910 | typedef struct { | ||||
911 | PyObject *callback; | ||||
912 | long main_thread_id; | ||||
913 | unsigned int frame_size; | ||||
914 | } PyAudioCallbackContext; | ||||
915 | |||||
916 | typedef struct { | ||||
917 | PyObject_HEADPyObject ob_base; | ||||
918 | PaStream *stream; | ||||
919 | PaStreamParameters *inputParameters; | ||||
920 | PaStreamParameters *outputParameters; | ||||
921 | |||||
922 | /* include PaStreamInfo too! */ | ||||
923 | PaStreamInfo *streamInfo; | ||||
924 | |||||
925 | /* context for callback */ | ||||
926 | PyAudioCallbackContext *callbackContext; | ||||
927 | |||||
928 | int is_open; | ||||
929 | } _pyAudio_Stream; | ||||
930 | |||||
931 | static int | ||||
932 | _is_open(_pyAudio_Stream *obj) { | ||||
933 | return (obj) && (obj->is_open); | ||||
934 | } | ||||
935 | |||||
936 | static void | ||||
937 | _cleanup_Stream_object(_pyAudio_Stream *streamObject) | ||||
938 | { | ||||
939 | if (streamObject->stream != NULL((void*)0)) { | ||||
940 | Py_BEGIN_ALLOW_THREADS{ PyThreadState *_save; _save = PyEval_SaveThread(); | ||||
941 | Pa_CloseStream(streamObject->stream); | ||||
942 | Py_END_ALLOW_THREADSPyEval_RestoreThread(_save); } | ||||
943 | streamObject->stream = NULL((void*)0); | ||||
944 | } | ||||
945 | |||||
946 | if (streamObject->streamInfo) | ||||
947 | streamObject->streamInfo = NULL((void*)0); | ||||
948 | |||||
949 | if (streamObject->inputParameters != NULL((void*)0)) { | ||||
950 | free(streamObject->inputParameters); | ||||
951 | streamObject->inputParameters = NULL((void*)0); | ||||
952 | } | ||||
953 | |||||
954 | if (streamObject->outputParameters != NULL((void*)0)) { | ||||
955 | free(streamObject->outputParameters); | ||||
956 | streamObject->outputParameters = NULL((void*)0); | ||||
957 | } | ||||
958 | |||||
959 | if (streamObject->callbackContext != NULL((void*)0)) { | ||||
960 | Py_XDECREF(streamObject->callbackContext->callback)_Py_XDECREF(((PyObject*)(streamObject->callbackContext-> callback))); | ||||
961 | free(streamObject->callbackContext); | ||||
962 | streamObject->callbackContext = NULL((void*)0); | ||||
963 | } | ||||
964 | |||||
965 | /* designate the stream as closed */ | ||||
966 | streamObject->is_open = 0; | ||||
967 | } | ||||
968 | |||||
969 | static void | ||||
970 | _pyAudio_Stream_dealloc(_pyAudio_Stream* self) | ||||
971 | { | ||||
972 | /* deallocate memory if necessary */ | ||||
973 | _cleanup_Stream_object(self); | ||||
974 | |||||
975 | /* free the object */ | ||||
976 | Py_TYPE(self)(((PyObject*)(self))->ob_type)->tp_free((PyObject*) self); | ||||
977 | } | ||||
978 | |||||
979 | |||||
980 | static PyObject * | ||||
981 | _pyAudio_Stream_get_structVersion(_pyAudio_Stream *self, | ||||
982 | void *closure) | ||||
983 | { | ||||
984 | /* sanity check */ | ||||
985 | if (!_is_open(self)) { | ||||
986 | PyErr_SetObject(PyExc_IOError, | ||||
987 | Py_BuildValue("(s,i)", | ||||
988 | "Stream closed", | ||||
989 | paBadStreamPtr)); | ||||
990 | return NULL((void*)0); | ||||
991 | } | ||||
992 | |||||
993 | if ((!self->streamInfo)) { | ||||
994 | PyErr_SetObject(PyExc_IOError, | ||||
995 | Py_BuildValue("(s,i)", | ||||
996 | "No StreamInfo available", | ||||
997 | paBadStreamPtr)); | ||||
998 | return NULL((void*)0); | ||||
999 | } | ||||
1000 | |||||
1001 | return PyLong_FromLong(self->streamInfo->structVersion); | ||||
1002 | } | ||||
1003 | |||||
1004 | static PyObject * | ||||
1005 | _pyAudio_Stream_get_inputLatency(_pyAudio_Stream *self, | ||||
1006 | void *closure) | ||||
1007 | { | ||||
1008 | /* sanity check */ | ||||
1009 | if (!_is_open(self)) { | ||||
1010 | PyErr_SetObject(PyExc_IOError, | ||||
1011 | Py_BuildValue("(s,i)", | ||||
1012 | "Stream closed", | ||||
1013 | paBadStreamPtr)); | ||||
1014 | return NULL((void*)0); | ||||
1015 | } | ||||
1016 | |||||
1017 | /* sanity check */ | ||||
1018 | if ((!self->streamInfo)) { | ||||
1019 | PyErr_SetObject(PyExc_IOError, | ||||
1020 | Py_BuildValue("(s,i)", | ||||
1021 | "No StreamInfo available", | ||||
1022 | paBadStreamPtr)); | ||||
1023 | return NULL((void*)0); | ||||
1024 | } | ||||
1025 | |||||
1026 | return PyFloat_FromDouble(self->streamInfo->inputLatency); | ||||
1027 | } | ||||
1028 | |||||
1029 | static PyObject * | ||||
1030 | _pyAudio_Stream_get_outputLatency(_pyAudio_Stream *self, | ||||
1031 | void *closure) | ||||
1032 | { | ||||
1033 | /* sanity check */ | ||||
1034 | if (!_is_open(self)) { | ||||
1035 | PyErr_SetObject(PyExc_IOError, | ||||
1036 | Py_BuildValue("(s,i)", | ||||
1037 | "Stream closed", | ||||
1038 | paBadStreamPtr)); | ||||
1039 | return NULL((void*)0); | ||||
1040 | } | ||||
1041 | |||||
1042 | /* sanity check */ | ||||
1043 | if ((!self->streamInfo)) { | ||||
1044 | PyErr_SetObject(PyExc_IOError, | ||||
1045 | Py_BuildValue("(s,i)", | ||||
1046 | "No StreamInfo available", | ||||
1047 | paBadStreamPtr)); | ||||
1048 | return NULL((void*)0); | ||||
1049 | } | ||||
1050 | |||||
1051 | return PyFloat_FromDouble(self->streamInfo->outputLatency); | ||||
1052 | } | ||||
1053 | |||||
1054 | static PyObject * | ||||
1055 | _pyAudio_Stream_get_sampleRate(_pyAudio_Stream *self, | ||||
1056 | void *closure) | ||||
1057 | { | ||||
1058 | /* sanity check */ | ||||
1059 | if (!_is_open(self)) { | ||||
1060 | PyErr_SetObject(PyExc_IOError, | ||||
1061 | Py_BuildValue("(s,i)", | ||||
1062 | "Stream closed", | ||||
1063 | paBadStreamPtr)); | ||||
1064 | return NULL((void*)0); | ||||
1065 | } | ||||
1066 | |||||
1067 | /* sanity check */ | ||||
1068 | if ((!self->streamInfo)) { | ||||
1069 | PyErr_SetObject(PyExc_IOError, | ||||
1070 | Py_BuildValue("(s,i)", | ||||
1071 | "No StreamInfo available", | ||||
1072 | paBadStreamPtr)); | ||||
1073 | return NULL((void*)0); | ||||
1074 | } | ||||
1075 | |||||
1076 | return PyFloat_FromDouble(self->streamInfo->sampleRate); | ||||
1077 | } | ||||
1078 | |||||
1079 | static int | ||||
1080 | _pyAudio_Stream_antiset(_pyAudio_Stream *self, | ||||
1081 | PyObject *value, | ||||
1082 | void *closure) | ||||
1083 | { | ||||
1084 | /* read-only: do not allow users to change values */ | ||||
1085 | PyErr_SetString(PyExc_AttributeError, | ||||
1086 | "Fields read-only: cannot modify values"); | ||||
1087 | return -1; | ||||
1088 | } | ||||
1089 | |||||
1090 | static PyGetSetDef _pyAudio_Stream_getseters[] = { | ||||
1091 | {"structVersion", | ||||
1092 | (getter) _pyAudio_Stream_get_structVersion, | ||||
1093 | (setter) _pyAudio_Stream_antiset, | ||||
1094 | "struct version", | ||||
1095 | NULL((void*)0)}, | ||||
1096 | |||||
1097 | {"inputLatency", | ||||
1098 | (getter) _pyAudio_Stream_get_inputLatency, | ||||
1099 | (setter) _pyAudio_Stream_antiset, | ||||
1100 | "input latency", | ||||
1101 | NULL((void*)0)}, | ||||
1102 | |||||
1103 | {"outputLatency", | ||||
1104 | (getter) _pyAudio_Stream_get_outputLatency, | ||||
1105 | (setter) _pyAudio_Stream_antiset, | ||||
1106 | "output latency", | ||||
1107 | NULL((void*)0)}, | ||||
1108 | |||||
1109 | {"sampleRate", | ||||
1110 | (getter) _pyAudio_Stream_get_sampleRate, | ||||
1111 | (setter) _pyAudio_Stream_antiset, | ||||
1112 | "sample rate", | ||||
1113 | NULL((void*)0)}, | ||||
1114 | |||||
1115 | {NULL((void*)0)} | ||||
1116 | }; | ||||
1117 | |||||
1118 | static PyTypeObject _pyAudio_StreamType = { | ||||
1119 | PyVarObject_HEAD_INIT(NULL, 0){ { 1, ((void*)0) }, 0 }, | ||||
1120 | "_portaudio.Stream", /*tp_name*/ | ||||
1121 | sizeof(_pyAudio_Stream), /*tp_basicsize*/ | ||||
1122 | 0, /*tp_itemsize*/ | ||||
1123 | (destructor) _pyAudio_Stream_dealloc, /*tp_dealloc*/ | ||||
1124 | 0, /*tp_print*/ | ||||
1125 | 0, /*tp_getattr*/ | ||||
1126 | 0, /*tp_setattr*/ | ||||
1127 | 0, /*tp_compare*/ | ||||
1128 | 0, /*tp_repr*/ | ||||
1129 | 0, /*tp_as_number*/ | ||||
1130 | 0, /*tp_as_sequence*/ | ||||
1131 | 0, /*tp_as_mapping*/ | ||||
1132 | 0, /*tp_hash */ | ||||
1133 | 0, /*tp_call*/ | ||||
1134 | 0, /*tp_str*/ | ||||
1135 | 0, /*tp_getattro*/ | ||||
1136 | 0, /*tp_setattro*/ | ||||
1137 | 0, /*tp_as_buffer*/ | ||||
1138 | Py_TPFLAGS_DEFAULT( 0 | (1UL << 18) | 0), /*tp_flags*/ | ||||
1139 | "Port Audio Stream", /* tp_doc */ | ||||
1140 | 0, /* tp_traverse */ | ||||
1141 | 0, /* tp_clear */ | ||||
1142 | 0, /* tp_richcompare */ | ||||
1143 | 0, /* tp_weaklistoffset */ | ||||
1144 | 0, /* tp_iter */ | ||||
1145 | 0, /* tp_iternext */ | ||||
1146 | 0, /* tp_methods */ | ||||
1147 | 0, /* tp_members */ | ||||
1148 | _pyAudio_Stream_getseters, /* tp_getset */ | ||||
1149 | 0, /* tp_base */ | ||||
1150 | 0, /* tp_dict */ | ||||
1151 | 0, /* tp_descr_get */ | ||||
1152 | 0, /* tp_descr_set */ | ||||
1153 | 0, /* tp_dictoffset */ | ||||
1154 | 0, /* tp_init */ | ||||
1155 | 0, /* tp_alloc */ | ||||
1156 | 0, /* tp_new */ | ||||
1157 | }; | ||||
1158 | |||||
1159 | static _pyAudio_Stream * | ||||
1160 | _create_Stream_object(void) | ||||
1161 | { | ||||
1162 | _pyAudio_Stream *obj; | ||||
1163 | |||||
1164 | /* don't allow subclassing? */ | ||||
1165 | obj = (_pyAudio_Stream *) PyObject_New(_pyAudio_Stream,( (_pyAudio_Stream *) _PyObject_New(&_pyAudio_StreamType) ) | ||||
1166 | &_pyAudio_StreamType)( (_pyAudio_Stream *) _PyObject_New(&_pyAudio_StreamType) ); | ||||
1167 | return obj; | ||||
1168 | } | ||||
1169 | |||||
1170 | |||||
1171 | /************************************************************ | ||||
1172 | * | ||||
1173 | * III. PortAudio Method Implementations | ||||
1174 | * | ||||
1175 | ************************************************************/ | ||||
1176 | |||||
1177 | /************************************************************* | ||||
1178 | * Version Info | ||||
1179 | *************************************************************/ | ||||
1180 | |||||
1181 | static PyObject * | ||||
1182 | pa_get_version(PyObject *self, PyObject *args) | ||||
1183 | { | ||||
1184 | if (!PyArg_ParseTuple(args, "")) | ||||
1185 | return NULL((void*)0); | ||||
1186 | |||||
1187 | return PyLong_FromLong(Pa_GetVersion()); | ||||
1188 | } | ||||
1189 | |||||
1190 | static PyObject * | ||||
1191 | pa_get_version_text(PyObject *self, PyObject *args) | ||||
1192 | { | ||||
1193 | if (!PyArg_ParseTuple(args, "")) | ||||
1194 | return NULL((void*)0); | ||||
1195 | |||||
1196 | return PyUnicode_FromString(Pa_GetVersionText()); | ||||
1197 | } | ||||
1198 | |||||
1199 | /************************************************************* | ||||
1200 | * Initialization/Termination | ||||
1201 | *************************************************************/ | ||||
1202 | |||||
1203 | static PyObject * | ||||
1204 | pa_initialize(PyObject *self, PyObject *args) | ||||
1205 | { | ||||
1206 | int err; | ||||
1207 | err = Pa_Initialize(); | ||||
1208 | if (err != paNoError) { | ||||
1209 | Pa_Terminate(); | ||||
1210 | #ifdef VERBOSE | ||||
1211 | fprintf(stderr, "An error occured while using the portaudio stream\n")__fprintf_chk (stderr, 2 - 1, "An error occured while using the portaudio stream\n" ); | ||||
1212 | fprintf(stderr, "Error number: %d\n", err)__fprintf_chk (stderr, 2 - 1, "Error number: %d\n", err); | ||||
1213 | fprintf(stderr, "Error message: %s\n", Pa_GetErrorText(err))__fprintf_chk (stderr, 2 - 1, "Error message: %s\n", Pa_GetErrorText (err)); | ||||
1214 | #endif | ||||
1215 | PyErr_SetObject(PyExc_IOError, | ||||
1216 | Py_BuildValue("(s,i)", | ||||
1217 | Pa_GetErrorText(err), err)); | ||||
1218 | return NULL((void*)0); | ||||
1219 | } | ||||
1220 | |||||
1221 | Py_INCREF(Py_None)_Py_INCREF(((PyObject*)((&_Py_NoneStruct)))); | ||||
1222 | return Py_None(&_Py_NoneStruct); | ||||
1223 | } | ||||
1224 | |||||
1225 | static PyObject * | ||||
1226 | pa_terminate(PyObject *self, PyObject *args) | ||||
1227 | { | ||||
1228 | Pa_Terminate(); | ||||
1229 | Py_INCREF(Py_None)_Py_INCREF(((PyObject*)((&_Py_NoneStruct)))); | ||||
1230 | return Py_None(&_Py_NoneStruct); | ||||
1231 | } | ||||
1232 | |||||
1233 | /************************************************************* | ||||
1234 | * HostAPI | ||||
1235 | *************************************************************/ | ||||
1236 | |||||
1237 | static PyObject * | ||||
1238 | pa_get_host_api_count(PyObject *self, PyObject *args) | ||||
1239 | { | ||||
1240 | PaHostApiIndex count; | ||||
1241 | |||||
1242 | if (!PyArg_ParseTuple(args, "")) | ||||
1243 | return NULL((void*)0); | ||||
1244 | |||||
1245 | count = Pa_GetHostApiCount(); | ||||
1246 | |||||
1247 | if (count < 0) { | ||||
1248 | |||||
1249 | #ifdef VERBOSE | ||||
1250 | fprintf(stderr, "An error occured while using the portaudio stream\n")__fprintf_chk (stderr, 2 - 1, "An error occured while using the portaudio stream\n" ); | ||||
1251 | fprintf(stderr, "Error number: %d\n", count)__fprintf_chk (stderr, 2 - 1, "Error number: %d\n", count); | ||||
1252 | fprintf(stderr, "Error message: %s\n", Pa_GetErrorText(count))__fprintf_chk (stderr, 2 - 1, "Error message: %s\n", Pa_GetErrorText (count)); | ||||
1253 | #endif | ||||
1254 | |||||
1255 | PyErr_SetObject(PyExc_IOError, | ||||
1256 | Py_BuildValue("(s,i)", | ||||
1257 | Pa_GetErrorText(count), count)); | ||||
1258 | return NULL((void*)0); | ||||
1259 | } | ||||
1260 | |||||
1261 | return PyLong_FromLong(count); | ||||
1262 | } | ||||
1263 | |||||
1264 | static PyObject * | ||||
1265 | pa_get_default_host_api(PyObject *self, PyObject *args) | ||||
1266 | { | ||||
1267 | PaHostApiIndex index; | ||||
1268 | |||||
1269 | if (!PyArg_ParseTuple(args, "")) | ||||
1270 | return NULL((void*)0); | ||||
1271 | |||||
1272 | index = Pa_GetDefaultHostApi(); | ||||
1273 | |||||
1274 | if (index < 0) { | ||||
1275 | |||||
1276 | #ifdef VERBOSE | ||||
1277 | fprintf(stderr, "An error occured while using the portaudio stream\n")__fprintf_chk (stderr, 2 - 1, "An error occured while using the portaudio stream\n" ); | ||||
1278 | fprintf(stderr, "Error number: %d\n", index)__fprintf_chk (stderr, 2 - 1, "Error number: %d\n", index); | ||||
1279 | fprintf(stderr, "Error message: %s\n", Pa_GetErrorText(index))__fprintf_chk (stderr, 2 - 1, "Error message: %s\n", Pa_GetErrorText (index)); | ||||
1280 | #endif | ||||
1281 | |||||
1282 | PyErr_SetObject(PyExc_IOError, | ||||
1283 | Py_BuildValue("(s,i)", | ||||
1284 | Pa_GetErrorText(index), index)); | ||||
1285 | return NULL((void*)0); | ||||
1286 | } | ||||
1287 | |||||
1288 | return PyLong_FromLong(index); | ||||
1289 | } | ||||
1290 | |||||
1291 | static PyObject * | ||||
1292 | pa_host_api_type_id_to_host_api_index(PyObject *self, PyObject *args) | ||||
1293 | { | ||||
1294 | PaHostApiTypeId typeid; | ||||
1295 | PaHostApiIndex index; | ||||
1296 | |||||
1297 | if (!PyArg_ParseTuple(args, "i", &typeid)) | ||||
1298 | return NULL((void*)0); | ||||
1299 | |||||
1300 | index = Pa_HostApiTypeIdToHostApiIndex(typeid); | ||||
1301 | |||||
1302 | if (index < 0) { | ||||
1303 | |||||
1304 | #ifdef VERBOSE | ||||
1305 | fprintf(stderr, "An error occured while using the portaudio stream\n")__fprintf_chk (stderr, 2 - 1, "An error occured while using the portaudio stream\n" ); | ||||
1306 | fprintf(stderr, "Error number: %d\n", index)__fprintf_chk (stderr, 2 - 1, "Error number: %d\n", index); | ||||
1307 | fprintf(stderr, "Error message: %s\n", Pa_GetErrorText(index))__fprintf_chk (stderr, 2 - 1, "Error message: %s\n", Pa_GetErrorText (index)); | ||||
1308 | #endif | ||||
1309 | |||||
1310 | PyErr_SetObject(PyExc_IOError, | ||||
1311 | Py_BuildValue("(s,i)", | ||||
1312 | Pa_GetErrorText(index), index)); | ||||
1313 | return NULL((void*)0); | ||||
1314 | } | ||||
1315 | |||||
1316 | return PyLong_FromLong(index); | ||||
1317 | } | ||||
1318 | |||||
1319 | static PyObject * | ||||
1320 | pa_host_api_device_index_to_device_index(PyObject *self, PyObject *args) | ||||
1321 | { | ||||
1322 | PaHostApiIndex apiIndex; | ||||
1323 | int hostApiDeviceindex; | ||||
1324 | PaDeviceIndex devIndex; | ||||
1325 | |||||
1326 | |||||
1327 | if (!PyArg_ParseTuple(args, "ii", &apiIndex, &hostApiDeviceindex)) | ||||
1328 | return NULL((void*)0); | ||||
1329 | |||||
1330 | devIndex = Pa_HostApiDeviceIndexToDeviceIndex(apiIndex, hostApiDeviceindex); | ||||
1331 | if (devIndex < 0) { | ||||
1332 | |||||
1333 | #ifdef VERBOSE | ||||
1334 | fprintf(stderr, "An error occured while using the portaudio stream\n")__fprintf_chk (stderr, 2 - 1, "An error occured while using the portaudio stream\n" ); | ||||
1335 | fprintf(stderr, "Error number: %d\n", devIndex)__fprintf_chk (stderr, 2 - 1, "Error number: %d\n", devIndex); | ||||
1336 | fprintf(stderr, "Error message: %s\n", Pa_GetErrorText(devIndex))__fprintf_chk (stderr, 2 - 1, "Error message: %s\n", Pa_GetErrorText (devIndex)); | ||||
1337 | #endif | ||||
1338 | |||||
1339 | PyErr_SetObject(PyExc_IOError, | ||||
1340 | Py_BuildValue("(s,i)", | ||||
1341 | Pa_GetErrorText(devIndex), devIndex)); | ||||
1342 | return NULL((void*)0); | ||||
1343 | } | ||||
1344 | |||||
1345 | return PyLong_FromLong(devIndex); | ||||
1346 | } | ||||
1347 | |||||
1348 | static PyObject * | ||||
1349 | pa_get_host_api_info(PyObject *self, PyObject *args) | ||||
1350 | { | ||||
1351 | PaHostApiIndex index; | ||||
1352 | PaHostApiInfo* _info; | ||||
1353 | _pyAudio_paHostApiInfo* py_info; | ||||
1354 | |||||
1355 | if (!PyArg_ParseTuple(args, "i", &index)) | ||||
1356 | return NULL((void*)0); | ||||
1357 | |||||
1358 | _info = (PaHostApiInfo *) Pa_GetHostApiInfo(index); | ||||
1359 | |||||
1360 | if (!_info) { | ||||
1361 | PyErr_SetObject(PyExc_IOError, | ||||
1362 | Py_BuildValue("(s,i)", | ||||
1363 | "Invalid host api info", | ||||
1364 | paInvalidHostApi)); | ||||
1365 | return NULL((void*)0); | ||||
1366 | } | ||||
1367 | |||||
1368 | py_info = _create_paHostApiInfo_object(); | ||||
1369 | py_info->apiInfo = _info; | ||||
1370 | |||||
1371 | return (PyObject *) py_info; | ||||
1372 | } | ||||
1373 | |||||
1374 | /************************************************************* | ||||
1375 | * Device API | ||||
1376 | *************************************************************/ | ||||
1377 | |||||
1378 | static PyObject * | ||||
1379 | pa_get_device_count(PyObject *self, PyObject *args) | ||||
1380 | { | ||||
1381 | PaDeviceIndex count; | ||||
1382 | |||||
1383 | if (!PyArg_ParseTuple(args, "")) | ||||
1384 | return NULL((void*)0); | ||||
1385 | |||||
1386 | count = Pa_GetDeviceCount(); | ||||
1387 | if (count < 0) { | ||||
1388 | |||||
1389 | #ifdef VERBOSE | ||||
1390 | fprintf(stderr, "An error occured while using the portaudio stream\n")__fprintf_chk (stderr, 2 - 1, "An error occured while using the portaudio stream\n" ); | ||||
1391 | fprintf(stderr, "Error number: %d\n", count)__fprintf_chk (stderr, 2 - 1, "Error number: %d\n", count); | ||||
1392 | fprintf(stderr, "Error message: %s\n", Pa_GetErrorText(count))__fprintf_chk (stderr, 2 - 1, "Error message: %s\n", Pa_GetErrorText (count)); | ||||
1393 | #endif | ||||
1394 | |||||
1395 | PyErr_SetObject(PyExc_IOError, | ||||
1396 | Py_BuildValue("(s,i)", | ||||
1397 | Pa_GetErrorText(count), count)); | ||||
1398 | return NULL((void*)0); | ||||
1399 | } | ||||
1400 | |||||
1401 | return PyLong_FromLong(count); | ||||
1402 | } | ||||
1403 | |||||
1404 | static PyObject * | ||||
1405 | pa_get_default_input_device(PyObject *self, PyObject *args) | ||||
1406 | { | ||||
1407 | PaDeviceIndex index; | ||||
1408 | |||||
1409 | if (!PyArg_ParseTuple(args, "")) | ||||
1410 | return NULL((void*)0); | ||||
1411 | |||||
1412 | index = Pa_GetDefaultInputDevice(); | ||||
1413 | if (index == paNoDevice((PaDeviceIndex)-1)) { | ||||
1414 | PyErr_SetString(PyExc_IOError, "No Default Input Device Available"); | ||||
1415 | return NULL((void*)0); | ||||
1416 | } else if (index < 0) { | ||||
1417 | |||||
1418 | #ifdef VERBOSE | ||||
1419 | fprintf(stderr, "An error occured while using the portaudio stream\n")__fprintf_chk (stderr, 2 - 1, "An error occured while using the portaudio stream\n" ); | ||||
1420 | fprintf(stderr, "Error number: %d\n", index)__fprintf_chk (stderr, 2 - 1, "Error number: %d\n", index); | ||||
1421 | fprintf(stderr, "Error message: %s\n", Pa_GetErrorText(index))__fprintf_chk (stderr, 2 - 1, "Error message: %s\n", Pa_GetErrorText (index)); | ||||
1422 | #endif | ||||
1423 | |||||
1424 | PyErr_SetObject(PyExc_IOError, | ||||
1425 | Py_BuildValue("(s,i)", | ||||
1426 | Pa_GetErrorText(index), index)); | ||||
1427 | return NULL((void*)0); | ||||
1428 | } | ||||
1429 | |||||
1430 | return PyLong_FromLong(index); | ||||
1431 | } | ||||
1432 | |||||
1433 | static PyObject * | ||||
1434 | pa_get_default_output_device(PyObject *self, PyObject *args) | ||||
1435 | { | ||||
1436 | PaDeviceIndex index; | ||||
1437 | |||||
1438 | if (!PyArg_ParseTuple(args, "")) | ||||
1439 | return NULL((void*)0); | ||||
1440 | |||||
1441 | index = Pa_GetDefaultOutputDevice(); | ||||
1442 | if (index == paNoDevice((PaDeviceIndex)-1)) { | ||||
1443 | PyErr_SetString(PyExc_IOError, "No Default Output Device Available"); | ||||
1444 | return NULL((void*)0); | ||||
1445 | } else if (index < 0) { | ||||
1446 | |||||
1447 | #ifdef VERBOSE | ||||
1448 | fprintf(stderr, "An error occured while using the portaudio stream\n")__fprintf_chk (stderr, 2 - 1, "An error occured while using the portaudio stream\n" ); | ||||
1449 | fprintf(stderr, "Error number: %d\n", index)__fprintf_chk (stderr, 2 - 1, "Error number: %d\n", index); | ||||
1450 | fprintf(stderr, "Error message: %s\n", Pa_GetErrorText(index))__fprintf_chk (stderr, 2 - 1, "Error message: %s\n", Pa_GetErrorText (index)); | ||||
1451 | #endif | ||||
1452 | |||||
1453 | PyErr_SetObject(PyExc_IOError, | ||||
1454 | Py_BuildValue("(s,i)", | ||||
1455 | Pa_GetErrorText(index), index)); | ||||
1456 | return NULL((void*)0); | ||||
1457 | } | ||||
1458 | |||||
1459 | return PyLong_FromLong(index); | ||||
1460 | } | ||||
1461 | |||||
1462 | static PyObject * | ||||
1463 | pa_get_device_info(PyObject *self, PyObject *args) | ||||
1464 | { | ||||
1465 | PaDeviceIndex index; | ||||
1466 | PaDeviceInfo* _info; | ||||
1467 | _pyAudio_paDeviceInfo* py_info; | ||||
1468 | |||||
1469 | if (!PyArg_ParseTuple(args, "i", &index)) | ||||
1470 | return NULL((void*)0); | ||||
1471 | |||||
1472 | _info = (PaDeviceInfo *) Pa_GetDeviceInfo(index); | ||||
1473 | |||||
1474 | if (!_info) { | ||||
1475 | PyErr_SetObject(PyExc_IOError, | ||||
1476 | Py_BuildValue("(s,i)", | ||||
1477 | "Invalid device info", paInvalidDevice)); | ||||
1478 | return NULL((void*)0); | ||||
1479 | } | ||||
1480 | |||||
1481 | py_info = _create_paDeviceInfo_object(); | ||||
1482 | py_info->devInfo = _info; | ||||
1483 | return (PyObject *) py_info; | ||||
1484 | } | ||||
1485 | |||||
1486 | /************************************************************* | ||||
1487 | * Stream Open / Close / Supported | ||||
1488 | *************************************************************/ | ||||
1489 | |||||
1490 | int | ||||
1491 | _stream_callback_cfunction(const void *input, | ||||
1492 | void *output, | ||||
1493 | unsigned long frameCount, | ||||
1494 | const PaStreamCallbackTimeInfo *timeInfo, | ||||
1495 | PaStreamCallbackFlags statusFlags, | ||||
1496 | void *userData) | ||||
1497 | { | ||||
1498 | int return_val = paAbort; | ||||
1499 | PyGILState_STATE _state = PyGILState_Ensure(); | ||||
1500 | |||||
1501 | #ifdef VERBOSE | ||||
1502 | if (statusFlags != 0) { | ||||
1503 | printf("Status flag set: ")__printf_chk (2 - 1, "Status flag set: "); | ||||
1504 | if (statusFlags & paInputUnderflow((PaStreamCallbackFlags) 0x00000001)) { | ||||
1505 | printf("input underflow!\n")__printf_chk (2 - 1, "input underflow!\n"); | ||||
1506 | } | ||||
1507 | if (statusFlags & paInputOverflow((PaStreamCallbackFlags) 0x00000002)) { | ||||
1508 | printf("input overflow!\n")__printf_chk (2 - 1, "input overflow!\n"); | ||||
1509 | } | ||||
1510 | if (statusFlags & paOutputUnderflow((PaStreamCallbackFlags) 0x00000004)) { | ||||
1511 | printf("output underflow!\n")__printf_chk (2 - 1, "output underflow!\n"); | ||||
1512 | } | ||||
1513 | if (statusFlags & paOutputUnderflow((PaStreamCallbackFlags) 0x00000004)) { | ||||
1514 | printf("output overflow!\n")__printf_chk (2 - 1, "output overflow!\n"); | ||||
1515 | } | ||||
1516 | if (statusFlags & paPrimingOutput((PaStreamCallbackFlags) 0x00000010)) { | ||||
1517 | printf("priming output!\n")__printf_chk (2 - 1, "priming output!\n"); | ||||
1518 | } | ||||
1519 | } | ||||
1520 | #endif | ||||
1521 | |||||
1522 | PyAudioCallbackContext *context = (PyAudioCallbackContext *)userData; | ||||
1523 | PyObject *py_callback = context->callback; | ||||
1524 | unsigned int bytes_per_frame = context->frame_size; | ||||
1525 | long main_thread_id = context->main_thread_id; | ||||
1526 | |||||
1527 | PyObject *py_frame_count = PyLong_FromUnsignedLong(frameCount); | ||||
1528 | PyObject *py_time_info = Py_BuildValue("{s:d,s:d,s:d}", | ||||
1529 | "input_buffer_adc_time", | ||||
1530 | timeInfo->inputBufferAdcTime, | ||||
1531 | "current_time", | ||||
1532 | timeInfo->currentTime, | ||||
1533 | "output_buffer_dac_time", | ||||
1534 | timeInfo->outputBufferDacTime); | ||||
1535 | PyObject *py_status_flags = PyLong_FromUnsignedLong(statusFlags); | ||||
1536 | PyObject *py_input_data = Py_None(&_Py_NoneStruct); | ||||
1537 | const char *pData; | ||||
1538 | int output_len; | ||||
1539 | PyObject *py_result; | ||||
1540 | |||||
1541 | if (input) { | ||||
1542 | py_input_data = PyBytes_FromStringAndSize(input, | ||||
1543 | bytes_per_frame * frameCount); | ||||
1544 | } | ||||
1545 | |||||
1546 | py_result = PyObject_CallFunctionObjArgs(py_callback, | ||||
1547 | py_input_data, | ||||
1548 | py_frame_count, | ||||
1549 | py_time_info, | ||||
1550 | py_status_flags, | ||||
1551 | NULL((void*)0)); | ||||
1552 | |||||
1553 | if (py_result == NULL((void*)0)) { | ||||
1554 | #ifdef VERBOSE | ||||
1555 | fprintf(stderr, "An error occured while using the portaudio stream\n")__fprintf_chk (stderr, 2 - 1, "An error occured while using the portaudio stream\n" ); | ||||
1556 | fprintf(stderr, "Error message: Could not call callback function\n")__fprintf_chk (stderr, 2 - 1, "Error message: Could not call callback function\n" ); | ||||
1557 | #endif | ||||
1558 | PyObject *err = PyErr_Occurred(); | ||||
1559 | |||||
1560 | if (err) { | ||||
1561 | PyThreadState_SetAsyncExc(main_thread_id, err); | ||||
1562 | |||||
1563 | // Print out a stack trace to help debugging. | ||||
1564 | // TODO: make VERBOSE a runtime flag so users can control | ||||
1565 | // the amount of logging. | ||||
1566 | PyErr_Print(); | ||||
1567 | } | ||||
1568 | |||||
1569 | goto end; | ||||
1570 | } | ||||
1571 | |||||
1572 | |||||
1573 | if (!PyArg_ParseTuple(py_result, | ||||
1574 | "z#i", | ||||
1575 | &pData, | ||||
1576 | &output_len, | ||||
1577 | &return_val)) { | ||||
1578 | #ifdef VERBOSE | ||||
1579 | fprintf(stderr, "An error occured while using the portaudio stream\n")__fprintf_chk (stderr, 2 - 1, "An error occured while using the portaudio stream\n" ); | ||||
1580 | fprintf(stderr, "Error message: Could not parse callback return value\n")__fprintf_chk (stderr, 2 - 1, "Error message: Could not parse callback return value\n" ); | ||||
1581 | #endif | ||||
1582 | |||||
1583 | PyObject *err = PyErr_Occurred(); | ||||
1584 | |||||
1585 | if (err) { | ||||
1586 | PyThreadState_SetAsyncExc(main_thread_id, err); | ||||
1587 | |||||
1588 | // Print out a stack trace to help debugging. | ||||
1589 | // TODO: make VERBOSE a runtime flag so users can control | ||||
1590 | // the amount of logging. | ||||
1591 | PyErr_Print(); | ||||
1592 | } | ||||
1593 | |||||
1594 | Py_XDECREF(py_result)_Py_XDECREF(((PyObject*)(py_result))); | ||||
1595 | return_val = paAbort; | ||||
1596 | goto end; | ||||
1597 | } | ||||
1598 | |||||
1599 | Py_DECREF(py_result)_Py_DECREF(((PyObject*)(py_result))); | ||||
1600 | |||||
1601 | if ((return_val != paComplete) && | ||||
1602 | (return_val != paAbort) && | ||||
1603 | (return_val != paContinue)) { | ||||
1604 | PyErr_SetString(PyExc_ValueError, | ||||
1605 | "Invalid PaStreamCallbackResult from callback"); | ||||
1606 | PyThreadState_SetAsyncExc(main_thread_id, PyErr_Occurred()); | ||||
1607 | PyErr_Print(); | ||||
1608 | |||||
1609 | // Quit the callback loop | ||||
1610 | return_val = paAbort; | ||||
1611 | |||||
1612 | goto end; | ||||
1613 | } | ||||
1614 | |||||
1615 | // Copy bytes for playback only if this is an output stream: | ||||
1616 | |||||
1617 | if (output) { | ||||
1618 | char *output_data = (char*)output; | ||||
1619 | memcpy(output_data, pData, min(output_len, bytes_per_frame * frameCount)({ __typeof__ (output_len) _a = (output_len); __typeof__ (bytes_per_frame * frameCount) _b = (bytes_per_frame * frameCount); _a < _b ? _a : _b; })); | ||||
1620 | |||||
1621 | // Pad out the rest of the buffer with 0s if callback returned | ||||
1622 | // too few frames (and assume paComplete). | ||||
1623 | if (output_len < (frameCount * bytes_per_frame)) { | ||||
1624 | memset(output_data + output_len, | ||||
1625 | 0, | ||||
1626 | (frameCount * bytes_per_frame) - output_len); | ||||
1627 | return_val = paComplete; | ||||
1628 | } | ||||
1629 | } | ||||
1630 | |||||
1631 | end: | ||||
1632 | |||||
1633 | if (input) { | ||||
1634 | // Decrement this at the end, after memcpy, in case the user | ||||
1635 | // returns py_input_data back for playback. | ||||
1636 | Py_DECREF(py_input_data)_Py_DECREF(((PyObject*)(py_input_data))); | ||||
1637 | } | ||||
1638 | |||||
1639 | Py_XDECREF(py_frame_count)_Py_XDECREF(((PyObject*)(py_frame_count))); | ||||
1640 | Py_XDECREF(py_time_info)_Py_XDECREF(((PyObject*)(py_time_info))); | ||||
1641 | Py_XDECREF(py_status_flags)_Py_XDECREF(((PyObject*)(py_status_flags))); | ||||
1642 | |||||
1643 | PyGILState_Release(_state); | ||||
1644 | return return_val; | ||||
1645 | } | ||||
1646 | |||||
1647 | static PyObject * | ||||
1648 | pa_open(PyObject *self, PyObject *args, PyObject *kwargs) | ||||
1649 | { | ||||
1650 | int rate, channels; | ||||
1651 | int input, output, frames_per_buffer; | ||||
1652 | int input_device_index = -1; | ||||
1653 | int output_device_index = -1; | ||||
1654 | PyObject *input_device_index_arg = NULL((void*)0); | ||||
1655 | PyObject *output_device_index_arg = NULL((void*)0); | ||||
1656 | PyObject *stream_callback = NULL((void*)0); | ||||
1657 | PaSampleFormat format; | ||||
1658 | PaError err; | ||||
1659 | PyObject *input_device_index_long; | ||||
1660 | PyObject *output_device_index_long; | ||||
1661 | PaStreamParameters *outputParameters = NULL((void*)0); | ||||
1662 | PaStreamParameters *inputParameters = NULL((void*)0); | ||||
1663 | PaStream *stream = NULL((void*)0); | ||||
1664 | PaStreamInfo *streamInfo = NULL((void*)0); | ||||
1665 | PyAudioCallbackContext *context = NULL((void*)0); | ||||
1666 | _pyAudio_Stream *streamObject; | ||||
1667 | |||||
1668 | /* pass in rate, channel, width */ | ||||
1669 | static char *kwlist[] = {"rate", | ||||
1670 | "channels", | ||||
1671 | "format", | ||||
1672 | "input", | ||||
1673 | "output", | ||||
1674 | "input_device_index", | ||||
1675 | "output_device_index", | ||||
1676 | "frames_per_buffer", | ||||
1677 | "input_host_api_specific_stream_info", | ||||
1678 | "output_host_api_specific_stream_info", | ||||
1679 | "stream_callback", | ||||
1680 | NULL((void*)0)}; | ||||
1681 | |||||
1682 | #ifdef MACOSX | ||||
1683 | _pyAudio_MacOSX_hostApiSpecificStreamInfo *inputHostSpecificStreamInfo = | ||||
1684 | NULL((void*)0); | ||||
1685 | _pyAudio_MacOSX_hostApiSpecificStreamInfo *outputHostSpecificStreamInfo = | ||||
1686 | NULL((void*)0); | ||||
1687 | #else | ||||
1688 | /* mostly ignored...*/ | ||||
1689 | PyObject *inputHostSpecificStreamInfo = NULL((void*)0); | ||||
1690 | PyObject *outputHostSpecificStreamInfo = NULL((void*)0); | ||||
1691 | #endif | ||||
1692 | |||||
1693 | /* default to neither output nor input */ | ||||
1694 | input = 0; | ||||
1695 | output = 0; | ||||
1696 | frames_per_buffer = DEFAULT_FRAMES_PER_BUFFER1024; | ||||
1697 | |||||
1698 | if (!PyArg_ParseTupleAndKeywords(args, kwargs, | ||||
| |||||
1699 | #ifdef MACOSX | ||||
1700 | "iik|iiOOiO!O!O", | ||||
1701 | #else | ||||
1702 | "iik|iiOOiOOO", | ||||
1703 | #endif | ||||
1704 | kwlist, | ||||
1705 | &rate, &channels, &format, | ||||
1706 | &input, &output, | ||||
1707 | &input_device_index_arg, | ||||
1708 | &output_device_index_arg, | ||||
1709 | &frames_per_buffer, | ||||
1710 | #ifdef MACOSX | ||||
1711 | &_pyAudio_MacOSX_hostApiSpecificStreamInfoType, | ||||
1712 | #endif | ||||
1713 | &inputHostSpecificStreamInfo, | ||||
1714 | #ifdef MACOSX | ||||
1715 | &_pyAudio_MacOSX_hostApiSpecificStreamInfoType, | ||||
1716 | #endif | ||||
1717 | &outputHostSpecificStreamInfo, | ||||
1718 | &stream_callback)) | ||||
1719 | |||||
1720 | return NULL((void*)0); | ||||
1721 | |||||
1722 | if (stream_callback && (PyCallable_Check(stream_callback) == 0)) { | ||||
1723 | PyErr_SetString(PyExc_TypeError, "stream_callback must be callable"); | ||||
1724 | return NULL((void*)0); | ||||
1725 | } | ||||
1726 | |||||
1727 | /* check to see if device indices were specified */ | ||||
1728 | if ((input_device_index_arg == NULL((void*)0)) || | ||||
1729 | (input_device_index_arg == Py_None(&_Py_NoneStruct))) { | ||||
1730 | |||||
1731 | #ifdef VERBOSE | ||||
1732 | printf("Using default input device\n")__printf_chk (2 - 1, "Using default input device\n"); | ||||
1733 | #endif | ||||
1734 | |||||
1735 | input_device_index = -1; | ||||
1736 | |||||
1737 | } else { | ||||
1738 | // Support both Python 2 and Python 3 by using PyNumber_Check | ||||
1739 | if (!PyNumber_Check(input_device_index_arg)) { | ||||
1740 | PyErr_SetString(PyExc_ValueError, | ||||
1741 | "input_device_index must be integer (or None)"); | ||||
1742 | return NULL((void*)0); | ||||
1743 | } | ||||
1744 | |||||
1745 | input_device_index_long = | ||||
1746 | PyNumber_Long(input_device_index_arg); | ||||
1747 | |||||
1748 | input_device_index = (int) PyLong_AsLong(input_device_index_long); | ||||
1749 | Py_DECREF(input_device_index_long)_Py_DECREF(((PyObject*)(input_device_index_long))); | ||||
1750 | |||||
1751 | #ifdef VERBOSE | ||||
1752 | printf("Using input device index number: %d\n", input_device_index)__printf_chk (2 - 1, "Using input device index number: %d\n", input_device_index); | ||||
1753 | #endif | ||||
1754 | } | ||||
1755 | |||||
1756 | if ((output_device_index_arg == NULL((void*)0)) || | ||||
1757 | (output_device_index_arg == Py_None(&_Py_NoneStruct))) { | ||||
1758 | |||||
1759 | #ifdef VERBOSE | ||||
1760 | printf("Using default output device\n")__printf_chk (2 - 1, "Using default output device\n"); | ||||
1761 | #endif | ||||
1762 | |||||
1763 | output_device_index = -1; | ||||
1764 | |||||
1765 | } else { | ||||
1766 | // Support both Python 2 and Python 3 by using PyNumber_Check | ||||
1767 | if (!PyNumber_Check(output_device_index_arg)) { | ||||
1768 | PyErr_SetString(PyExc_ValueError, | ||||
1769 | "output_device_index must be integer (or None)"); | ||||
1770 | return NULL((void*)0); | ||||
1771 | } | ||||
1772 | |||||
1773 | output_device_index_long = | ||||
1774 | PyNumber_Long(output_device_index_arg); | ||||
1775 | output_device_index = (int) PyLong_AsLong(output_device_index_long); | ||||
1776 | Py_DECREF(output_device_index_long)_Py_DECREF(((PyObject*)(output_device_index_long))); | ||||
1777 | |||||
1778 | #ifdef VERBOSE | ||||
1779 | printf("Using output device index number: %d\n", output_device_index)__printf_chk (2 - 1, "Using output device index number: %d\n" , output_device_index); | ||||
1780 | #endif | ||||
1781 | } | ||||
1782 | |||||
1783 | /* sanity checks */ | ||||
1784 | if (input == 0 && output == 0) { | ||||
1785 | PyErr_SetString(PyExc_ValueError, "Must specify either input or output"); | ||||
1786 | return NULL((void*)0); | ||||
1787 | } | ||||
1788 | |||||
1789 | if (channels < 1) { | ||||
1790 | PyErr_SetString(PyExc_ValueError, "Invalid audio channels"); | ||||
1791 | return NULL((void*)0); | ||||
1792 | } | ||||
1793 | |||||
1794 | if (output) { | ||||
1795 | outputParameters = | ||||
1796 | (PaStreamParameters *) malloc(sizeof(PaStreamParameters)); | ||||
1797 | |||||
1798 | |||||
1799 | if (output_device_index < 0) | ||||
1800 | /* default output device */ | ||||
1801 | outputParameters->device = Pa_GetDefaultOutputDevice(); | ||||
1802 | else | ||||
1803 | outputParameters->device = output_device_index; | ||||
1804 | |||||
1805 | /* final check -- ensure that there is a default device */ | ||||
1806 | if (outputParameters->device < 0 || | ||||
1807 | outputParameters->device >= Pa_GetDeviceCount()) { | ||||
1808 | free(outputParameters); | ||||
1809 | PyErr_SetObject(PyExc_IOError, | ||||
1810 | Py_BuildValue("(s,i)", | ||||
1811 | "Invalid output device " | ||||
1812 | "(no default output device)", | ||||
1813 | paInvalidDevice)); | ||||
1814 | return NULL((void*)0); | ||||
1815 | } | ||||
1816 | |||||
1817 | outputParameters->channelCount = channels; | ||||
1818 | outputParameters->sampleFormat = format; | ||||
1819 | outputParameters->suggestedLatency = | ||||
1820 | Pa_GetDeviceInfo(outputParameters->device)->defaultLowOutputLatency; | ||||
1821 | outputParameters->hostApiSpecificStreamInfo = NULL((void*)0); | ||||
1822 | |||||
1823 | #ifdef MACOSX | ||||
1824 | if (outputHostSpecificStreamInfo) { | ||||
1825 | outputParameters->hostApiSpecificStreamInfo = | ||||
1826 | outputHostSpecificStreamInfo->paMacCoreStreamInfo; | ||||
1827 | } | ||||
1828 | #endif | ||||
1829 | |||||
1830 | } | ||||
1831 | |||||
1832 | if (input
| ||||
1833 | inputParameters = | ||||
1834 | (PaStreamParameters *) malloc(sizeof(PaStreamParameters)); | ||||
1835 | |||||
1836 | if (input_device_index
| ||||
1837 | /* default output device */ | ||||
1838 | inputParameters->device = Pa_GetDefaultInputDevice(); | ||||
1839 | } else { | ||||
1840 | inputParameters->device = input_device_index; | ||||
1841 | } | ||||
1842 | |||||
1843 | /* final check -- ensure that there is a default device */ | ||||
1844 | if (inputParameters->device < 0) { | ||||
1845 | free(inputParameters); | ||||
1846 | PyErr_SetObject(PyExc_IOError, | ||||
1847 | Py_BuildValue("(s,i)", | ||||
| |||||
1848 | "Invalid input device " | ||||
1849 | "(no default output device)", | ||||
1850 | paInvalidDevice)); | ||||
1851 | return NULL((void*)0); | ||||
1852 | } | ||||
1853 | |||||
1854 | inputParameters->channelCount = channels; | ||||
1855 | inputParameters->sampleFormat = format; | ||||
1856 | inputParameters->suggestedLatency = | ||||
1857 | Pa_GetDeviceInfo(inputParameters->device)->defaultLowInputLatency; | ||||
1858 | inputParameters->hostApiSpecificStreamInfo = NULL((void*)0); | ||||
1859 | |||||
1860 | #ifdef MACOSX | ||||
1861 | if (inputHostSpecificStreamInfo) { | ||||
1862 | inputParameters->hostApiSpecificStreamInfo = | ||||
1863 | inputHostSpecificStreamInfo->paMacCoreStreamInfo; | ||||
1864 | } | ||||
1865 | #endif | ||||
1866 | |||||
1867 | } | ||||
1868 | |||||
1869 | // Handle callback mode: | ||||
1870 | if (stream_callback) { | ||||
1871 | Py_INCREF(stream_callback)_Py_INCREF(((PyObject*)(stream_callback))); | ||||
1872 | context = (PyAudioCallbackContext *) malloc(sizeof(PyAudioCallbackContext)); | ||||
1873 | context->callback = (PyObject *) stream_callback; | ||||
1874 | context->main_thread_id = PyThreadState_Get()->thread_id; | ||||
1875 | context->frame_size = Pa_GetSampleSize(format) * channels; | ||||
1876 | } | ||||
1877 | |||||
1878 | err = Pa_OpenStream(&stream, | ||||
1879 | /* input/output parameters */ | ||||
1880 | /* NULL values are ignored */ | ||||
1881 | inputParameters, | ||||
1882 | outputParameters, | ||||
1883 | /* Samples Per Second */ | ||||
1884 | rate, | ||||
1885 | /* allocate frames in the buffer */ | ||||
1886 | frames_per_buffer, | ||||
1887 | /* we won't output out of range samples | ||||
1888 | so don't bother clipping them */ | ||||
1889 | paClipOff((PaStreamFlags) 0x00000001), | ||||
1890 | /* callback, if specified */ | ||||
1891 | (stream_callback)?(_stream_callback_cfunction):(NULL((void*)0)), | ||||
1892 | /* callback userData, if applicable */ | ||||
1893 | context); | ||||
1894 | |||||
1895 | if (err != paNoError) { | ||||
1896 | |||||
1897 | #ifdef VERBOSE | ||||
1898 | fprintf(stderr, "An error occured while using the portaudio stream\n")__fprintf_chk (stderr, 2 - 1, "An error occured while using the portaudio stream\n" ); | ||||
1899 | fprintf(stderr, "Error number: %d\n", err)__fprintf_chk (stderr, 2 - 1, "Error number: %d\n", err); | ||||
1900 | fprintf(stderr, "Error message: %s\n", Pa_GetErrorText(err))__fprintf_chk (stderr, 2 - 1, "Error message: %s\n", Pa_GetErrorText (err)); | ||||
1901 | #endif | ||||
1902 | |||||
1903 | PyErr_SetObject(PyExc_IOError, | ||||
1904 | Py_BuildValue("(s,i)", | ||||
1905 | Pa_GetErrorText(err), err)); | ||||
1906 | return NULL((void*)0); | ||||
1907 | } | ||||
1908 | |||||
1909 | streamInfo = (PaStreamInfo *) Pa_GetStreamInfo(stream); | ||||
1910 | if (!streamInfo) { | ||||
1911 | /* Pa_Terminate(); */ | ||||
1912 | PyErr_SetObject(PyExc_IOError, | ||||
1913 | Py_BuildValue("(s,i)", | ||||
1914 | "Could not get stream information", | ||||
1915 | paInternalError)); | ||||
1916 | return NULL((void*)0); | ||||
1917 | } | ||||
1918 | |||||
1919 | streamObject = _create_Stream_object(); | ||||
1920 | streamObject->stream = stream; | ||||
1921 | streamObject->inputParameters = inputParameters; | ||||
1922 | streamObject->outputParameters = outputParameters; | ||||
1923 | streamObject->is_open = 1; | ||||
1924 | streamObject->streamInfo = streamInfo; | ||||
1925 | streamObject->callbackContext = context; | ||||
1926 | |||||
1927 | return (PyObject *) streamObject; | ||||
1928 | } | ||||
1929 | |||||
1930 | static PyObject * | ||||
1931 | pa_close(PyObject *self, PyObject *args) | ||||
1932 | { | ||||
1933 | PyObject *stream_arg; | ||||
1934 | _pyAudio_Stream *streamObject; | ||||
1935 | |||||
1936 | if (!PyArg_ParseTuple(args, "O!", &_pyAudio_StreamType, &stream_arg)) | ||||
1937 | return NULL((void*)0); | ||||
1938 | |||||
1939 | streamObject = (_pyAudio_Stream *) stream_arg; | ||||
1940 | |||||
1941 | _cleanup_Stream_object(streamObject); | ||||
1942 | |||||
1943 | Py_INCREF(Py_None)_Py_INCREF(((PyObject*)((&_Py_NoneStruct)))); | ||||
1944 | return Py_None(&_Py_NoneStruct); | ||||
1945 | } | ||||
1946 | |||||
1947 | static PyObject * | ||||
1948 | pa_get_sample_size(PyObject *self, PyObject *args) | ||||
1949 | { | ||||
1950 | PaSampleFormat format; | ||||
1951 | int size_in_bytes; | ||||
1952 | |||||
1953 | if (!PyArg_ParseTuple(args, "k", &format)) | ||||
1954 | return NULL((void*)0); | ||||
1955 | |||||
1956 | size_in_bytes = Pa_GetSampleSize(format); | ||||
1957 | |||||
1958 | if (size_in_bytes < 0) { | ||||
1959 | PyErr_SetObject(PyExc_ValueError, | ||||
1960 | Py_BuildValue("(s,i)", | ||||
1961 | Pa_GetErrorText(size_in_bytes), | ||||
1962 | size_in_bytes)); | ||||
1963 | return NULL((void*)0); | ||||
1964 | } | ||||
1965 | |||||
1966 | return PyLong_FromLong(size_in_bytes); | ||||
1967 | } | ||||
1968 | |||||
1969 | |||||
1970 | static PyObject * | ||||
1971 | pa_is_format_supported(PyObject *self, PyObject *args, | ||||
1972 | PyObject *kwargs) | ||||
1973 | { | ||||
1974 | /* pass in rate, channel, width */ | ||||
1975 | static char *kwlist[] = { | ||||
1976 | "sample_rate", | ||||
1977 | "input_device", | ||||
1978 | "input_channels", | ||||
1979 | "input_format", | ||||
1980 | "output_device", | ||||
1981 | "output_channels", | ||||
1982 | "output_format", | ||||
1983 | NULL((void*)0) | ||||
1984 | }; | ||||
1985 | |||||
1986 | int input_device, input_channels; | ||||
1987 | int output_device, output_channels; | ||||
1988 | float sample_rate; | ||||
1989 | PaStreamParameters inputParams; | ||||
1990 | PaStreamParameters outputParams; | ||||
1991 | PaSampleFormat input_format, output_format; | ||||
1992 | PaError error; | ||||
1993 | |||||
1994 | input_device = input_channels = | ||||
1995 | output_device = output_channels = -1; | ||||
1996 | |||||
1997 | input_format = output_format = -1; | ||||
1998 | |||||
1999 | if (!PyArg_ParseTupleAndKeywords(args, kwargs, "f|iikiik", kwlist, | ||||
2000 | &sample_rate, | ||||
2001 | &input_device, | ||||
2002 | &input_channels, | ||||
2003 | &input_format, | ||||
2004 | &output_device, | ||||
2005 | &output_channels, | ||||
2006 | &output_format)) | ||||
2007 | return NULL((void*)0); | ||||
2008 | |||||
2009 | if (!(input_device < 0)) { | ||||
2010 | inputParams.device = input_device; | ||||
2011 | inputParams.channelCount = input_channels; | ||||
2012 | inputParams.sampleFormat = input_format; | ||||
2013 | inputParams.suggestedLatency = 0; | ||||
2014 | inputParams.hostApiSpecificStreamInfo = NULL((void*)0); | ||||
2015 | } | ||||
2016 | |||||
2017 | if (!(output_device < 0)) { | ||||
2018 | outputParams.device = output_device; | ||||
2019 | outputParams.channelCount = output_channels; | ||||
2020 | outputParams.sampleFormat = output_format; | ||||
2021 | outputParams.suggestedLatency = 0; | ||||
2022 | outputParams.hostApiSpecificStreamInfo = NULL((void*)0); | ||||
2023 | } | ||||
2024 | |||||
2025 | error = Pa_IsFormatSupported((input_device < 0) ? NULL((void*)0) : &inputParams, | ||||
2026 | (output_device < 0) ? NULL((void*)0) : &outputParams, | ||||
2027 | sample_rate); | ||||
2028 | |||||
2029 | if (error == paFormatIsSupported(0)) { | ||||
2030 | Py_INCREF(Py_True)_Py_INCREF(((PyObject*)(((PyObject *) &_Py_TrueStruct)))); | ||||
2031 | return Py_True((PyObject *) &_Py_TrueStruct); | ||||
2032 | } else { | ||||
2033 | PyErr_SetObject(PyExc_ValueError, | ||||
2034 | Py_BuildValue("(s,i)", | ||||
2035 | Pa_GetErrorText(error), | ||||
2036 | error)); | ||||
2037 | return NULL((void*)0); | ||||
2038 | } | ||||
2039 | } | ||||
2040 | |||||
2041 | /************************************************************* | ||||
2042 | * Stream Start / Stop / Info | ||||
2043 | *************************************************************/ | ||||
2044 | |||||
2045 | static PyObject * | ||||
2046 | pa_start_stream(PyObject *self, PyObject *args) | ||||
2047 | { | ||||
2048 | int err; | ||||
2049 | PyObject *stream_arg; | ||||
2050 | _pyAudio_Stream *streamObject; | ||||
2051 | PaStream *stream; | ||||
2052 | |||||
2053 | if (!PyArg_ParseTuple(args, "O!", &_pyAudio_StreamType, &stream_arg)) | ||||
2054 | return NULL((void*)0); | ||||
2055 | |||||
2056 | streamObject = (_pyAudio_Stream *) stream_arg; | ||||
2057 | |||||
2058 | if (!_is_open(streamObject)) { | ||||
2059 | PyErr_SetObject(PyExc_IOError, | ||||
2060 | Py_BuildValue("(s,i)", | ||||
2061 | "Stream closed", | ||||
2062 | paBadStreamPtr)); | ||||
2063 | return NULL((void*)0); | ||||
2064 | } | ||||
2065 | |||||
2066 | stream = streamObject->stream; | ||||
2067 | |||||
2068 | if ( ((err = Pa_StartStream(stream)) != paNoError) && | ||||
2069 | (err != paStreamIsNotStopped)) { | ||||
2070 | _cleanup_Stream_object(streamObject); | ||||
2071 | |||||
2072 | #ifdef VERBOSE | ||||
2073 | fprintf(stderr, "An error occured while using the portaudio stream\n")__fprintf_chk (stderr, 2 - 1, "An error occured while using the portaudio stream\n" ); | ||||
2074 | fprintf(stderr, "Error number: %d\n", err)__fprintf_chk (stderr, 2 - 1, "Error number: %d\n", err); | ||||
2075 | fprintf(stderr, "Error message: %s\n", Pa_GetErrorText(err))__fprintf_chk (stderr, 2 - 1, "Error message: %s\n", Pa_GetErrorText (err)); | ||||
2076 | #endif | ||||
2077 | |||||
2078 | PyErr_SetObject(PyExc_IOError, | ||||
2079 | Py_BuildValue("(s,i)", | ||||
2080 | Pa_GetErrorText(err), | ||||
2081 | err)); | ||||
2082 | return NULL((void*)0); | ||||
2083 | } | ||||
2084 | |||||
2085 | Py_INCREF(Py_None)_Py_INCREF(((PyObject*)((&_Py_NoneStruct)))); | ||||
2086 | return Py_None(&_Py_NoneStruct); | ||||
2087 | } | ||||
2088 | |||||
2089 | static PyObject * | ||||
2090 | pa_stop_stream(PyObject *self, PyObject *args) | ||||
2091 | { | ||||
2092 | |||||
2093 | int err; | ||||
2094 | PyObject *stream_arg; | ||||
2095 | _pyAudio_Stream *streamObject; | ||||
2096 | PaStream *stream; | ||||
2097 | |||||
2098 | if (!PyArg_ParseTuple(args, "O!", &_pyAudio_StreamType, &stream_arg)) | ||||
2099 | return NULL((void*)0); | ||||
2100 | |||||
2101 | streamObject = (_pyAudio_Stream *) stream_arg; | ||||
2102 | |||||
2103 | if (!_is_open(streamObject)) { | ||||
2104 | PyErr_SetString(PyExc_IOError, "Stream not open"); | ||||
2105 | return NULL((void*)0); | ||||
2106 | } | ||||
2107 | |||||
2108 | stream = streamObject->stream; | ||||
2109 | |||||
2110 | Py_BEGIN_ALLOW_THREADS{ PyThreadState *_save; _save = PyEval_SaveThread(); | ||||
2111 | err = Pa_StopStream(stream); | ||||
2112 | Py_END_ALLOW_THREADSPyEval_RestoreThread(_save); } | ||||
2113 | |||||
2114 | if ((err != paNoError) && (err != paStreamIsStopped)) { | ||||
2115 | _cleanup_Stream_object(streamObject); | ||||
2116 | |||||
2117 | #ifdef VERBOSE | ||||
2118 | fprintf(stderr, "An error occured while using the portaudio stream\n")__fprintf_chk (stderr, 2 - 1, "An error occured while using the portaudio stream\n" ); | ||||
2119 | fprintf(stderr, "Error number: %d\n", err)__fprintf_chk (stderr, 2 - 1, "Error number: %d\n", err); | ||||
2120 | fprintf(stderr, "Error message: %s\n", Pa_GetErrorText(err))__fprintf_chk (stderr, 2 - 1, "Error message: %s\n", Pa_GetErrorText (err)); | ||||
2121 | #endif | ||||
2122 | |||||
2123 | PyErr_SetObject(PyExc_IOError, | ||||
2124 | Py_BuildValue("(s,i)", | ||||
2125 | Pa_GetErrorText(err), | ||||
2126 | err)); | ||||
2127 | return NULL((void*)0); | ||||
2128 | } | ||||
2129 | |||||
2130 | Py_INCREF(Py_None)_Py_INCREF(((PyObject*)((&_Py_NoneStruct)))); | ||||
2131 | return Py_None(&_Py_NoneStruct); | ||||
2132 | } | ||||
2133 | |||||
2134 | static PyObject * | ||||
2135 | pa_abort_stream(PyObject *self, PyObject *args) | ||||
2136 | { | ||||
2137 | int err; | ||||
2138 | PyObject *stream_arg; | ||||
2139 | _pyAudio_Stream *streamObject; | ||||
2140 | PaStream *stream; | ||||
2141 | |||||
2142 | if (!PyArg_ParseTuple(args, "O!", &_pyAudio_StreamType, &stream_arg)) | ||||
2143 | return NULL((void*)0); | ||||
2144 | |||||
2145 | streamObject = (_pyAudio_Stream *) stream_arg; | ||||
2146 | |||||
2147 | if (!_is_open(streamObject)) { | ||||
2148 | PyErr_SetString(PyExc_IOError, "Stream not open"); | ||||
2149 | return NULL((void*)0); | ||||
2150 | } | ||||
2151 | |||||
2152 | stream = streamObject->stream; | ||||
2153 | |||||
2154 | Py_BEGIN_ALLOW_THREADS{ PyThreadState *_save; _save = PyEval_SaveThread(); | ||||
2155 | err = Pa_AbortStream(stream); | ||||
2156 | Py_END_ALLOW_THREADSPyEval_RestoreThread(_save); } | ||||
2157 | |||||
2158 | if ((err != paNoError) && (err != paStreamIsStopped)) { | ||||
2159 | _cleanup_Stream_object(streamObject); | ||||
2160 | |||||
2161 | #ifdef VERBOSE | ||||
2162 | fprintf(stderr, "An error occured while using the portaudio stream\n")__fprintf_chk (stderr, 2 - 1, "An error occured while using the portaudio stream\n" ); | ||||
2163 | fprintf(stderr, "Error number: %d\n", err)__fprintf_chk (stderr, 2 - 1, "Error number: %d\n", err); | ||||
2164 | fprintf(stderr, "Error message: %s\n", Pa_GetErrorText(err))__fprintf_chk (stderr, 2 - 1, "Error message: %s\n", Pa_GetErrorText (err)); | ||||
2165 | #endif | ||||
2166 | |||||
2167 | PyErr_SetObject(PyExc_IOError, | ||||
2168 | Py_BuildValue("(s,i)", | ||||
2169 | Pa_GetErrorText(err), | ||||
2170 | err)); | ||||
2171 | return NULL((void*)0); | ||||
2172 | } | ||||
2173 | |||||
2174 | Py_INCREF(Py_None)_Py_INCREF(((PyObject*)((&_Py_NoneStruct)))); | ||||
2175 | return Py_None(&_Py_NoneStruct); | ||||
2176 | } | ||||
2177 | |||||
2178 | static PyObject * | ||||
2179 | pa_is_stream_stopped(PyObject *self, PyObject *args) | ||||
2180 | { | ||||
2181 | int err; | ||||
2182 | PyObject *stream_arg; | ||||
2183 | _pyAudio_Stream *streamObject; | ||||
2184 | PaStream *stream; | ||||
2185 | |||||
2186 | if (!PyArg_ParseTuple(args, "O!", &_pyAudio_StreamType, &stream_arg)) | ||||
2187 | return NULL((void*)0); | ||||
2188 | |||||
2189 | streamObject = (_pyAudio_Stream *) stream_arg; | ||||
2190 | |||||
2191 | if (!_is_open(streamObject)) { | ||||
2192 | PyErr_SetObject(PyExc_IOError, | ||||
2193 | Py_BuildValue("(s,i)", | ||||
2194 | "Stream closed", | ||||
2195 | paBadStreamPtr)); | ||||
2196 | return NULL((void*)0); | ||||
2197 | } | ||||
2198 | |||||
2199 | stream = streamObject->stream; | ||||
2200 | |||||
2201 | if ((err = Pa_IsStreamStopped(stream)) < 0) { | ||||
2202 | _cleanup_Stream_object(streamObject); | ||||
2203 | |||||
2204 | #ifdef VERBOSE | ||||
2205 | fprintf(stderr, "An error occured while using the portaudio stream\n")__fprintf_chk (stderr, 2 - 1, "An error occured while using the portaudio stream\n" ); | ||||
2206 | fprintf(stderr, "Error number: %d\n", err)__fprintf_chk (stderr, 2 - 1, "Error number: %d\n", err); | ||||
2207 | fprintf(stderr, "Error message: %s\n", Pa_GetErrorText(err))__fprintf_chk (stderr, 2 - 1, "Error message: %s\n", Pa_GetErrorText (err)); | ||||
2208 | #endif | ||||
2209 | |||||
2210 | PyErr_SetObject(PyExc_IOError, | ||||
2211 | Py_BuildValue("(s,i)", | ||||
2212 | Pa_GetErrorText(err), | ||||
2213 | err)); | ||||
2214 | return NULL((void*)0); | ||||
2215 | } | ||||
2216 | |||||
2217 | if (err) { | ||||
2218 | Py_INCREF(Py_True)_Py_INCREF(((PyObject*)(((PyObject *) &_Py_TrueStruct)))); | ||||
2219 | return Py_True((PyObject *) &_Py_TrueStruct); | ||||
2220 | } | ||||
2221 | |||||
2222 | Py_INCREF(Py_False)_Py_INCREF(((PyObject*)(((PyObject *) &_Py_FalseStruct))) ); | ||||
2223 | return Py_False((PyObject *) &_Py_FalseStruct); | ||||
2224 | } | ||||
2225 | |||||
2226 | static PyObject * | ||||
2227 | pa_is_stream_active(PyObject *self, PyObject *args) | ||||
2228 | { | ||||
2229 | |||||
2230 | int err; | ||||
2231 | PyObject *stream_arg; | ||||
2232 | _pyAudio_Stream *streamObject; | ||||
2233 | PaStream *stream; | ||||
2234 | |||||
2235 | if (!PyArg_ParseTuple(args, "O!", &_pyAudio_StreamType, &stream_arg)) | ||||
2236 | return NULL((void*)0); | ||||
2237 | |||||
2238 | streamObject = (_pyAudio_Stream *) stream_arg; | ||||
2239 | |||||
2240 | if (!_is_open(streamObject)) { | ||||
2241 | PyErr_SetString(PyExc_IOError, "Stream not open"); | ||||
2242 | return NULL((void*)0); | ||||
2243 | } | ||||
2244 | |||||
2245 | stream = streamObject->stream; | ||||
2246 | |||||
2247 | if ((err = Pa_IsStreamActive(stream)) < 0) { | ||||
2248 | _cleanup_Stream_object(streamObject); | ||||
2249 | |||||
2250 | #ifdef VERBOSE | ||||
2251 | fprintf(stderr, "An error occured while using the portaudio stream\n")__fprintf_chk (stderr, 2 - 1, "An error occured while using the portaudio stream\n" ); | ||||
2252 | fprintf(stderr, "Error number: %d\n", err)__fprintf_chk (stderr, 2 - 1, "Error number: %d\n", err); | ||||
2253 | fprintf(stderr, "Error message: %s\n", Pa_GetErrorText(err))__fprintf_chk (stderr, 2 - 1, "Error message: %s\n", Pa_GetErrorText (err)); | ||||
2254 | #endif | ||||
2255 | |||||
2256 | PyErr_SetObject(PyExc_IOError, | ||||
2257 | Py_BuildValue("(s,i)", | ||||
2258 | Pa_GetErrorText(err), | ||||
2259 | err)); | ||||
2260 | return NULL((void*)0); | ||||
2261 | } | ||||
2262 | |||||
2263 | if (err) { | ||||
2264 | Py_INCREF(Py_True)_Py_INCREF(((PyObject*)(((PyObject *) &_Py_TrueStruct)))); | ||||
2265 | return Py_True((PyObject *) &_Py_TrueStruct); | ||||
2266 | } | ||||
2267 | |||||
2268 | Py_INCREF(Py_False)_Py_INCREF(((PyObject*)(((PyObject *) &_Py_FalseStruct))) ); | ||||
2269 | return Py_False((PyObject *) &_Py_FalseStruct); | ||||
2270 | } | ||||
2271 | |||||
2272 | static PyObject * | ||||
2273 | pa_get_stream_time(PyObject *self, PyObject *args) | ||||
2274 | { | ||||
2275 | double time; | ||||
2276 | PyObject *stream_arg; | ||||
2277 | _pyAudio_Stream *streamObject; | ||||
2278 | PaStream *stream; | ||||
2279 | |||||
2280 | if (!PyArg_ParseTuple(args, "O!", &_pyAudio_StreamType, &stream_arg)) | ||||
2281 | return NULL((void*)0); | ||||
2282 | |||||
2283 | streamObject = (_pyAudio_Stream *) stream_arg; | ||||
2284 | |||||
2285 | if (!_is_open(streamObject)) { | ||||
2286 | PyErr_SetObject(PyExc_IOError, | ||||
2287 | Py_BuildValue("(s,i)", | ||||
2288 | "Stream closed", | ||||
2289 | paBadStreamPtr)); | ||||
2290 | return NULL((void*)0); | ||||
2291 | } | ||||
2292 | |||||
2293 | stream = streamObject->stream; | ||||
2294 | |||||
2295 | if ((time = Pa_GetStreamTime(stream)) == 0) { | ||||
2296 | _cleanup_Stream_object(streamObject); | ||||
2297 | PyErr_SetObject(PyExc_IOError, | ||||
2298 | Py_BuildValue("(s,i)", | ||||
2299 | "Internal Error", | ||||
2300 | paInternalError)); | ||||
2301 | return NULL((void*)0); | ||||
2302 | } | ||||
2303 | |||||
2304 | return PyFloat_FromDouble(time); | ||||
2305 | } | ||||
2306 | |||||
2307 | static PyObject * | ||||
2308 | pa_get_stream_cpu_load(PyObject *self, PyObject *args) | ||||
2309 | { | ||||
2310 | PyObject *stream_arg; | ||||
2311 | _pyAudio_Stream *streamObject; | ||||
2312 | PaStream *stream; | ||||
2313 | |||||
2314 | if (!PyArg_ParseTuple(args, "O!", &_pyAudio_StreamType, &stream_arg)) | ||||
2315 | return NULL((void*)0); | ||||
2316 | |||||
2317 | streamObject = (_pyAudio_Stream *) stream_arg; | ||||
2318 | |||||
2319 | if (!_is_open(streamObject)) { | ||||
2320 | PyErr_SetObject(PyExc_IOError, | ||||
2321 | Py_BuildValue("(s,i)", | ||||
2322 | "Stream closed", | ||||
2323 | paBadStreamPtr)); | ||||
2324 | return NULL((void*)0); | ||||
2325 | } | ||||
2326 | |||||
2327 | stream = streamObject->stream; | ||||
2328 | return PyFloat_FromDouble(Pa_GetStreamCpuLoad(stream)); | ||||
2329 | } | ||||
2330 | |||||
2331 | |||||
2332 | /************************************************************* | ||||
2333 | * Stream Read/Write | ||||
2334 | *************************************************************/ | ||||
2335 | |||||
2336 | static PyObject * | ||||
2337 | pa_write_stream(PyObject *self, PyObject *args) | ||||
2338 | { | ||||
2339 | const char *data; | ||||
2340 | int total_size; | ||||
2341 | int total_frames; | ||||
2342 | int err; | ||||
2343 | int should_throw_exception = 0; | ||||
2344 | |||||
2345 | PyObject *stream_arg; | ||||
2346 | _pyAudio_Stream *streamObject; | ||||
2347 | PaStream *stream; | ||||
2348 | |||||
2349 | if (!PyArg_ParseTuple(args, "O!s#i|i", | ||||
2350 | &_pyAudio_StreamType, | ||||
2351 | &stream_arg, | ||||
2352 | &data, | ||||
2353 | &total_size, | ||||
2354 | &total_frames, | ||||
2355 | &should_throw_exception)) | ||||
2356 | return NULL((void*)0); | ||||
2357 | |||||
2358 | /* make sure total frames is larger than 0 */ | ||||
2359 | if (total_frames < 0) { | ||||
2360 | PyErr_SetString(PyExc_ValueError, | ||||
2361 | "Invalid number of frames"); | ||||
2362 | return NULL((void*)0); | ||||
2363 | } | ||||
2364 | |||||
2365 | streamObject = (_pyAudio_Stream *) stream_arg; | ||||
2366 | |||||
2367 | if (!_is_open(streamObject)) { | ||||
2368 | PyErr_SetObject(PyExc_IOError, | ||||
2369 | Py_BuildValue("(s,i)", | ||||
2370 | "Stream closed", | ||||
2371 | paBadStreamPtr)); | ||||
2372 | return NULL((void*)0); | ||||
2373 | } | ||||
2374 | |||||
2375 | stream = streamObject->stream; | ||||
2376 | |||||
2377 | Py_BEGIN_ALLOW_THREADS{ PyThreadState *_save; _save = PyEval_SaveThread(); | ||||
2378 | err = Pa_WriteStream(stream, data, total_frames); | ||||
2379 | Py_END_ALLOW_THREADSPyEval_RestoreThread(_save); } | ||||
2380 | |||||
2381 | if (err != paNoError) { | ||||
2382 | if (err == paOutputUnderflowed) { | ||||
2383 | if (should_throw_exception) | ||||
2384 | goto error; | ||||
2385 | } else | ||||
2386 | goto error; | ||||
2387 | } | ||||
2388 | |||||
2389 | Py_INCREF(Py_None)_Py_INCREF(((PyObject*)((&_Py_NoneStruct)))); | ||||
2390 | return Py_None(&_Py_NoneStruct); | ||||
2391 | |||||
2392 | error: | ||||
2393 | /* cleanup */ | ||||
2394 | _cleanup_Stream_object(streamObject); | ||||
2395 | |||||
2396 | #ifdef VERBOSE | ||||
2397 | fprintf(stderr, "An error occured while using the portaudio stream\n")__fprintf_chk (stderr, 2 - 1, "An error occured while using the portaudio stream\n" ); | ||||
2398 | fprintf(stderr, "Error number: %d\n", err)__fprintf_chk (stderr, 2 - 1, "Error number: %d\n", err); | ||||
2399 | fprintf(stderr, "Error message: %s\n", Pa_GetErrorText(err))__fprintf_chk (stderr, 2 - 1, "Error message: %s\n", Pa_GetErrorText (err)); | ||||
2400 | #endif | ||||
2401 | |||||
2402 | PyErr_SetObject(PyExc_IOError, | ||||
2403 | Py_BuildValue("(s,i)", | ||||
2404 | Pa_GetErrorText(err), | ||||
2405 | err)); | ||||
2406 | return NULL((void*)0); | ||||
2407 | } | ||||
2408 | |||||
2409 | static PyObject * | ||||
2410 | pa_read_stream(PyObject *self, PyObject *args) | ||||
2411 | { | ||||
2412 | int err; | ||||
2413 | int total_frames; | ||||
2414 | short *sampleBlock; | ||||
2415 | int num_bytes; | ||||
2416 | PyObject *rv; | ||||
2417 | |||||
2418 | PyObject *stream_arg; | ||||
2419 | _pyAudio_Stream *streamObject; | ||||
2420 | PaStream *stream; | ||||
2421 | PaStreamParameters *inputParameters; | ||||
2422 | |||||
2423 | if (!PyArg_ParseTuple(args, "O!i", | ||||
2424 | &_pyAudio_StreamType, | ||||
2425 | &stream_arg, | ||||
2426 | &total_frames)) | ||||
2427 | return NULL((void*)0); | ||||
2428 | |||||
2429 | /* make sure value is positive! */ | ||||
2430 | if (total_frames < 0) { | ||||
2431 | PyErr_SetString(PyExc_ValueError, "Invalid number of frames"); | ||||
2432 | return NULL((void*)0); | ||||
2433 | } | ||||
2434 | |||||
2435 | streamObject = (_pyAudio_Stream *) stream_arg; | ||||
2436 | |||||
2437 | if (!_is_open(streamObject)) { | ||||
2438 | PyErr_SetObject(PyExc_IOError, | ||||
2439 | Py_BuildValue("(s,i)", | ||||
2440 | "Stream closed", | ||||
2441 | paBadStreamPtr)); | ||||
2442 | return NULL((void*)0); | ||||
2443 | } | ||||
2444 | |||||
2445 | stream = streamObject->stream; | ||||
2446 | inputParameters = streamObject->inputParameters; | ||||
2447 | num_bytes = (total_frames) * (inputParameters->channelCount) * | ||||
2448 | (Pa_GetSampleSize(inputParameters->sampleFormat)); | ||||
2449 | |||||
2450 | #ifdef VERBOSE | ||||
2451 | fprintf(stderr, "Allocating %d bytes\n", num_bytes)__fprintf_chk (stderr, 2 - 1, "Allocating %d bytes\n", num_bytes ); | ||||
2452 | #endif | ||||
2453 | |||||
2454 | rv = PyBytes_FromStringAndSize(NULL((void*)0), num_bytes); | ||||
2455 | sampleBlock = (short *) PyBytes_AsString(rv); | ||||
2456 | |||||
2457 | if (sampleBlock == NULL((void*)0)) { | ||||
2458 | PyErr_SetObject(PyExc_IOError, | ||||
2459 | Py_BuildValue("(s,i)", | ||||
2460 | "Out of memory", | ||||
2461 | paInsufficientMemory)); | ||||
2462 | return NULL((void*)0); | ||||
2463 | } | ||||
2464 | |||||
2465 | Py_BEGIN_ALLOW_THREADS{ PyThreadState *_save; _save = PyEval_SaveThread(); | ||||
2466 | err = Pa_ReadStream(stream, sampleBlock, total_frames); | ||||
2467 | Py_END_ALLOW_THREADSPyEval_RestoreThread(_save); } | ||||
2468 | |||||
2469 | if (err != paNoError) { | ||||
2470 | |||||
2471 | /* ignore input overflow and output underflow */ | ||||
2472 | if (err & paInputOverflowed) { | ||||
2473 | |||||
2474 | #ifdef VERBOSE | ||||
2475 | fprintf(stderr, "Input Overflow.\n")__fprintf_chk (stderr, 2 - 1, "Input Overflow.\n"); | ||||
2476 | #endif | ||||
2477 | |||||
2478 | } else if (err & paOutputUnderflowed) { | ||||
2479 | |||||
2480 | #ifdef VERBOSE | ||||
2481 | fprintf(stderr, "Output Underflow.\n")__fprintf_chk (stderr, 2 - 1, "Output Underflow.\n"); | ||||
2482 | #endif | ||||
2483 | |||||
2484 | } else { | ||||
2485 | /* clean up */ | ||||
2486 | _cleanup_Stream_object(streamObject); | ||||
2487 | } | ||||
2488 | |||||
2489 | /* free the string buffer */ | ||||
2490 | Py_XDECREF(rv)_Py_XDECREF(((PyObject*)(rv))); | ||||
2491 | |||||
2492 | PyErr_SetObject(PyExc_IOError, | ||||
2493 | Py_BuildValue("(s,i)", | ||||
2494 | Pa_GetErrorText(err), err)); | ||||
2495 | return NULL((void*)0); | ||||
2496 | } | ||||
2497 | |||||
2498 | return rv; | ||||
2499 | } | ||||
2500 | |||||
2501 | static PyObject * | ||||
2502 | pa_get_stream_write_available(PyObject *self, PyObject *args) | ||||
2503 | { | ||||
2504 | signed long frames; | ||||
2505 | PyObject *stream_arg; | ||||
2506 | _pyAudio_Stream *streamObject; | ||||
2507 | PaStream *stream; | ||||
2508 | |||||
2509 | if (!PyArg_ParseTuple(args, "O!", &_pyAudio_StreamType, &stream_arg)) | ||||
2510 | return NULL((void*)0); | ||||
2511 | |||||
2512 | streamObject = (_pyAudio_Stream *) stream_arg; | ||||
2513 | |||||
2514 | if (!_is_open(streamObject)) { | ||||
2515 | PyErr_SetObject(PyExc_IOError, | ||||
2516 | Py_BuildValue("(s,i)", | ||||
2517 | "Stream closed", | ||||
2518 | paBadStreamPtr)); | ||||
2519 | return NULL((void*)0); | ||||
2520 | } | ||||
2521 | |||||
2522 | stream = streamObject->stream; | ||||
2523 | frames = Pa_GetStreamWriteAvailable(stream); | ||||
2524 | return PyLong_FromLong(frames); | ||||
2525 | } | ||||
2526 | |||||
2527 | static PyObject * | ||||
2528 | pa_get_stream_read_available(PyObject *self, PyObject *args) | ||||
2529 | { | ||||
2530 | signed long frames; | ||||
2531 | PyObject *stream_arg; | ||||
2532 | _pyAudio_Stream *streamObject; | ||||
2533 | PaStream *stream; | ||||
2534 | |||||
2535 | if (!PyArg_ParseTuple(args, "O!", &_pyAudio_StreamType, &stream_arg)) | ||||
2536 | return NULL((void*)0); | ||||
2537 | |||||
2538 | streamObject = (_pyAudio_Stream *) stream_arg; | ||||
2539 | |||||
2540 | if (!_is_open(streamObject)) { | ||||
2541 | PyErr_SetObject(PyExc_IOError, | ||||
2542 | Py_BuildValue("(s,i)", | ||||
2543 | "Stream closed", | ||||
2544 | paBadStreamPtr)); | ||||
2545 | return NULL((void*)0); | ||||
2546 | } | ||||
2547 | |||||
2548 | stream = streamObject->stream; | ||||
2549 | frames = Pa_GetStreamReadAvailable(stream); | ||||
2550 | return PyLong_FromLong(frames); | ||||
2551 | } | ||||
2552 | |||||
2553 | |||||
2554 | /************************************************************ | ||||
2555 | * | ||||
2556 | * IV. Python Module Init | ||||
2557 | * | ||||
2558 | ************************************************************/ | ||||
2559 | |||||
2560 | #if PY_MAJOR_VERSION3 >= 3 | ||||
2561 | #define ERROR_INIT((void*)0) NULL((void*)0) | ||||
2562 | #else | ||||
2563 | #define ERROR_INIT((void*)0) /**/ | ||||
2564 | #endif | ||||
2565 | |||||
2566 | #if PY_MAJOR_VERSION3 >= 3 | ||||
2567 | static struct PyModuleDef moduledef = { | ||||
2568 | PyModuleDef_HEAD_INIT{ { 1, ((void*)0) }, ((void*)0), 0, ((void*)0), }, | ||||
2569 | "_portaudio", | ||||
2570 | NULL((void*)0), | ||||
2571 | -1, | ||||
2572 | paMethods, | ||||
2573 | NULL((void*)0), | ||||
2574 | NULL((void*)0), | ||||
2575 | NULL((void*)0), | ||||
2576 | NULL((void*)0) | ||||
2577 | }; | ||||
2578 | #endif | ||||
2579 | |||||
2580 | PyMODINIT_FUNCPyObject* | ||||
2581 | #if PY_MAJOR_VERSION3 >= 3 | ||||
2582 | PyInit__portaudio(void) | ||||
2583 | #else | ||||
2584 | init_portaudio(void) | ||||
2585 | #endif | ||||
2586 | { | ||||
2587 | PyObject* m; | ||||
2588 | |||||
2589 | PyEval_InitThreads(); | ||||
2590 | |||||
2591 | _pyAudio_StreamType.tp_new = PyType_GenericNew; | ||||
2592 | if (PyType_Ready(&_pyAudio_StreamType) < 0) | ||||
2593 | return ERROR_INIT((void*)0); | ||||
2594 | |||||
2595 | _pyAudio_paDeviceInfoType.tp_new = PyType_GenericNew; | ||||
2596 | if (PyType_Ready(&_pyAudio_paDeviceInfoType) < 0) | ||||
2597 | return ERROR_INIT((void*)0); | ||||
2598 | |||||
2599 | _pyAudio_paHostApiInfoType.tp_new = PyType_GenericNew; | ||||
2600 | if (PyType_Ready(&_pyAudio_paHostApiInfoType) < 0) | ||||
2601 | return ERROR_INIT((void*)0); | ||||
2602 | |||||
2603 | #ifdef MACOSX | ||||
2604 | _pyAudio_MacOSX_hostApiSpecificStreamInfoType.tp_new = PyType_GenericNew; | ||||
2605 | if (PyType_Ready(&_pyAudio_MacOSX_hostApiSpecificStreamInfoType) < 0) | ||||
2606 | return ERROR_INIT((void*)0); | ||||
2607 | #endif | ||||
2608 | |||||
2609 | #if PY_MAJOR_VERSION3 >= 3 | ||||
2610 | m = PyModule_Create(&moduledef)PyModule_Create2(&moduledef, 1013); | ||||
2611 | #else | ||||
2612 | m = Py_InitModule("_portaudio", paMethods); | ||||
2613 | #endif | ||||
2614 | |||||
2615 | Py_INCREF(&_pyAudio_StreamType)_Py_INCREF(((PyObject*)(&_pyAudio_StreamType))); | ||||
2616 | Py_INCREF(&_pyAudio_paDeviceInfoType)_Py_INCREF(((PyObject*)(&_pyAudio_paDeviceInfoType))); | ||||
2617 | Py_INCREF(&_pyAudio_paHostApiInfoType)_Py_INCREF(((PyObject*)(&_pyAudio_paHostApiInfoType))); | ||||
2618 | |||||
2619 | #ifdef MACOSX | ||||
2620 | Py_INCREF(&_pyAudio_MacOSX_hostApiSpecificStreamInfoType)_Py_INCREF(((PyObject*)(&_pyAudio_MacOSX_hostApiSpecificStreamInfoType ))); | ||||
2621 | PyModule_AddObject(m, "paMacCoreStreamInfo", | ||||
2622 | (PyObject *) | ||||
2623 | &_pyAudio_MacOSX_hostApiSpecificStreamInfoType); | ||||
2624 | #endif | ||||
2625 | |||||
2626 | /* Add PortAudio constants */ | ||||
2627 | |||||
2628 | /* host apis */ | ||||
2629 | PyModule_AddIntConstant(m, "paInDevelopment", paInDevelopment); | ||||
2630 | PyModule_AddIntConstant(m, "paDirectSound", paDirectSound); | ||||
2631 | PyModule_AddIntConstant(m, "paMME", paMME); | ||||
2632 | PyModule_AddIntConstant(m, "paASIO", paASIO); | ||||
2633 | PyModule_AddIntConstant(m, "paSoundManager", paSoundManager); | ||||
2634 | PyModule_AddIntConstant(m, "paCoreAudio", paCoreAudio); | ||||
2635 | PyModule_AddIntConstant(m, "paOSS", paOSS); | ||||
2636 | PyModule_AddIntConstant(m, "paALSA", paALSA); | ||||
2637 | PyModule_AddIntConstant(m, "paAL", paAL); | ||||
2638 | PyModule_AddIntConstant(m, "paBeOS", paBeOS); | ||||
2639 | PyModule_AddIntConstant(m, "paWDMKS", paWDMKS); | ||||
2640 | PyModule_AddIntConstant(m, "paJACK", paJACK); | ||||
2641 | PyModule_AddIntConstant(m, "paWASAPI", paWASAPI); | ||||
2642 | PyModule_AddIntConstant(m, "paNoDevice", paNoDevice((PaDeviceIndex)-1)); | ||||
2643 | |||||
2644 | /* formats */ | ||||
2645 | PyModule_AddIntConstant(m, "paFloat32", paFloat32((PaSampleFormat) 0x00000001)); | ||||
2646 | PyModule_AddIntConstant(m, "paInt32", paInt32((PaSampleFormat) 0x00000002)); | ||||
2647 | PyModule_AddIntConstant(m, "paInt24", paInt24((PaSampleFormat) 0x00000004)); | ||||
2648 | PyModule_AddIntConstant(m, "paInt16", paInt16((PaSampleFormat) 0x00000008)); | ||||
2649 | PyModule_AddIntConstant(m, "paInt8", paInt8((PaSampleFormat) 0x00000010)); | ||||
2650 | PyModule_AddIntConstant(m, "paUInt8", paUInt8((PaSampleFormat) 0x00000020)); | ||||
2651 | PyModule_AddIntConstant(m, "paCustomFormat", paCustomFormat((PaSampleFormat) 0x00010000)); | ||||
2652 | |||||
2653 | /* error codes */ | ||||
2654 | PyModule_AddIntConstant(m, "paNoError", paNoError); | ||||
2655 | PyModule_AddIntConstant(m, "paNotInitialized", paNotInitialized); | ||||
2656 | PyModule_AddIntConstant(m, "paUnanticipatedHostError", | ||||
2657 | paUnanticipatedHostError); | ||||
2658 | PyModule_AddIntConstant(m, "paInvalidChannelCount", | ||||
2659 | paInvalidChannelCount); | ||||
2660 | PyModule_AddIntConstant(m, "paInvalidSampleRate", | ||||
2661 | paInvalidSampleRate); | ||||
2662 | PyModule_AddIntConstant(m, "paInvalidDevice", paInvalidDevice); | ||||
2663 | PyModule_AddIntConstant(m, "paInvalidFlag", paInvalidFlag); | ||||
2664 | PyModule_AddIntConstant(m, "paSampleFormatNotSupported", | ||||
2665 | paSampleFormatNotSupported); | ||||
2666 | PyModule_AddIntConstant(m, "paBadIODeviceCombination", | ||||
2667 | paBadIODeviceCombination); | ||||
2668 | PyModule_AddIntConstant(m, "paInsufficientMemory", | ||||
2669 | paInsufficientMemory); | ||||
2670 | PyModule_AddIntConstant(m, "paBufferTooBig", paBufferTooBig); | ||||
2671 | PyModule_AddIntConstant(m, "paBufferTooSmall", paBufferTooSmall); | ||||
2672 | PyModule_AddIntConstant(m, "paNullCallback", paNullCallback); | ||||
2673 | PyModule_AddIntConstant(m, "paBadStreamPtr", paBadStreamPtr); | ||||
2674 | PyModule_AddIntConstant(m, "paTimedOut", paTimedOut); | ||||
2675 | PyModule_AddIntConstant(m, "paInternalError", paInternalError); | ||||
2676 | PyModule_AddIntConstant(m, "paDeviceUnavailable", paDeviceUnavailable); | ||||
2677 | PyModule_AddIntConstant(m, "paIncompatibleHostApiSpecificStreamInfo", | ||||
2678 | paIncompatibleHostApiSpecificStreamInfo); | ||||
2679 | PyModule_AddIntConstant(m, "paStreamIsStopped", paStreamIsStopped); | ||||
2680 | PyModule_AddIntConstant(m, "paStreamIsNotStopped", paStreamIsNotStopped); | ||||
2681 | PyModule_AddIntConstant(m, "paInputOverflowed", paInputOverflowed); | ||||
2682 | PyModule_AddIntConstant(m, "paOutputUnderflowed", paOutputUnderflowed); | ||||
2683 | PyModule_AddIntConstant(m, "paHostApiNotFound", paHostApiNotFound); | ||||
2684 | PyModule_AddIntConstant(m, "paInvalidHostApi", paInvalidHostApi); | ||||
2685 | PyModule_AddIntConstant(m, "paCanNotReadFromACallbackStream", | ||||
2686 | paCanNotReadFromACallbackStream); | ||||
2687 | PyModule_AddIntConstant(m, "paCanNotWriteToACallbackStream", | ||||
2688 | paCanNotWriteToACallbackStream); | ||||
2689 | PyModule_AddIntConstant(m, "paCanNotReadFromAnOutputOnlyStream", | ||||
2690 | paCanNotReadFromAnOutputOnlyStream); | ||||
2691 | PyModule_AddIntConstant(m, "paCanNotWriteToAnInputOnlyStream", | ||||
2692 | paCanNotWriteToAnInputOnlyStream); | ||||
2693 | PyModule_AddIntConstant(m, "paIncompatibleStreamHostApi", | ||||
2694 | paIncompatibleStreamHostApi); | ||||
2695 | |||||
2696 | /* callback constants */ | ||||
2697 | PyModule_AddIntConstant(m, "paContinue", paContinue); | ||||
2698 | PyModule_AddIntConstant(m, "paComplete", paComplete); | ||||
2699 | PyModule_AddIntConstant(m, "paAbort", paAbort); | ||||
2700 | |||||
2701 | /* callback status flags */ | ||||
2702 | PyModule_AddIntConstant(m, "paInputUnderflow", paInputUnderflow((PaStreamCallbackFlags) 0x00000001)); | ||||
2703 | PyModule_AddIntConstant(m, "paInputOverflow", paInputOverflow((PaStreamCallbackFlags) 0x00000002)); | ||||
2704 | PyModule_AddIntConstant(m, "paOutputUnderflow", paOutputUnderflow((PaStreamCallbackFlags) 0x00000004)); | ||||
2705 | PyModule_AddIntConstant(m, "paOutputOverflow", paOutputOverflow((PaStreamCallbackFlags) 0x00000008)); | ||||
2706 | PyModule_AddIntConstant(m, "paPrimingOutput", paPrimingOutput((PaStreamCallbackFlags) 0x00000010)); | ||||
2707 | |||||
2708 | #ifdef MACOSX | ||||
2709 | PyModule_AddIntConstant(m, "paMacCoreChangeDeviceParameters", | ||||
2710 | paMacCoreChangeDeviceParameters); | ||||
2711 | PyModule_AddIntConstant(m, "paMacCoreFailIfConversionRequired", | ||||
2712 | paMacCoreFailIfConversionRequired); | ||||
2713 | PyModule_AddIntConstant(m, "paMacCoreConversionQualityMin", | ||||
2714 | paMacCoreConversionQualityMin); | ||||
2715 | PyModule_AddIntConstant(m, "paMacCoreConversionQualityMedium", | ||||
2716 | paMacCoreConversionQualityMedium); | ||||
2717 | PyModule_AddIntConstant(m, "paMacCoreConversionQualityLow", | ||||
2718 | paMacCoreConversionQualityLow); | ||||
2719 | PyModule_AddIntConstant(m, "paMacCoreConversionQualityHigh", | ||||
2720 | paMacCoreConversionQualityHigh); | ||||
2721 | PyModule_AddIntConstant(m, "paMacCoreConversionQualityMax", | ||||
2722 | paMacCoreConversionQualityMax); | ||||
2723 | PyModule_AddIntConstant(m, "paMacCorePlayNice", | ||||
2724 | paMacCorePlayNice); | ||||
2725 | PyModule_AddIntConstant(m, "paMacCorePro", | ||||
2726 | paMacCorePro); | ||||
2727 | PyModule_AddIntConstant(m, "paMacCoreMinimizeCPUButPlayNice", | ||||
2728 | paMacCoreMinimizeCPUButPlayNice); | ||||
2729 | PyModule_AddIntConstant(m, "paMacCoreMinimizeCPU", | ||||
2730 | paMacCoreMinimizeCPU); | ||||
2731 | #endif | ||||
2732 | |||||
2733 | #if PY_MAJOR_VERSION3 >= 3 | ||||
2734 | return m; | ||||
2735 | #endif | ||||
2736 | } |
1 | #ifndef Py_BuildValue |
2 | struct _object; |
3 | typedef struct _object PyObject; |
4 | PyObject* clang_analyzer_PyObject_New_Reference(); |
5 | PyObject* Py_BuildValue(const char *format, ...) { |
6 | return clang_analyzer_PyObject_New_Reference(); |
7 | } |
8 | #else |
9 | #warning "API Py_BuildValue is defined as a macro." |
10 | #endif |