1#
2#   ctcsound.py:
3#
4#   Copyright (C) 2016 Francois Pinot
5#
6#   This file is part of Csound.
7#
8#   This code is free software; you can redistribute it
9#   and/or modify it under the terms of the GNU Lesser General Public
10#   License as published by the Free Software Foundation; either
11#   version 2.1 of the License, or (at your option) any later version.
12#
13#   Csound is distributed in the hope that it will be useful,
14#   but WITHOUT ANY WARRANTY; without even the implied warranty of
15#   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16#   GNU Lesser General Public License for more details.
17#
18#   You should have received a copy of the GNU Lesser General Public
19#   License along with Csound; if not, write to the Free Software
20#   Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
21#   02110-1301 USA
22#
23
24import ctypes as ct
25import numpy as np
26import sys
27
28# This is a workaround to yield the PEP 3118 problem which appeared with
29# numpy 1.15.0
30if np.__version__ < '1.15':
31	arrFromPointer = lambda p : np.ctypeslib.as_array(p)
32elif np.__version__ < '1.16':
33	sys.exit("ctcsound won't work with numpy 1.15.x. Please revert numpy" +
34		" to an older version or update numpy to a version >= 1.16")
35else:
36	arrFromPointer = lambda p : p.contents
37
38if sys.platform.startswith('linux'):
39    libcsound = ct.CDLL("libcsound64.so")
40elif sys.platform.startswith('win'):
41    if sys.version_info.major <=3 and sys.version_info.minor < 8:
42        libcsound = ct.cdll.csound64
43    else:
44        import ctypes.util
45        libcsound = ct.CDLL(ctypes.util.find_library("csound64"))
46elif sys.platform.startswith('darwin'):
47    libcsound = ct.CDLL("CsoundLib64.framework/CsoundLib64")
48else:
49    sys.exit("Don't know your system! Exiting...")
50
51MYFLT = ct.c_double
52
53class CsoundParams(ct.Structure):
54    _fields_ = [("debug_mode", ct.c_int),        # debug mode, 0 or 1
55                ("buffer_frames", ct.c_int),     # number of frames in in/out buffers
56                ("hardware_buffer_frames", ct.c_int), # ibid. hardware
57                ("displays", ct.c_int),          # graph displays, 0 or 1
58                ("ascii_graphs", ct.c_int),      # use ASCII graphs, 0 or 1
59                ("postscript_graphs", ct.c_int), # use postscript graphs, 0 or 1
60                ("message_level", ct.c_int),     # message printout control
61                ("tempo", ct.c_int),             # tempo ("sets Beatmode)
62                ("ring_bell", ct.c_int),         # bell, 0 or 1
63                ("use_cscore", ct.c_int),        # use cscore for processing
64                ("terminate_on_midi", ct.c_int), # terminate performance at the end
65                                              #   of midifile, 0 or 1
66                ("heartbeat", ct.c_int),         # print heart beat, 0 or 1
67                ("defer_gen01_load", ct.c_int),  # defer GEN01 load, 0 or 1
68                ("midi_key", ct.c_int),          # pfield to map midi key no
69                ("midi_key_cps", ct.c_int),      # pfield to map midi key no as cps
70                ("midi_key_oct", ct.c_int),      # pfield to map midi key no as oct
71                ("midi_key_pch", ct.c_int),      # pfield to map midi key no as pch
72                ("midi_velocity", ct.c_int),     # pfield to map midi velocity
73                ("midi_velocity_amp", ct.c_int), # pfield to map midi velocity as amplitude
74                ("no_default_paths", ct.c_int),  # disable relative paths from files, 0 or 1
75                ("number_of_threads", ct.c_int), # number of threads for multicore performance
76                ("syntax_check_only", ct.c_int), # do not compile, only check syntax
77                ("csd_line_counts", ct.c_int),   # csd line error reporting
78                ("compute_weights", ct.c_int),   # deprecated, kept for backwards comp.
79                ("realtime_mode", ct.c_int),     # use realtime priority mode, 0 or 1
80                ("sample_accurate", ct.c_int),   # use sample-level score event accuracy
81                ("sample_rate_override", MYFLT),  # overriding sample rate
82                ("control_rate_override", MYFLT), # overriding control rate
83                ("nchnls_override", ct.c_int),   # overriding number of out channels
84                ("nchnls_i_override", ct.c_int), # overriding number of in channels
85                ("e0dbfs_override", MYFLT),   # overriding 0dbfs
86                ("daemon", ct.c_int),            # daemon mode
87                ("ksmps_override", ct.c_int),    # ksmps override
88                ("FFT_library", ct.c_int)]       # fft_lib
89
90string64 = ct.c_char * 64
91
92class CsoundAudioDevice(ct.Structure):
93    _fields_ = [("device_name", string64),
94                ("device_id", string64),
95                ("rt_module", string64),
96                ("max_nchnls", ct.c_int),
97                ("isOutput", ct.c_int)]
98
99class CsoundMidiDevice(ct.Structure):
100    _fields_ = [("device_name", string64),
101                ("interface_name", string64),
102                ("device_id", string64),
103                ("midi_module", string64),
104                ("isOutput", ct.c_int)]
105
106class CsoundRtAudioParams(ct.Structure):
107    _fields_ = [("devName", ct.c_char_p),   # device name (NULL/empty: default)
108                ("devNum", ct.c_int),       # device number (0-1023), 1024: default
109                ("bufSamp_SW", ct.c_uint),  # buffer fragment size (-b) in sample frames
110                ("bufSamp_HW", ct.c_int),   # total buffer size (-B) in sample frames
111                ("nChannels", ct.c_int),    # number of channels
112                ("sampleFormat", ct.c_int), # sample format (AE_SHORT etc.)
113                ("sampleRate", ct.c_float)] # sample rate in Hz
114
115class RtClock(ct.Structure):
116    _fields_ = [("starttime_real", ct.c_int64),
117                ("starttime_CPU", ct.c_int64)]
118
119class OpcodeListEntry(ct.Structure):
120    _fields_ = [("opname", ct.c_char_p),
121                ("outypes", ct.c_char_p),
122                ("intypes", ct.c_char_p),
123                ("flags", ct.c_int)]
124
125class CsoundRandMTState(ct.Structure):
126    _fields_ = [("mti", ct.c_int),
127                ("mt", ct.c_uint32*624)]
128
129# PVSDATEXT is a variation on PVSDAT used in the pvs bus interface
130class PvsdatExt(ct.Structure):
131    _fields_ = [("N", ct.c_int32),
132                ("sliding", ct.c_int),      # Flag to indicate sliding case
133                ("NB", ct.c_int32),
134                ("overlap", ct.c_int32),
135                ("winsize", ct.c_int32),
136                ("wintype", ct.c_int),
137                ("format", ct.c_int32),
138                ("framecount", ct.c_uint32),
139                ("frame", ct.POINTER(ct.c_float))]
140
141# This structure holds the parameter hints for control channels
142class ControlChannelHints(ct.Structure):
143    _fields_ = [("behav", ct.c_int),
144                ("dflt", MYFLT),
145                ("min", MYFLT),
146                ("max", MYFLT),
147                ("x", ct.c_int),
148                ("y", ct.c_int),
149                ("width", ct.c_int),
150                ("height", ct.c_int),
151                # This member must be set explicitly to None if not used
152                ("attributes", ct.c_char_p)]
153
154class ControlChannelInfo(ct.Structure):
155    _fields_ = [("name", ct.c_char_p),
156                ("type", ct.c_int),
157                ("hints", ControlChannelHints)]
158
159CAPSIZE  = 60
160
161class Windat(ct.Structure):
162    _fields_ = [("windid", ct.POINTER(ct.c_uint)),    # set by makeGraph()
163                ("fdata", ct.POINTER(MYFLT)),      # data passed to drawGraph()
164                ("npts", ct.c_int32),              # size of above array
165                ("caption", ct.c_char * CAPSIZE),  # caption string for graph
166                ("waitflg", ct.c_int16 ),          # set =1 to wait for ms after Draw
167                ("polarity", ct.c_int16),          # controls positioning of X axis
168                ("max", MYFLT),                 # workspace .. extrema this frame
169                ("min", MYFLT),
170                ("absmax", MYFLT),              # workspace .. largest of above
171                ("oabsmax", MYFLT),             # Y axis scaling factor
172                ("danflag", ct.c_int),             # set to 1 for extra Yaxis mid span
173                ("absflag", ct.c_int)]             # set to 1 to skip abs check
174
175# Symbols for Windat.polarity field
176NOPOL = 0
177NEGPOL = 1
178POSPOL = 2
179BIPOL = 3
180
181class NamedGen(ct.Structure):
182    pass
183
184NamedGen._fields_ = [
185    ("name", ct.c_char_p),
186    ("genum", ct.c_int),
187    ("next", ct.POINTER(NamedGen))]
188
189
190libcsound.csoundSetOpcodedir.argtypes = [ct.c_char_p]
191libcsound.csoundCreate.restype = ct.c_void_p
192libcsound.csoundCreate.argtypes = [ct.py_object]
193libcsound.csoundLoadPlugins.argtypes = [ct.c_void_p, ct.c_char_p]
194libcsound.csoundDestroy.argtypes = [ct.c_void_p]
195
196libcsound.csoundParseOrc.restype = ct.c_void_p
197libcsound.csoundParseOrc.argtypes = [ct.c_void_p, ct.c_char_p]
198
199libcsound.csoundCompileTree.argtypes = [ct.c_void_p, ct.c_void_p]
200libcsound.csoundCompileTreeAsync.argtypes = [ct.c_void_p, ct.c_void_p]
201libcsound.csoundDeleteTree.argtypes = [ct.c_void_p, ct.c_void_p]
202libcsound.csoundCompileOrc.argtypes = [ct.c_void_p, ct.c_char_p]
203libcsound.csoundCompileOrcAsync.argtypes = [ct.c_void_p, ct.c_char_p]
204
205libcsound.csoundEvalCode.restype = MYFLT
206libcsound.csoundEvalCode.argtypes = [ct.c_void_p, ct.c_char_p]
207
208libcsound.csoundCompileArgs.argtypes = [ct.c_void_p, ct.c_int, ct.POINTER(ct.c_char_p)]
209libcsound.csoundStart.argtypes = [ct.c_void_p]
210libcsound.csoundCompile.argtypes = [ct.c_void_p, ct.c_int, ct.POINTER(ct.c_char_p)]
211libcsound.csoundCompileCsd.argtypes = [ct.c_void_p, ct.c_char_p]
212libcsound.csoundCompileCsdText.argtypes = [ct.c_void_p, ct.c_char_p]
213
214libcsound.csoundPerform.argtypes = [ct.c_void_p]
215libcsound.csoundPerformKsmps.argtypes = [ct.c_void_p]
216libcsound.csoundPerformBuffer.argtypes = [ct.c_void_p]
217libcsound.csoundStop.argtypes = [ct.c_void_p]
218libcsound.csoundCleanup.argtypes = [ct.c_void_p]
219libcsound.csoundReset.argtypes = [ct.c_void_p]
220
221libcsound.csoundUDPServerStart.argtypes = [ct.c_void_p, ct.c_uint]
222libcsound.csoundUDPServerStatus.argtypes = [ct.c_void_p]
223libcsound.csoundUDPServerClose.argtypes = [ct.c_void_p]
224libcsound.csoundUDPConsole.argtypes = [ct.c_void_p, ct.c_char_p, ct.c_uint, ct.c_uint]
225libcsound.csoundStopUDPConsole.argtypes = [ct.c_void_p]
226
227libcsound.csoundGetSr.restype = MYFLT
228libcsound.csoundGetSr.argtypes = [ct.c_void_p]
229libcsound.csoundGetKr.restype = MYFLT
230libcsound.csoundGetKr.argtypes = [ct.c_void_p]
231libcsound.csoundGetKsmps.restype = ct.c_uint32
232libcsound.csoundGetKsmps.argtypes = [ct.c_void_p]
233libcsound.csoundGetNchnls.restype = ct.c_uint32
234libcsound.csoundGetNchnls.argtypes = [ct.c_void_p]
235libcsound.csoundGetNchnlsInput.restype = ct.c_uint32
236libcsound.csoundGetNchnlsInput.argtypes = [ct.c_void_p]
237libcsound.csoundGet0dBFS.restype = MYFLT
238libcsound.csoundGet0dBFS.argtypes = [ct.c_void_p]
239libcsound.csoundGetA4.restype = MYFLT
240libcsound.csoundGetA4.argtypes = [ct.c_void_p]
241libcsound.csoundGetCurrentTimeSamples.restype = ct.c_int64
242libcsound.csoundGetCurrentTimeSamples.argtypes = [ct.c_void_p]
243libcsound.csoundGetHostData.restype = ct.py_object
244libcsound.csoundGetHostData.argtypes = [ct.c_void_p]
245libcsound.csoundSetHostData.argtypes = [ct.c_void_p, ct.py_object]
246libcsound.csoundSetOption.argtypes = [ct.c_void_p, ct.c_char_p]
247libcsound.csoundSetParams.argtypes = [ct.c_void_p, ct.POINTER(CsoundParams)]
248libcsound.csoundGetParams.argtypes = [ct.c_void_p, ct.POINTER(CsoundParams)]
249libcsound.csoundGetDebug.argtypes = [ct.c_void_p]
250libcsound.csoundSetDebug.argtypes = [ct.c_void_p, ct.c_int]
251libcsound.csoundSystemSr.restype = MYFLT
252libcsound.csoundSystemSr.argtypes = [ct.c_void_p, MYFLT]
253
254libcsound.csoundGetOutputName.restype = ct.c_char_p
255libcsound.csoundGetOutputName.argtypes = [ct.c_void_p]
256libcsound.csoundGetInputName.restype = ct.c_char_p
257libcsound.csoundGetInputName.argtypes = [ct.c_void_p]
258libcsound.csoundSetOutput.argtypes = [ct.c_void_p, ct.c_char_p, ct.c_char_p, ct.c_char_p]
259libcsound.csoundGetOutputFormat.argtypes = [ct.c_void_p, ct.c_char_p, ct.c_char_p]
260libcsound.csoundSetInput.argtypes = [ct.c_void_p, ct.c_char_p]
261libcsound.csoundSetMIDIInput.argtypes = [ct.c_void_p, ct.c_char_p]
262libcsound.csoundSetMIDIFileInput.argtypes = [ct.c_void_p, ct.c_char_p]
263libcsound.csoundSetMIDIOutput.argtypes = [ct.c_void_p, ct.c_char_p]
264libcsound.csoundSetMIDIFileOutput.argtypes = [ct.c_void_p, ct.c_char_p]
265FILEOPENFUNC = ct.CFUNCTYPE(None, ct.c_void_p, ct.c_char_p, ct.c_int, ct.c_int, ct.c_int)
266libcsound.csoundSetFileOpenCallback.argtypes = [ct.c_void_p, FILEOPENFUNC]
267
268libcsound.csoundSetRTAudioModule.argtypes = [ct.c_void_p, ct.c_char_p]
269libcsound.csoundGetModule.argtypes = [ct.c_void_p, ct.c_int, ct.POINTER(ct.c_char_p), ct.POINTER(ct.c_char_p)]
270libcsound.csoundGetInputBufferSize.restype = ct.c_long
271libcsound.csoundGetInputBufferSize.argtypes = [ct.c_void_p]
272libcsound.csoundGetOutputBufferSize.restype = ct.c_long
273libcsound.csoundGetOutputBufferSize.argtypes = [ct.c_void_p]
274libcsound.csoundGetInputBuffer.restype = ct.POINTER(MYFLT)
275libcsound.csoundGetInputBuffer.argtypes = [ct.c_void_p]
276libcsound.csoundGetOutputBuffer.restype = ct.POINTER(MYFLT)
277libcsound.csoundGetOutputBuffer.argtypes = [ct.c_void_p]
278libcsound.csoundGetSpin.restype = ct.POINTER(MYFLT)
279libcsound.csoundGetSpin.argtypes = [ct.c_void_p]
280libcsound.csoundClearSpin.argtypes = [ct.c_void_p]
281libcsound.csoundAddSpinSample.argtypes = [ct.c_void_p, ct.c_int, ct.c_int, MYFLT]
282libcsound.csoundSetSpinSample.argtypes = [ct.c_void_p, ct.c_int, ct.c_int, MYFLT]
283libcsound.csoundGetSpout.restype = ct.POINTER(MYFLT)
284libcsound.csoundGetSpout.argtypes = [ct.c_void_p]
285libcsound.csoundGetSpoutSample.restype = MYFLT
286libcsound.csoundGetSpoutSample.argtypes = [ct.c_void_p, ct.c_int, ct.c_int]
287libcsound.csoundGetRtRecordUserData.restype = ct.POINTER(ct.c_void_p)
288libcsound.csoundGetRtRecordUserData.argtypes = [ct.c_void_p]
289libcsound.csoundGetRtPlayUserData.restype = ct.POINTER(ct.c_void_p)
290libcsound.csoundGetRtPlayUserData.argtypes = [ct.c_void_p]
291libcsound.csoundSetHostImplementedAudioIO.argtypes = [ct.c_void_p, ct.c_int, ct.c_int]
292libcsound.csoundGetAudioDevList.argtypes = [ct.c_void_p, ct.c_void_p, ct.c_int]
293PLAYOPENFUNC = ct.CFUNCTYPE(ct.c_int, ct.c_void_p, ct.POINTER(CsoundRtAudioParams))
294libcsound.csoundSetPlayopenCallback.argtypes = [ct.c_void_p, PLAYOPENFUNC]
295RTPLAYFUNC = ct.CFUNCTYPE(None, ct.c_void_p, ct.POINTER(MYFLT), ct.c_int)
296libcsound.csoundSetRtplayCallback.argtypes = [ct.c_void_p, RTPLAYFUNC]
297RECORDOPENFUNC = ct.CFUNCTYPE(ct.c_int, ct.c_void_p, ct.POINTER(CsoundRtAudioParams))
298libcsound.csoundSetRecopenCallback.argtypes = [ct.c_void_p, RECORDOPENFUNC]
299RTRECORDFUNC = ct.CFUNCTYPE(ct.c_int, ct.c_void_p, ct.POINTER(MYFLT), ct.c_int)
300libcsound.csoundSetRtrecordCallback.argtypes = [ct.c_void_p, RTRECORDFUNC]
301RTCLOSEFUNC = ct.CFUNCTYPE(None, ct.c_void_p)
302libcsound.csoundSetRtcloseCallback.argtypes = [ct.c_void_p, RTCLOSEFUNC]
303AUDIODEVLISTFUNC = ct.CFUNCTYPE(ct.c_int, ct.c_void_p, ct.POINTER(CsoundAudioDevice), ct.c_int)
304libcsound.csoundSetAudioDeviceListCallback.argtypes = [ct.c_void_p, AUDIODEVLISTFUNC]
305
306libcsound.csoundSetMIDIModule.argtypes = [ct.c_void_p, ct.c_char_p]
307libcsound.csoundSetHostImplementedMIDIIO.argtypes = [ct.c_void_p, ct.c_int]
308libcsound.csoundGetMIDIDevList.argtypes = [ct.c_void_p, ct.c_void_p, ct.c_int]
309MIDIINOPENFUNC = ct.CFUNCTYPE(ct.c_int, ct.c_void_p, ct.POINTER(ct.c_void_p), ct.c_char_p)
310libcsound.csoundSetExternalMidiInOpenCallback.argtypes = [ct.c_void_p, MIDIINOPENFUNC]
311MIDIREADFUNC = ct.CFUNCTYPE(ct.c_int, ct.c_void_p, ct.c_void_p, ct.c_char_p, ct.c_int)
312libcsound.csoundSetExternalMidiReadCallback.argtypes = [ct.c_void_p, MIDIREADFUNC]
313MIDIINCLOSEFUNC = ct.CFUNCTYPE(ct.c_int, ct.c_void_p, ct.c_void_p)
314libcsound.csoundSetExternalMidiInCloseCallback.argtypes = [ct.c_void_p, MIDIINCLOSEFUNC]
315MIDIOUTOPENFUNC = ct.CFUNCTYPE(ct.c_int, ct.c_void_p, ct.POINTER(ct.c_void_p), ct.c_char_p)
316libcsound.csoundSetExternalMidiOutOpenCallback.argtypes = [ct.c_void_p, MIDIOUTOPENFUNC]
317MIDIWRITEFUNC = ct.CFUNCTYPE(ct.c_int, ct.c_void_p, ct.c_void_p, ct.c_char_p, ct.c_int)
318libcsound.csoundSetExternalMidiWriteCallback.argtypes = [ct.c_void_p, MIDIWRITEFUNC]
319MIDIOUTCLOSEFUNC = ct.CFUNCTYPE(ct.c_int, ct.c_void_p, ct.c_void_p)
320libcsound.csoundSetExternalMidiOutCloseCallback.argtypes = [ct.c_void_p, MIDIOUTCLOSEFUNC]
321MIDIERRORFUNC = ct.CFUNCTYPE(ct.c_char_p, ct.c_int)
322libcsound.csoundSetExternalMidiErrorStringCallback.argtypes = [ct.c_void_p, MIDIERRORFUNC]
323MIDIDEVLISTFUNC = ct.CFUNCTYPE(ct.c_int, ct.c_void_p, ct.POINTER(CsoundMidiDevice), ct.c_int)
324libcsound.csoundSetMIDIDeviceListCallback.argtypes = [ct.c_void_p, MIDIDEVLISTFUNC]
325
326libcsound.csoundReadScore.argtypes = [ct.c_void_p, ct.c_char_p]
327libcsound.csoundReadScoreAsync.argtypes = [ct.c_void_p, ct.c_char_p]
328libcsound.csoundGetScoreTime.restype = ct.c_double
329libcsound.csoundGetScoreTime.argtypes = [ct.c_void_p]
330libcsound.csoundIsScorePending.argtypes = [ct.c_void_p]
331libcsound.csoundSetScorePending.argtypes = [ct.c_void_p, ct.c_int]
332libcsound.csoundGetScoreOffsetSeconds.restype = MYFLT
333libcsound.csoundGetScoreOffsetSeconds.argtypes = [ct.c_void_p]
334libcsound.csoundSetScoreOffsetSeconds.argtypes = [ct.c_void_p, MYFLT]
335libcsound.csoundRewindScore.argtypes = [ct.c_void_p]
336CSCOREFUNC = ct.CFUNCTYPE(None, ct.c_void_p)
337libcsound.csoundSetCscoreCallback.argtypes = [ct.c_void_p, CSCOREFUNC]
338
339libcsound.csoundMessage.argtypes = [ct.c_void_p, ct.c_char_p, ct.c_char_p]
340libcsound.csoundMessageS.argtypes = [ct.c_void_p, ct.c_int, ct.c_char_p, ct.c_char_p]
341libcsound.csoundGetMessageLevel.argtypes = [ct.c_void_p]
342libcsound.csoundSetMessageLevel.argtypes = [ct.c_void_p, ct.c_int]
343libcsound.csoundCreateMessageBuffer.argtypes = [ct.c_void_p, ct.c_int]
344libcsound.csoundGetFirstMessage.restype = ct.c_char_p
345libcsound.csoundGetFirstMessage.argtypes = [ct.c_void_p]
346libcsound.csoundGetFirstMessageAttr.argtypes = [ct.c_void_p]
347libcsound.csoundPopFirstMessage.argtypes = [ct.c_void_p]
348libcsound.csoundGetMessageCnt.argtypes = [ct.c_void_p]
349libcsound.csoundDestroyMessageBuffer.argtypes = [ct.c_void_p]
350
351libcsound.csoundGetChannelPtr.argtypes = [ct.c_void_p, ct.POINTER(ct.POINTER(MYFLT)), ct.c_char_p, ct.c_int]
352libcsound.csoundListChannels.argtypes = [ct.c_void_p, ct.POINTER(ct.POINTER(ControlChannelInfo))]
353libcsound.csoundDeleteChannelList.argtypes = [ct.c_void_p, ct.POINTER(ControlChannelInfo)]
354libcsound.csoundSetControlChannelHints.argtypes = [ct.c_void_p, ct.c_char_p, ControlChannelHints]
355libcsound.csoundGetControlChannelHints.argtypes = [ct.c_void_p, ct.c_char_p, ct.POINTER(ControlChannelHints)]
356libcsound.csoundGetChannelLock.restype = ct.POINTER(ct.c_int)
357libcsound.csoundGetChannelLock.argtypes = [ct.c_void_p, ct.c_char_p]
358libcsound.csoundGetControlChannel.restype = MYFLT
359libcsound.csoundGetControlChannel.argtypes = [ct.c_void_p, ct.c_char_p, ct.POINTER(ct.c_int)]
360libcsound.csoundSetControlChannel.argtypes = [ct.c_void_p, ct.c_char_p, MYFLT]
361libcsound.csoundGetAudioChannel.argtypes = [ct.c_void_p, ct.c_char_p, ct.POINTER(ct.c_int)]
362libcsound.csoundSetAudioChannel.argtypes = [ct.c_void_p, ct.c_char_p, ct.POINTER(ct.c_int)]
363libcsound.csoundGetStringChannel.argtypes = [ct.c_void_p, ct.c_char_p, ct.c_char_p]
364libcsound.csoundSetStringChannel.argtypes = [ct.c_void_p, ct.c_char_p, ct.c_char_p]
365libcsound.csoundGetChannelDatasize.argtypes = [ct.c_void_p, ct.c_char_p]
366CHANNELFUNC = ct.CFUNCTYPE(None, ct.c_void_p, ct.c_char_p, ct.c_void_p, ct.c_void_p)
367libcsound.csoundSetInputChannelCallback.argtypes = [ct.c_void_p, CHANNELFUNC]
368libcsound.csoundSetOutputChannelCallback.argtypes = [ct.c_void_p, CHANNELFUNC]
369libcsound.csoundSetPvsChannel.argtypes = [ct.c_void_p, ct.POINTER(PvsdatExt), ct.c_char_p]
370libcsound.csoundGetPvsChannel.argtypes = [ct.c_void_p, ct.POINTER(PvsdatExt), ct.c_char_p]
371libcsound.csoundScoreEvent.argtypes = [ct.c_void_p, ct.c_char, ct.POINTER(MYFLT), ct.c_long]
372libcsound.csoundScoreEventAsync.argtypes = [ct.c_void_p, ct.c_char, ct.POINTER(MYFLT), ct.c_long]
373libcsound.csoundScoreEventAbsolute.argtypes = [ct.c_void_p, ct.c_char, ct.POINTER(MYFLT), ct.c_long, ct.c_double]
374libcsound.csoundScoreEventAbsoluteAsync.argtypes = [ct.c_void_p, ct.c_char, ct.POINTER(MYFLT), ct.c_long, ct.c_double]
375libcsound.csoundInputMessage.argtypes = [ct.c_void_p, ct.c_char_p]
376libcsound.csoundInputMessageAsync.argtypes = [ct.c_void_p, ct.c_char_p]
377libcsound.csoundKillInstance.argtypes = [ct.c_void_p, MYFLT, ct.c_char_p, ct.c_int, ct.c_int]
378SENSEFUNC = ct.CFUNCTYPE(None, ct.c_void_p, ct.py_object)
379libcsound.csoundRegisterSenseEventCallback.argtypes = [ct.c_void_p, SENSEFUNC, ct.py_object]
380libcsound.csoundKeyPress.argtypes = [ct.c_void_p, ct.c_char]
381KEYBOARDFUNC = ct.CFUNCTYPE(ct.c_int, ct.py_object, ct.c_void_p, ct.c_uint)
382libcsound.csoundRegisterKeyboardCallback.argtypes = [ct.c_void_p, KEYBOARDFUNC, ct.py_object, ct.c_uint]
383libcsound.csoundRemoveKeyboardCallback.argtypes = [ct.c_void_p, KEYBOARDFUNC]
384
385libcsound.csoundTableLength.argtypes = [ct.c_void_p, ct.c_int]
386libcsound.csoundTableGet.restype = MYFLT
387libcsound.csoundTableGet.argtypes = [ct.c_void_p, ct.c_int, ct.c_int]
388libcsound.csoundTableSet.argtypes = [ct.c_void_p, ct.c_int, ct.c_int, MYFLT]
389libcsound.csoundTableCopyOut.argtypes = [ct.c_void_p, ct.c_int, ct.POINTER(MYFLT)]
390libcsound.csoundTableCopyOutAsync.argtypes = [ct.c_void_p, ct.c_int, ct.POINTER(MYFLT)]
391libcsound.csoundTableCopyIn.argtypes = [ct.c_void_p, ct.c_int, ct.POINTER(MYFLT)]
392libcsound.csoundTableCopyInAsync.argtypes = [ct.c_void_p, ct.c_int, ct.POINTER(MYFLT)]
393libcsound.csoundGetTable.argtypes = [ct.c_void_p, ct.POINTER(ct.POINTER(MYFLT)), ct.c_int]
394libcsound.csoundGetTableArgs.argtypes = [ct.c_void_p, ct.POINTER(ct.POINTER(MYFLT)), ct.c_int]
395libcsound.csoundIsNamedGEN.argtypes = [ct.c_void_p, ct.c_int]
396libcsound.csoundGetNamedGEN.argtypes = [ct.c_void_p, ct.c_int, ct.c_char_p, ct.c_int]
397
398libcsound.csoundSetIsGraphable.argtypes = [ct.c_void_p, ct.c_int]
399MAKEGRAPHFUNC = ct.CFUNCTYPE(None, ct.c_void_p, ct.POINTER(Windat), ct.c_char_p)
400libcsound.csoundSetMakeGraphCallback.argtypes = [ct.c_void_p, MAKEGRAPHFUNC]
401DRAWGRAPHFUNC = ct.CFUNCTYPE(None, ct.c_void_p, ct.POINTER(Windat))
402libcsound.csoundSetDrawGraphCallback.argtypes = [ct.c_void_p, DRAWGRAPHFUNC]
403KILLGRAPHFUNC = ct.CFUNCTYPE(None, ct.c_void_p, ct.POINTER(Windat))
404libcsound.csoundSetKillGraphCallback.argtypes = [ct.c_void_p, KILLGRAPHFUNC]
405EXITGRAPHFUNC = ct.CFUNCTYPE(ct.c_int, ct.c_void_p)
406libcsound.csoundSetExitGraphCallback.argtypes = [ct.c_void_p, EXITGRAPHFUNC]
407
408libcsound.csoundGetNamedGens.restype = ct.c_void_p
409libcsound.csoundGetNamedGens.argtypes = [ct.c_void_p]
410libcsound.csoundNewOpcodeList.argtypes = [ct.c_void_p, ct.POINTER(ct.POINTER(OpcodeListEntry))]
411libcsound.csoundDisposeOpcodeList.argtypes = [ct.c_void_p, ct.POINTER(OpcodeListEntry)]
412OPCODEFUNC = ct.CFUNCTYPE(ct.c_int, ct.c_void_p, ct.c_void_p)
413libcsound.csoundAppendOpcode.argtypes = [ct.c_void_p, ct.c_char_p, ct.c_int, ct.c_int, ct.c_int, \
414                                         ct.c_char_p, ct.c_char_p, OPCODEFUNC, OPCODEFUNC, OPCODEFUNC]
415
416YIELDFUNC = ct.CFUNCTYPE(ct.c_int, ct.c_void_p)
417libcsound.csoundSetYieldCallback.argtypes = [ct.c_void_p, YIELDFUNC]
418THREADFUNC = ct.CFUNCTYPE(ct.POINTER(ct.c_uint), ct.py_object)
419libcsound.csoundCreateThread.restype = ct.c_void_p
420libcsound.csoundCreateThread.argtypes = [THREADFUNC, ct.py_object]
421libcsound.csoundGetCurrentThreadId.restype = ct.c_void_p
422libcsound.csoundJoinThread.restype = ct.POINTER(ct.c_uint)
423libcsound.csoundJoinThread.argtypes = [ct.c_void_p]
424libcsound.csoundCreateThreadLock.restype = ct.c_void_p
425libcsound.csoundWaitThreadLock.argtypes = [ct.c_void_p, ct.c_uint]
426libcsound.csoundWaitThreadLockNoTimeout.argtypes = [ct.c_void_p]
427libcsound.csoundNotifyThreadLock.argtypes = [ct.c_void_p]
428libcsound.csoundDestroyThreadLock.argtypes = [ct.c_void_p]
429libcsound.csoundCreateMutex.restype = ct.c_void_p
430libcsound.csoundCreateMutex.argtypes = [ct.c_int]
431libcsound.csoundLockMutex.argtypes = [ct.c_void_p]
432libcsound.csoundLockMutexNoWait.argtypes = [ct.c_void_p]
433libcsound.csoundUnlockMutex.argtypes = [ct.c_void_p]
434libcsound.csoundDestroyMutex.argtypes = [ct.c_void_p]
435libcsound.csoundCreateBarrier.restype = ct.c_void_p
436libcsound.csoundCreateBarrier.argtypes = [ct.c_uint]
437libcsound.csoundDestroyBarrier.argtypes = [ct.c_void_p]
438libcsound.csoundWaitBarrier.argtypes = [ct.c_void_p]
439libcsound.csoundSleep.argtypes = [ct.c_uint]
440libcsound.csoundSpinLockInit.argtypes = [ct.POINTER(ct.c_int32)]
441libcsound.csoundSpinLock.argtypes = [ct.POINTER(ct.c_int32)]
442libcsound.csoundSpinTryLock.argtypes = [ct.POINTER(ct.c_int32)]
443libcsound.csoundSpinUnLock.argtypes = [ct.POINTER(ct.c_int32)]
444
445libcsound.csoundRunCommand.restype = ct.c_long
446libcsound.csoundRunCommand.argtypes = [ct.POINTER(ct.c_char_p), ct.c_int]
447libcsound.csoundInitTimerStruct.argtypes = [ct.POINTER(RtClock)]
448libcsound.csoundGetRealTime.restype = ct.c_double
449libcsound.csoundGetRealTime.argtypes = [ct.POINTER(RtClock)]
450libcsound.csoundGetCPUTime.restype = ct.c_double
451libcsound.csoundGetCPUTime.argtypes = [ct.POINTER(RtClock)]
452libcsound.csoundGetRandomSeedFromTime.restype = ct.c_uint32
453libcsound.csoundGetEnv.restype = ct.c_char_p
454libcsound.csoundGetEnv.argtypes = [ct.c_void_p, ct.c_char_p]
455libcsound.csoundSetGlobalEnv.argtypes = [ct.c_char_p, ct.c_char_p]
456libcsound.csoundCreateGlobalVariable.argtypes = [ct.c_void_p, ct.c_char_p, ct.c_uint]
457libcsound.csoundQueryGlobalVariable.restype = ct.c_void_p
458libcsound.csoundQueryGlobalVariable.argtypes = [ct.c_void_p, ct.c_char_p]
459libcsound.csoundQueryGlobalVariableNoCheck.restype = ct.c_void_p
460libcsound.csoundQueryGlobalVariableNoCheck.argtypes = [ct.c_void_p, ct.c_char_p]
461libcsound.csoundDestroyGlobalVariable.argtypes = [ct.c_void_p, ct.c_char_p]
462libcsound.csoundRunUtility.argtypes = [ct.c_void_p, ct.c_char_p, ct.c_int, ct.POINTER(ct.c_char_p)]
463libcsound.csoundListUtilities.restype = ct.POINTER(ct.c_char_p)
464libcsound.csoundListUtilities.argtypes = [ct.c_void_p]
465libcsound.csoundDeleteUtilityList.argtypes = [ct.c_void_p, ct.POINTER(ct.c_char_p)]
466libcsound.csoundGetUtilityDescription.restype = ct.c_char_p
467libcsound.csoundGetUtilityDescription.argtypes = [ct.c_void_p, ct.c_char_p]
468libcsound.csoundRand31.argtypes = [ct.POINTER(ct.c_int)]
469libcsound.csoundSeedRandMT.argtypes = [ct.POINTER(CsoundRandMTState), ct.POINTER(ct.c_uint32), ct.c_uint32]
470libcsound.csoundRandMT.restype = ct.c_uint32
471libcsound.csoundRandMT.argtypes = [ct.POINTER(CsoundRandMTState)]
472libcsound.csoundCreateCircularBuffer.restype = ct.c_void_p
473libcsound.csoundCreateCircularBuffer.argtypes = [ct.c_void_p, ct.c_int, ct.c_int]
474libcsound.csoundReadCircularBuffer.argtypes = [ct.c_void_p, ct.c_void_p, ct.c_void_p, ct.c_int]
475libcsound.csoundPeekCircularBuffer.argtypes = [ct.c_void_p, ct.c_void_p, ct.c_void_p, ct.c_int]
476libcsound.csoundWriteCircularBuffer.argtypes = [ct.c_void_p, ct.c_void_p, ct.c_void_p, ct.c_int]
477libcsound.csoundFlushCircularBuffer.argtypes = [ct.c_void_p, ct.c_void_p]
478libcsound.csoundDestroyCircularBuffer.argtypes = [ct.c_void_p, ct.c_void_p]
479libcsound.csoundOpenLibrary.argtypes = [ct.POINTER(ct.c_void_p), ct.c_char_p]
480libcsound.csoundCloseLibrary.argtypes = [ct.c_void_p]
481libcsound.csoundGetLibrarySymbol.retype = ct.c_void_p
482libcsound.csoundGetLibrarySymbol.argtypes = [ct.c_void_p, ct.c_char_p]
483
484
485def cchar(s):
486    if sys.version_info[0] >= 3:
487        return ct.c_char(ord(s[0]))
488    return ct.c_char(s[0])
489
490def cstring(s):
491    if sys.version_info[0] >= 3 and s != None:
492        return bytes(s, 'utf-8')
493    return s
494
495def pstring(s):
496    if sys.version_info[0] >= 3 and s != None:
497        return str(s, 'utf-8')
498    return s
499
500def csoundArgList(lst):
501    if len(lst) == 1 and type(lst[0]) is list:
502        lst = lst[0]
503    argc = len(lst)
504    argv = (ct.POINTER(ct.c_char_p) * argc)()
505    for i in range(argc):
506        v = cstring(lst[i])
507        argv[i] = ct.cast(ct.pointer(ct.create_string_buffer(v)), ct.POINTER(ct.c_char_p))
508    return ct.c_int(argc), ct.cast(argv, ct.POINTER(ct.c_char_p))
509
510
511# message types (only one can be specified)
512CSOUNDMSG_DEFAULT = 0x0000       # standard message
513CSOUNDMSG_ERROR = 0x1000         # error message (initerror, perferror, etc.)
514CSOUNDMSG_ORCH = 0x2000          # orchestra opcodes (e.g. printks)
515CSOUNDMSG_REALTIME = 0x3000      # for progress display and heartbeat characters
516CSOUNDMSG_WARNING = 0x4000       # warning messages
517CSOUNDMSG_STDOUT = 0x5000
518
519# format attributes (colors etc.), use the bitwise OR of any of these:
520CSOUNDMSG_FG_BLACK = 0x0100
521CSOUNDMSG_FG_RED = 0x0101
522CSOUNDMSG_FG_GREEN = 0x0102
523CSOUNDMSG_FG_YELLOW = 0x0103
524CSOUNDMSG_FG_BLUE = 0x0104
525CSOUNDMSG_FG_MAGENTA = 0x0105
526CSOUNDMSG_FG_CYAN = 0x0106
527CSOUNDMSG_FG_WHITE = 0x0107
528
529CSOUNDMSG_FG_BOLD = 0x0008
530CSOUNDMSG_FG_UNDERLINE = 0x0080
531
532CSOUNDMSG_BG_BLACK = 0x0200
533CSOUNDMSG_BG_RED = 0x0210
534CSOUNDMSG_BG_GREEN = 0x0220
535CSOUNDMSG_BG_ORANGE = 0x0230
536CSOUNDMSG_BG_BLUE = 0x0240
537CSOUNDMSG_BG_MAGENTA = 0x0250
538CSOUNDMSG_BG_CYAN = 0x0260
539CSOUNDMSG_BG_GREY = 0x0270
540
541CSOUNDMSG_TYPE_MASK = 0x7000
542CSOUNDMSG_FG_COLOR_MASK = 0x0107
543CSOUNDMSG_FG_ATTR_MASK = 0x0088
544CSOUNDMSG_BG_COLOR_MASK = 0x0270
545
546
547# ERROR DEFINITIONS
548CSOUND_SUCCESS = 0               # Completed successfully.
549CSOUND_ERROR = -1                # Unspecified failure.
550CSOUND_INITIALIZATION = -2       # Failed during initialization.
551CSOUND_PERFORMANCE = -3          # Failed during performance.
552CSOUND_MEMORY = -4               # Failed to allocate requested memory.
553CSOUND_SIGNAL = -5               # Termination requested by SIGINT or SIGTERM.
554
555# Flags for csoundInitialize().
556CSOUNDINIT_NO_SIGNAL_HANDLER = 1
557CSOUNDINIT_NO_ATEXIT = 2
558
559# Types for keyboard callbacks set in registerKeyboardCallback()
560CSOUND_CALLBACK_KBD_EVENT = 1
561CSOUND_CALLBACK_KBD_TEXT = 2
562
563# Constants used by the bus interface (csoundGetChannelPtr() etc.).
564CSOUND_CONTROL_CHANNEL = 1
565CSOUND_AUDIO_CHANNEL  = 2
566CSOUND_STRING_CHANNEL = 3
567CSOUND_PVS_CHANNEL = 4
568CSOUND_VAR_CHANNEL = 5
569
570CSOUND_CHANNEL_TYPE_MASK = 15
571
572CSOUND_INPUT_CHANNEL = 16
573CSOUND_OUTPUT_CHANNEL = 32
574
575CSOUND_CONTROL_CHANNEL_NO_HINTS  = 0
576CSOUND_CONTROL_CHANNEL_INT  = 1
577CSOUND_CONTROL_CHANNEL_LIN  = 2
578CSOUND_CONTROL_CHANNEL_EXP  = 3
579
580# list of languages
581CSLANGUAGE_DEFAULT = 0
582CSLANGUAGE_AFRIKAANS = 1
583CSLANGUAGE_ALBANIAN = 2
584CSLANGUAGE_ARABIC = 3
585CSLANGUAGE_ARMENIAN = 4
586CSLANGUAGE_ASSAMESE = 5
587CSLANGUAGE_AZERI = 6
588CSLANGUAGE_BASQUE = 7
589CSLANGUAGE_BELARUSIAN = 8
590CSLANGUAGE_BENGALI = 9
591CSLANGUAGE_BULGARIAN = 10
592CSLANGUAGE_CATALAN = 11
593CSLANGUAGE_CHINESE = 12
594CSLANGUAGE_CROATIAN = 13
595CSLANGUAGE_CZECH = 14
596CSLANGUAGE_DANISH = 15
597CSLANGUAGE_DUTCH = 16
598CSLANGUAGE_ENGLISH_UK = 17
599CSLANGUAGE_ENGLISH_US = 18
600CSLANGUAGE_ESTONIAN = 19
601CSLANGUAGE_FAEROESE = 20
602CSLANGUAGE_FARSI = 21
603CSLANGUAGE_FINNISH = 22
604CSLANGUAGE_FRENCH = 23
605CSLANGUAGE_GEORGIAN = 24
606CSLANGUAGE_GERMAN = 25
607CSLANGUAGE_GREEK = 26
608CSLANGUAGE_GUJARATI = 27
609CSLANGUAGE_HEBREW = 28
610CSLANGUAGE_HINDI = 29
611CSLANGUAGE_HUNGARIAN = 30
612CSLANGUAGE_ICELANDIC = 31
613CSLANGUAGE_INDONESIAN = 32
614CSLANGUAGE_ITALIAN = 33
615CSLANGUAGE_JAPANESE = 34
616CSLANGUAGE_KANNADA = 35
617CSLANGUAGE_KASHMIRI = 36
618CSLANGUAGE_KAZAK = 37
619CSLANGUAGE_KONKANI = 38
620CSLANGUAGE_KOREAN = 39
621CSLANGUAGE_LATVIAN = 40
622CSLANGUAGE_LITHUANIAN = 41
623CSLANGUAGE_MACEDONIAN = 42
624CSLANGUAGE_MALAY = 43
625CSLANGUAGE_MALAYALAM = 44
626CSLANGUAGE_MANIPURI = 45
627CSLANGUAGE_MARATHI = 46
628CSLANGUAGE_NEPALI = 47
629CSLANGUAGE_NORWEGIAN = 48
630CSLANGUAGE_ORIYA = 49
631CSLANGUAGE_POLISH = 50
632CSLANGUAGE_PORTUGUESE = 51
633CSLANGUAGE_PUNJABI = 52
634CSLANGUAGE_ROMANIAN = 53
635CSLANGUAGE_RUSSIAN = 54
636CSLANGUAGE_SANSKRIT = 55
637CSLANGUAGE_SERBIAN = 56
638CSLANGUAGE_SINDHI = 57
639CSLANGUAGE_SLOVAK = 58
640CSLANGUAGE_SLOVENIAN = 59
641CSLANGUAGE_SPANISH = 60
642CSLANGUAGE_SWAHILI = 61
643CSLANGUAGE_SWEDISH = 62
644CSLANGUAGE_TAMIL = 63
645CSLANGUAGE_TATAR = 64
646CSLANGUAGE_TELUGU = 65
647CSLANGUAGE_THAI = 66
648CSLANGUAGE_TURKISH = 67
649CSLANGUAGE_UKRAINIAN = 68
650CSLANGUAGE_URDU = 69
651CSLANGUAGE_UZBEK = 70
652CSLANGUAGE_VIETNAMESE = 71
653CSLANGUAGE_COLUMBIAN = 72
654
655
656#Instantiation
657def csoundInitialize(flags):
658    """Initializes Csound library with specific flags.
659
660    This function is called internally by csoundCreate(), so there is generally
661    no need to use it explicitly unless you need to avoid default initialization
662    that sets signal handlers and atexit() callbacks.
663    Return value is zero on success, positive if initialization was
664    done already, and negative on error.
665    """
666    return libcsound.csoundInitialize(flags)
667
668def setOpcodedir(s):
669	"""Sets an opcodedir override for csoundCreate()."""
670	libcsound.csoundSetOpcodedir(cstring(s))
671
672class Csound:
673    #Instantiation
674    def __init__(self, hostData=None, pointer_=None):
675        """Creates an instance of Csound.
676
677        Gets an opaque pointer that must be passed to most Csound API
678        functions. The *hostData* parameter can be :code:`None`, or it can be
679        any sort of data; these data can be accessed from the Csound instance
680        that is passed to callback routines.
681        """
682        if pointer_:
683            self.cs = pointer_
684            self.fromPointer = True
685        else:
686            self.cs = libcsound.csoundCreate(ct.py_object(hostData))
687            self.fromPointer = False
688
689    def loadPlugins(self, directory):
690    	"""Loads all plugins from a given directory."""
691    	return libcsound.csoundLoadPlugins(self.cs, cstring(directory))
692
693    def __del__(self):
694        """Destroys an instance of Csound."""
695        if not self.fromPointer and libcsound:
696            libcsound.csoundDestroy(self.cs)
697
698    def csound(self):
699        """Returns the opaque pointer to the running Csound instance."""
700        return self.cs
701
702    def version(self):
703        """Returns the version number times 1000 (5.00.0 = 5000)."""
704        return libcsound.csoundGetVersion()
705
706    def APIVersion(self):
707        """Returns the API version number times 100 (1.00 = 100)."""
708        return libcsound.csoundGetAPIVersion()
709
710    #Performance
711    def parseOrc(self, orc):
712        """Parses the given orchestra from an ASCII string into a TREE.
713
714        This can be called during performance to parse new code.
715        """
716        return libcsound.csoundParseOrc(self.cs, cstring(orc))
717
718    def compileTree(self, tree):
719        """Compiles the given TREE node into structs for Csound to use.
720
721        This can be called during performance to compile a new TREE.
722        """
723        return libcsound.csoundCompileTree(self.cs, tree)
724
725    def compileTreeAsync(self, tree):
726        """Asynchronous version of :py:meth:`compileTree()`."""
727        return libcsound.csoundCompileTreeAsync(self.cs, tree)
728
729    def deleteTree(self, tree):
730        """Frees the resources associated with the TREE *tree*.
731
732        This function should be called whenever the TREE was
733        created with :py:meth:`parseOrc` and memory can be deallocated.
734        """
735        libcsound.csoundDeleteTree(self.cs, tree)
736
737    def compileOrc(self, orc):
738        """Parses, and compiles the given orchestra from an ASCII string.
739
740        Also evaluating any global space code (i-time only).
741        This can be called during performance to compile a new orchestra::
742
743            orc = 'instr 1 \\n a1 rand 0dbfs/4 \\n out a1 \\n'
744            cs.compileOrc(orc)
745        """
746        return libcsound.csoundCompileOrc(self.cs, cstring(orc))
747
748    def compileOrcAsync(self, orc):
749        """Async version of :py:meth:`compileOrc()`.
750
751        The code is parsed and compiled, then placed on a queue for
752        asynchronous merge into the running engine, and evaluation.
753        The function returns following parsing and compilation.
754        """
755        return libcsound.csoundCompileOrcAsync(self.cs, cstring(orc))
756
757    def evalCode(self, code):
758        """Parses and compiles an orchestra given on an string.
759
760        Evaluating any global space code (i-time only).
761        On SUCCESS it returns a value passed to the
762        'return' opcode in global space::
763
764            code = 'i1 = 2 + 2 \\n return i1 \\n'
765            retval = cs.evalCode(code)
766        """
767        return libcsound.csoundEvalCode(self.cs, cstring(code))
768
769    #def initializeCscore(insco, outsco):
770
771    def compileArgs(self, *args):
772        """Compiles *args*.
773
774        Reads arguments, parses and compiles an orchestra,
775        reads, processes and loads a score.
776        """
777        argc, argv = csoundArgList(args)
778        return libcsound.csoundCompileArgs(self.cs, argc, argv)
779
780    def start(self):
781        """Prepares Csound for performance.
782
783        Normally called after compiling a csd file or an orc file, in which
784        case score preprocessing is performed and performance terminates
785        when the score terminates.
786
787        However, if called before compiling a csd file or an orc file,
788        score preprocessing is not performed and "i" statements are dispatched
789        as real-time events, the <CsOptions> tag is ignored, and performance
790        continues indefinitely or until ended using the API.
791
792        NB: this is called internally by :py:meth:`compile_()`, therefore
793        it is only required if performance is started without
794        a call to that function.
795        """
796        return libcsound.csoundStart(self.cs)
797
798    def compile_(self, *args):
799        """Compiles Csound input files (such as an orchestra and score).
800
801        As directed by the supplied command-line arguments,
802        but does not perform them. Returns a non-zero error code on failure.
803        This function cannot be called during performance, and before a
804        repeated call, :py:meth:`reset()` needs to be called.
805        In this (host-driven) mode, the sequence of calls should be as follows::
806
807            cs.compile_(args)
808            while cs.performBuffer() == 0:
809                pass
810            cs.cleanup()
811            cs.reset()
812
813        Calls :py:meth:`start()` internally.
814        """
815        argc, argv = csoundArgList(args)
816        return libcsound.csoundCompile(self.cs, argc, argv)
817
818    def compileCsd(self, csd_filename):
819        """Compiles a Csound input file (.csd file).
820
821        The input file includes command-line arguments, but does not
822        perform the file. Returns a non-zero error code on failure.
823        In this (host-driven) mode, the sequence of calls should be
824        as follows::
825
826            cs.compileCsd(args)
827            while cs.performBuffer() == 0:
828                pass
829            cs.cleanup()
830            cs.reset()
831
832        NB: this function can be called during performance to
833        replace or add new instruments and events.
834        On a first call and if called before :py:meth:`start()`, this function
835        behaves similarly to :py:meth:`compile_()`.
836        """
837        return libcsound.csoundCompileCsd(self.cs, cstring(csd_filename))
838
839    def compileCsdText(self, csd_text):
840        """Compiles a Csound input file contained in a string of text.
841
842        The string of text includes command-line arguments, orchestra, score,
843        etc., but it is not performed. Returns a non-zero error code on failure.
844        In this (host-driven) mode, the sequence of calls should be as follows::
845
846            cs.compileCsdText(csd_text)
847            while cs.performBuffer() == 0:
848                pass
849            cs.cleanup()
850            cs.reset()
851
852        NB: a temporary file is created, the csd_text is written to the
853        temporary file, and :py:meth:`compileCsd` is called with the name of
854        the temporary file, which is deleted after compilation. Behavior may
855        vary by platform.
856        """
857        return libcsound.csoundCompileCsdText(self.cs, cstring(csd_text))
858
859    def perform(self):
860        """Senses input events and performs audio output.
861
862        This is done until the end of score is reached (positive return value),
863        an error occurs (negative return value), or performance is stopped by
864        calling :py:meth:`stop()` from another thread (zero return value).
865
866        Note that :py:meth:`compile_()`, or :py:meth:`compileOrc()`,
867        :py:meth:`readScore()`, :py:meth:`start()` must be
868        called first.
869
870        In the case of zero return value, :py:meth:`perform()` can be called
871        again to continue the stopped performance. Otherwise, :py:meth:`reset()`
872        should be called to clean up after the finished or failed performance.
873        """
874        return libcsound.csoundPerform(self.cs)
875
876    def performKsmps(self):
877        """Senses input events, and performs audio output.
878
879        This is done for one control sample worth (ksmps).
880
881        Note that :py:meth:`compile_()`, or :py:meth:`compileOrc()`,
882        :py:meth:`readScore()`, :py:meth:`start()` must be called first.
883
884        Returns :code:`False` during performance, and :code:`True` when
885        performance is finished. If called until it returns :code:`True`,
886        it will perform an entire score.
887
888        Enables external software to control the execution of Csound,
889        and to synchronize performance with audio input and output.
890        """
891        return libcsound.csoundPerformKsmps(self.cs)
892
893    def performBuffer(self):
894        """Performs Csound, sensing real-time and score events.
895
896        Processing one buffer's worth (-b frames) of interleaved audio.
897
898        Note that :py:meth:`compile_()` must be called first, then call
899        :py:meth:`outputBuffer()` and :py:meth:`inputBuffer(`) to get ndarrays
900        pointing to Csound's I/O buffers.
901
902        Returns :code:`False` during performance, and :code:`true` when
903        performance is finished.
904        """
905        return libcsound.csoundPerformBuffer(self.cs)
906
907    def stop(self):
908        """Stops a :py:meth:`perform()` running in another thread.
909
910        Note that it is not guaranteed that :py:meth:`perform()` has already
911        stopped when this function returns.
912        """
913        libcsound.csoundStop(self.cs)
914
915    def cleanup(self):
916        """Prints information and closes audio and MIDI devices.
917
918        | The information is about the end of a performance.
919        | Note: after calling cleanup(), the operation of the perform
920          function is undefined.
921        """
922        return libcsound.csoundCleanup(self.cs)
923
924    def reset(self):
925        """Resets all internal memory and state.
926
927        In preparation for a new performance.
928        Enable external software to run successive Csound performances
929        without reloading Csound. Implies :py:meth:`cleanup()`, unless already
930        called.
931        """
932        libcsound.csoundReset(self.cs)
933
934    #UDP server
935    def UDPServerStart(self, port):
936        """Starts the UDP server on a supplied port number.
937
938        Returns CSOUND_SUCCESS if server has been started successfully,
939        otherwise, CSOUND_ERROR.
940        """
941        return libcsound.csoundUDPServerStart(self.cs, ct.c_uint(port))
942
943    def UDPServerStatus(self):
944        """Returns the port number on which the server is running.
945
946        If the server is not running, CSOUND_ERROR is returned.
947        """
948        return libcsound.csoundUDPServerStatus(self.cs)
949
950    def UDPServerClose(self):
951        """Closes the UDP server.
952
953        Returns CSOUND_SUCCESS if the running server was successfully closed,
954        CSOUND_ERROR otherwise.
955        """
956        return libcsound.csoundUDPServerClose(self.cs)
957
958    def UDPConsole(self, addr, port, mirror):
959        """Turns on the transmission of console messages to UDP on addr:port.
960
961        If mirror is one, the messages will continue to be sent to the usual
962        destination (see :py:meth:`setMessageCallback()`) as well as to UDP.
963        Returns CSOUND_SUCCESS or CSOUND_ERROR if the UDP transmission
964        could not be set up.
965        """
966        return libcsound.csoundUDPConsole(self.cs, cstring(addr), ct.c_uint(port), ct.c_uint(mirror))
967
968    def stopUDPConsole(self):
969        """Stops transmitting console messages via UDP."""
970        libcsound.csoundStopUDPConsole(self.cs)
971
972    #Attributes
973    def sr(self):
974        """Returns the number of audio sample frames per second."""
975        return libcsound.csoundGetSr(self.cs)
976
977    def kr(self):
978        """Returns the number of control samples per second."""
979        return libcsound.csoundGetKr(self.cs)
980
981    def ksmps(self):
982        """Returns the number of audio sample frames per control sample."""
983        return libcsound.csoundGetKsmps(self.cs)
984
985    def nchnls(self):
986        """Returns the number of audio output channels.
987
988        Set through the :code:`nchnls` header variable in the csd file.
989        """
990        return libcsound.csoundGetNchnls(self.cs)
991
992    def nchnlsInput(self):
993        """Returns the number of audio input channels.
994
995        Set through the :code:`nchnls_i` header variable in the csd file. If
996        this variable is not set, the value is taken from :code:`nchnls`.
997        """
998        return libcsound.csoundGetNchnlsInput(self.cs)
999
1000    def get0dBFS(self):
1001        """Returns the 0dBFS level of the spin/spout buffers."""
1002        return libcsound.csoundGet0dBFS(self.cs)
1003
1004    def A4(self):
1005        """Returns the A4 frequency reference."""
1006        return libcsound.csoundGetA4(self.cs)
1007
1008    def currentTimeSamples(self):
1009        """Returns the current performance time in samples."""
1010        return libcsound.csoundGetCurrentTimeSamples(self.cs)
1011
1012    def sizeOfMYFLT(self):
1013        """Returns the size of MYFLT in bytes."""
1014        return libcsound.csoundGetSizeOfMYFLT()
1015
1016    def hostData(self):
1017        """Returns host data."""
1018        return libcsound.csoundGetHostData(self.cs)
1019
1020    def setHostData(self, data):
1021        """Sets host data."""
1022        libcsound.csoundSetHostData(self.cs, ct.py_object(data))
1023
1024    def setOption(self, option):
1025        """Sets a single csound option (flag).
1026
1027        | Returns CSOUND_SUCCESS on success.
1028        | NB: blank spaces are not allowed.
1029        """
1030        return libcsound.csoundSetOption(self.cs, cstring(option))
1031
1032    def setParams(self, params):
1033        """Configures Csound with a given set of parameters.
1034
1035        These parameters are defined in the CsoundParams structure.
1036        They are the part of the OPARMS struct that are configurable through
1037        command line flags.
1038        The CsoundParams structure can be obtained using :py:meth:`params()`.
1039        These options should only be changed before performance has started.
1040        """
1041        libcsound.csoundSetParams(self.cs, ct.byref(params))
1042
1043    def params(self, params):
1044        """Gets the current set of parameters from a CSOUND instance.
1045
1046        These parameters are in a CsoundParams structure. See
1047        :py:meth:`setParams()`::
1048
1049            p = CsoundParams()
1050            cs.params(p)
1051        """
1052        libcsound.csoundGetParams(self.cs, ct.byref(params))
1053
1054    def debug(self):
1055        """Returns whether Csound is set to print debug messages.
1056
1057        Those messages are sent through the :code:`DebugMsg()` internal API
1058        function.
1059        """
1060        return libcsound.csoundGetDebug(self.cs) != 0
1061
1062    def setDebug(self, debug):
1063        """Sets whether Csound prints debug messages.
1064
1065        The debug argument must have value :code:`True` or :code:`False`.
1066        Those messages come from the :code:`DebugMsg()` internal API function.
1067        """
1068        libcsound.csoundSetDebug(self.cs, ct.c_int(debug))
1069
1070    def systemSr(self, val):
1071    	"""If val > 0, sets the internal variable holding the system HW sr.
1072
1073    	Returns the stored value containing the system HW sr."""
1074    	return libcsound.csoundSystemSr(self.cs, val)
1075
1076    #General Input/Output
1077    def outputName(self):
1078        """Returns the audio output name (-o)"""
1079        s = libcsound.csoundGetOutputName(self.cs)
1080        return pstring(s)
1081
1082    def inputName(self):
1083        """Returns the audio input name (-i)"""
1084        s = libcsound.csoundGetInputName(self.cs)
1085        return pstring(s)
1086
1087    def setOutput(self, name, type_, format):
1088        """Sets output destination, type and format.
1089
1090        | *type_* can be one of  "wav", "aiff", "au", "raw", "paf", "svx", "nist",
1091          "voc", "ircam", "w64", "mat4", "mat5", "pvf", "xi", "htk", "sds",
1092          "avr", "wavex", "sd2", "flac", "caf", "wve", "ogg", "mpc2k", "rf64",
1093          or NULL (use default or realtime IO).
1094        | *format* can be one of "alaw", "schar", "uchar", "float", "double",
1095          "long", "short", "ulaw", "24bit", "vorbis", or NULL (use default or
1096          realtime IO).
1097
1098        For RT audio, use device_id from CS_AUDIODEVICE for a given audio
1099        device.
1100        """
1101        n = cstring(name)
1102        t = cstring(type_)
1103        f = cstring(format)
1104        libcsound.csoundSetOutput(self.cs, n, t, f)
1105
1106    def outputFormat(self):
1107        """Gets output type and format."""
1108        type_ = ct.create_string_buffer(6)
1109        format = ct.create_string_buffer(8)
1110        libcsound.csoundGetOutputFormat(self.cs, type_, format)
1111        return pstring(string_at(type_)), pstring(string_at(format))
1112
1113    def setInput(self, name):
1114        """Sets input source."""
1115        libcsound.csoundSetInput(self.cs, cstring(name))
1116
1117    def setMIDIInput(self, name):
1118        """Sets MIDI input device name/number."""
1119        libcsound.csoundSetMidiInput(self.cs, cstring(name))
1120
1121    def setMIDIFileInput(self, name):
1122        """Sets MIDI file input name."""
1123        libcsound.csoundSetMIDIFileInput(self.cs, cstring(name))
1124
1125    def setMIDIOutput(self, name):
1126        """Sets MIDI output device name/number."""
1127        libcsound.csoundSetMIDIOutput(self.cs, cstring(name))
1128
1129    def setMIDIFileOutput(self, name):
1130        """Sets MIDI file output name."""
1131        libcsound.csoundSetMIDIFileOutput(self.cs, cstring(name))
1132
1133    def setFileOpenCallback(self, function):
1134        """Sets a callback for receiving notices whenever Csound opens a file.
1135
1136        The callback is made after the file is successfully opened.
1137        The following information is passed to the callback:
1138
1139        bytes
1140            pathname of the file; either full or relative to current dir
1141        int
1142            a file type code from the enumeration CSOUND_FILETYPES
1143        int
1144            1 if Csound is writing the file, 0 if reading
1145        int
1146            1 if a temporary file that Csound will delete; 0 if not
1147
1148        Pass NULL to disable the callback.
1149        This callback is retained after a :py:meth:`reset()` call.
1150        """
1151        self.fileOpenCbRef = FILEOPENFUNC(function)
1152        libcsound.csoundSetFileOpenCallback(self.cs, self.fileOpenCbRef)
1153
1154    #Realtime Audio I/O
1155    def setRTAudioModule(self, module):
1156        """Sets the current RT audio module."""
1157        libcsound.csoundSetRTAudioModule(self.cs, cstring(module))
1158
1159    def module(self, number):
1160        """Retrieves a module name and type given a number.
1161
1162        Type is "audio" or "midi". Modules are added to list as csound loads
1163        them. Return CSOUND_SUCCESS on success and CSOUND_ERROR if module
1164        number was not found::
1165
1166            n = 0
1167            while True:
1168                name, type_, err = cs.module(n)
1169                if err == ctcsound.CSOUND_ERROR:
1170                    break
1171                print("Module %d:%s (%s)\\n" % (n, name, type_))
1172                n = n + 1
1173        """
1174        name = ct.pointer(ct.c_char_p(cstring("dummy")))
1175        type_ = ct.pointer(ct.c_char_p(cstring("dummy")))
1176        err = libcsound.csoundGetModule(self.cs, number, name, type_)
1177        if err == CSOUND_ERROR:
1178            return None, None, err
1179        n = pstring(string_at(name.contents))
1180        t = pstring(string_at(type_.contents))
1181        return n, t, err
1182
1183    def inputBufferSize(self):
1184        """Returns the number of samples in Csound's input buffer."""
1185        return libcsound.csoundGetInputBufferSize(self.cs)
1186
1187    def outputBufferSize(self):
1188        """Returns the number of samples in Csound's output buffer."""
1189        return libcsound.csoundGetOutputBufferSize(self.cs)
1190
1191    def inputBuffer(self):
1192        """Returns the Csound audio input buffer as an ndarray.
1193
1194        Enables external software to write audio into Csound before
1195        calling :py:meth:`performBuffer()`.
1196        """
1197        buf = libcsound.csoundGetInputBuffer(self.cs)
1198        size = libcsound.csoundGetInputBufferSize(self.cs)
1199        arrayType = np.ctypeslib.ndpointer(MYFLT, 1, (size,), 'C_CONTIGUOUS')
1200        p = ct.cast(buf, arrayType)
1201        return arrFromPointer(p)
1202
1203    def outputBuffer(self):
1204        """Returns the Csound audio output buffer as an ndarray.
1205
1206        Enables external software to read audio from Csound after
1207        calling :py:meth:`performBuffer()`.
1208        """
1209        buf = libcsound.csoundGetOutputBuffer(self.cs)
1210        size = libcsound.csoundGetOutputBufferSize(self.cs)
1211        arrayType = np.ctypeslib.ndpointer(MYFLT, 1, (size,), 'C_CONTIGUOUS')
1212        p = ct.cast(buf, arrayType)
1213        return arrFromPointer(p)
1214
1215    def spin(self):
1216        """Returns the Csound audio input working buffer (spin) as an ndarray.
1217
1218        Enables external software to write audio into Csound before
1219        calling :py:meth:`performKsmps()`.
1220        """
1221        buf = libcsound.csoundGetSpin(self.cs)
1222        size = self.ksmps() * self.nchnlsInput()
1223        arrayType = np.ctypeslib.ndpointer(MYFLT, 1, (size,), 'C_CONTIGUOUS')
1224        p = ct.cast(buf, arrayType)
1225        return arrFromPointer(p)
1226
1227    def clearSpin(self):
1228        """Clears the input buffer (spin)."""
1229        libcsound.csoundClearSpin(self.cs)
1230
1231    def addSpinSample(self, frame, channel, sample):
1232        """Adds the indicated sample into the audio input working buffer (spin).
1233
1234        This only ever makes sense before calling :py:meth:`performKsmps()`.
1235        The frame and channel must be in bounds relative to :py:meth:`ksmps()`
1236        and :py:meth:`nchnlsInput()`.
1237
1238        NB: the spin buffer needs to be cleared at every k-cycle by calling
1239        :py:meth:`clearSpin()`.
1240        """
1241        libcsound.csoundAddSpinSample(self.cs, frame, channel, sample)
1242
1243    def setSpinSample(self, frame, channel, sample):
1244        """Sets the audio input working buffer (spin) to the indicated sample.
1245
1246        This only ever makes sense before calling :py:meth:`performKsmps()`.
1247        The frame and channel must be in bounds relative to :py:meth:`ksmps()`
1248        and :py:meth:`nchnlsInput()`.
1249        """
1250        libcsound.csoundSetSpinSample(self.cs, frame, channel, sample)
1251
1252    def spout(self):
1253        """Returns the address of the Csound audio output working buffer (spout).
1254
1255        Enables external software to read audio from Csound after
1256        calling :py:meth:`performKsmps`.
1257        """
1258        buf = libcsound.csoundGetSpout(self.cs)
1259        size = self.ksmps() * self.nchnls()
1260        arrayType = np.ctypeslib.ndpointer(MYFLT, 1, (size,), 'C_CONTIGUOUS')
1261        p = ct.cast(buf, arrayType)
1262        return arrFromPointer(p)
1263
1264    def spoutSample(self, frame, channel):
1265        """Returns one sample from the Csound audio output working buf (spout).
1266
1267        Only ever makes sense after calling :py:meth:`performKsmps()`. The
1268        *frame* and *channel* must be in bounds relative to :py:meth:`ksmps()`
1269        and :py:meth:`nchnls()`.
1270        """
1271        return libcsound.csoundGetSpoutSample(self.cs, frame, channel)
1272
1273    def rtRecordUserData(self):
1274        """Returns pointer to user data pointer for real time audio input."""
1275        return libcsound.csoundGetRtRecordUserData(self.cs)
1276
1277    def rtPlaydUserData(self):
1278        """Returns pointer to user data pointer for real time audio output."""
1279        return libcsound.csoundGetRtPlayUserData(self.cs)
1280
1281    def setHostImplementedAudioIO(self, state, bufSize):
1282        """Sets user handling of sound I/O.
1283
1284        Calling this function with a :code:`True` *state* value between creation
1285        of the Csound object and the start of performance will disable all
1286        default handling of sound I/O by the Csound library, allowing the host
1287        application to use the spin/spout/input/output buffers directly.
1288
1289        For applications using spin/spout, *bufSize* should be set to 0.
1290        If *bufSize* is greater than zero, the buffer size (-b) will be
1291        set to the integer multiple of :py:meth:`ksmps()` that is nearest to the
1292        value specified.
1293        """
1294        libcsound.csoundSetHostImplementedAudioIO(self.cs, ct.c_int(state), bufSize)
1295
1296    def audioDevList(self, isOutput):
1297        """Returns a list of available input or output audio devices.
1298
1299        Each item in the list is a dictionnary representing a device. The
1300        dictionnary keys are *device_name*, *device_id*, *rt_module* (value
1301        type string), *max_nchnls* (value type int), and *isOutput* (value
1302        type boolean).
1303
1304        Must be called after an orchestra has been compiled
1305        to get meaningful information.
1306        """
1307        n = libcsound.csoundGetAudioDevList(self.cs, None, ct.c_int(isOutput))
1308        devs = (CsoundAudioDevice * n)()
1309        libcsound.csoundGetAudioDevList(self.cs, ct.byref(devs), ct.c_int(isOutput))
1310        lst = []
1311        for dev in devs:
1312            d = {}
1313            d["device_name"] = pstring(dev.device_name)
1314            d["device_id"] = pstring(dev.device_id)
1315            d["rt_module"] = pstring(dev.rt_module)
1316            d["max_nchnls"] = dev.max_nchnls
1317            d["isOutput"] = (dev.isOutput == 1)
1318            lst.append(d)
1319        return lst
1320
1321    def setPlayOpenCallback(self, function):
1322        """Sets a callback for opening real-time audio playback."""
1323        self.playOpenCbRef = PLAYOPENFUNC(function)
1324        libcsound.csoundSetPlayopenCallback(self.cs, self.playOpenCbRef)
1325
1326    def setRtPlayCallback(self, function):
1327        """Sets a callback for performing real-time audio playback."""
1328        self.rtPlayCbRef = RTPLAYFUNC(function)
1329        libcsound.csoundSetRtplayCallback(self.cs, self.rtPlayCbRef)
1330
1331    def setRecordOpenCallback(self, function):
1332        """Sets a callback for opening real-time audio recording."""
1333        self.recordOpenCbRef = RECORDOPENFUNC(function)
1334        libcsound.csoundSetRecopenCallback(self.cs, self.recordOpenCbRef)
1335
1336    def setRtRecordCallback(self, function):
1337        """Sets a callback for performing real-time audio recording."""
1338        self.rtRecordCbRef = RTRECORDFUNC(function)
1339        libcsound.csoundSetRtrecordCallback(self.cs, self.rtRecordCbRef)
1340
1341    def setRtCloseCallback(self, function):
1342        """Sets a callback for closing real-time audio playback and recording."""
1343        self.rtCloseCbRef = RTCLOSEFUNC(function)
1344        libcsound.csoundSetRtcloseCallback(self.cs, self.rtCloseCbRef)
1345
1346    def setAudioDevListCallback(self, function):
1347        """Sets a callback for obtaining a list of audio devices.
1348
1349        This should be set by rtaudio modules and should not be set by hosts.
1350        (See :py:meth:`audioDevList()`).
1351        """
1352        self.audioDevListCbRef = AUDIODEVLISTFUNC(function)
1353        libcsound.csoundSetAudioDeviceListCallback(self.cs, self.audioDevListCbRef)
1354
1355    #Realtime MIDI I/O
1356    def setMIDIModule(self, module):
1357        """Sets the current MIDI IO module."""
1358        libcsound.csoundSetMIDIModule(self.cs, cstring(module))
1359
1360    def setHostImplementedMIDIIO(self, state):
1361        """Called with *state* :code:`True` if the host is implementing via callbacks."""
1362        libcsound.csoundSetHostImplementedMIDIIO(self.cs, ct.c_int(state))
1363
1364    def midiDevList(self, isOutput):
1365        """Returns a list of available input or output midi devices.
1366
1367        Each item in the list is a dictionnary representing a device. The
1368        dictionnary keys are *device_name*, *interface_name*, *device_id*,
1369        *midi_module* (value type string), *isOutput* (value type boolean).
1370
1371        Must be called after an orchestra has been compiled
1372        to get meaningful information.
1373        """
1374        n = libcsound.csoundGetMIDIDevList(self.cs, None, ct.c_int(isOutput))
1375        devs = (csoundMidiDevice * n)()
1376        libcsound.csoundGetMIDIDevList(self.cs, ct.byref(devs), ct.c_int(isOutput))
1377        lst = []
1378        for dev in devs:
1379            d = {}
1380            d["device_name"] = pstring(dev.device_name)
1381            d["interface_name"] = pstring(dev.max_nchnlsinterface_name)
1382            d["device_id"] = pstring(dev.device_id)
1383            d["midi_module"] = pstring(dev.midi_module)
1384            d["isOutput"] = (dev.isOutput == 1)
1385            lst.append(d)
1386        return lst
1387
1388    def setExternalMidiInOpenCallback(self, function):
1389        """Sets a callback for opening real-time MIDI input."""
1390        self.extMidiInOpenCbRef = MIDIINOPENFUNC(function)
1391        libcsound.csoundSetExternalMidiInOpenCallback(self.cs, self.extMidiInOpenCbRef)
1392
1393    def setExternalMidiReadCallback(self, function):
1394        """Sets a callback for reading from real time MIDI input."""
1395        self.extMidiReadCbRef = MIDIREADFUNC(function)
1396        libcsound.csoundSetExternalMidiReadCallback(self.cs, self.extMidiReadCbRef)
1397
1398    def setExternalMidiInCloseCallback(self, function):
1399        """Sets a callback for closing real time MIDI input."""
1400        self.extMidiInCloseCbRef = MIDIINCLOSEFUNC(function)
1401        libcsound.csoundSetExternalMidiInCloseCallback(self.cs, self.extMidiInCloseCbRef)
1402
1403    def setExternalMidiOutOpenCallback(self, function):
1404        """Sets a callback for opening real-time MIDI input."""
1405        self.extMidiOutOpenCbRef = MIDIOUTOPENFUNC(function)
1406        libcsound.csoundSetExternalMidiOutOpenCallback(self.cs, self.extMidiOutOpenCbRef)
1407
1408    def setExternalMidiWriteCallback(self, function):
1409        """Sets a callback for reading from real time MIDI input."""
1410        self.extMidiWriteCbRef = MIDIWRITEFUNC(function)
1411        libcsound.csoundSetExternalMidiWriteCallback(self.cs, self.extMidiWriteCbRef)
1412
1413    def setExternalMidiOutCloseCallback(self, function):
1414        """Sets a callback for closing real time MIDI input."""
1415        self.extMidiOutCloseCbRef = MIDIOUTCLOSEFUNC(function)
1416        libcsound.csoundSetExternalMidiOutCloseCallback(self.cs, self.extMidiOutCloseCbRef)
1417
1418    def setExternalMidiErrorStringCallback(self, function):
1419        """ Sets a callback for converting MIDI error codes to strings."""
1420        self.extMidiErrStrCbRef = MIDIERRORFUNC(function)
1421        libcsound.csoundSetExternalMidiErrorStringCallback(self.cs, self.extMidiErrStrCbRef)
1422
1423    def setMidiDevListCallback(self, function):
1424        """Sets a callback for obtaining a list of MIDI devices.
1425
1426        This should be set by IO plugins and should not be set by hosts.
1427        (See :py:meth:`midiDevList()`).
1428        """
1429        self.midiDevListCbRef = MIDIDEVLISTFUNC(function)
1430        libcsound.csoundSetMIDIDeviceListCallback(self.cs, self.midiDevListCbRef)
1431
1432    #Score Handling
1433    def readScore(self, sco):
1434        """Reads, preprocesses, and loads a score from an ASCII string.
1435
1436        It can be called repeatedly, with the new score events
1437        being added to the currently scheduled ones.
1438        """
1439        return libcsound.csoundReadScore(self.cs, cstring(sco))
1440
1441    def readScoreAsync(self, sco):
1442        """Asynchronous version of :py:meth:`readScore()`."""
1443        libcsound.csoundReadScoreAsync(self.cs, cstring(sco))
1444
1445    def scoreTime(self):
1446        """Returns the current score time.
1447
1448        The return value is the time in seconds since the beginning of
1449        performance.
1450        """
1451        return libcsound.csoundGetScoreTime(self.cs)
1452
1453    def isScorePending(self):
1454        """Tells whether Csound score events are performed or not.
1455
1456        Independently of real-time MIDI events (see :py:meth:`setScorePending()`).
1457        """
1458        return libcsound.csoundIsScorePending(self.cs) != 0
1459
1460    def setScorePending(self, pending):
1461        """Sets whether Csound score events are performed or not.
1462
1463        Real-time events will continue to be performed. Can be used by external
1464        software, such as a VST host, to turn off performance of score events
1465        (while continuing to perform real-time events), for example to mute
1466        a Csound score while working on other tracks of a piece, or to play
1467        the Csound instruments live.
1468        """
1469        libcsound.csoundSetScorePending(self.cs, ct.c_int(pending))
1470
1471    def scoreOffsetSeconds(self):
1472        """Returns the score time beginning midway through a Csound score.
1473
1474        At this time score events will actually immediately be performed
1475        (see :py:meth:`setScoreOffsetSeconds()`).
1476        """
1477        return libcsound.csoundGetScoreOffsetSeconds(self.cs)
1478
1479    def setScoreOffsetSeconds(self, time):
1480        """Csound score events prior to the specified time are not performed.
1481
1482        Performance begins immediately at the specified time (real-time events
1483        will continue to be performed as they are received). Can be used by
1484        external software, such as a VST host, to begin score performance
1485        midway through a Csound score, for example to repeat a loop in a
1486        sequencer, or to synchronize other events with the Csound score.
1487        """
1488        libcsound.csoundSetScoreOffsetSeconds(self.cs, MYFLT(time))
1489
1490    def rewindScore(self):
1491        """Rewinds a compiled Csound score.
1492
1493        It is rewinded to the time specified with :py:meth:`setScoreOffsetSeconds()`.
1494        """
1495        libcsound.csoundRewindScore(self.cs)
1496
1497    def setCscoreCallback(self, function):
1498        """Sets an external callback for Cscore processing.
1499
1500        Pass :code:`None` to reset to the internal :code:`cscore()` function
1501        (which does nothing). This callback is retained after a
1502        :py:meth:`reset()` call.
1503        """
1504        self.cscoreCbRef = CSCOREFUNC(function)
1505        libcsound.csoundSetCscoreCallback(self.cs, self.cscoreCbRef)
1506
1507    #def scoreSort(self, inFile, outFile):
1508
1509    #def scoreExtract(self, inFile, outFile, extractFile)
1510
1511    #Messages and Text
1512    def message(self, fmt, *args):
1513        """Displays an informational message.
1514
1515        This is a workaround because :program:`ctypes` does not support
1516        variadic functions.
1517        The arguments are formatted in a string, using the python way, either
1518        old style or new style, and then this formatted string is passed to
1519        the Csound display message system.
1520        """
1521        if fmt[0] == '{':
1522            s = fmt.format(*args)
1523        else:
1524            s = fmt % args
1525        libcsound.csoundMessage(self.cs, cstring("%s"), cstring(s))
1526
1527    def messageS(self, attr, fmt, *args):
1528        """Prints message with special attributes.
1529
1530        (See msg_attr for the list of available attributes). With attr=0,
1531        messageS() is identical to :py:meth:`message()`.
1532        This is a workaround because :program:`ctypes` does not support
1533        variadic functions.
1534        The arguments are formatted in a string, using the python way, either
1535        old style or new style, and then this formatted string is passed to
1536        the csound display message system.
1537        """
1538        if fmt[0] == '{':
1539            s = fmt.format(*args)
1540        else:
1541            s = fmt % args
1542        libcsound.csoundMessageS(self.cs, attr, cstring("%s"), cstring(s))
1543
1544    #def setDefaultMessageCallback():
1545
1546    #def setMessageCallback():
1547
1548    #def setMessageStringCallback()
1549
1550    def messageLevel(self):
1551        """Returns the Csound message level (from 0 to 231)."""
1552        return libcsound.csoundGetMessageLevel(self.cs)
1553
1554    def setMessageLevel(self, messageLevel):
1555        """Sets the Csound message level (from 0 to 231)."""
1556        libcsound.csoundSetMessageLevel(self.cs, messageLevel)
1557
1558    def createMessageBuffer(self, toStdOut):
1559        """Creates a buffer for storing messages printed by Csound.
1560
1561        Should be called after creating a Csound instance and the buffer
1562        can be freed by calling :py:meth:`destroyMessageBuffer()` before
1563        deleting the Csound instance. You will generally want to call
1564        :py:meth:`cleanup()` to make sure the last messages are flushed to
1565        the message buffer before destroying Csound.
1566
1567        If *toStdOut* is :code:`True`, the messages are also printed to
1568        stdout and stderr (depending on the type of the message),
1569        in addition to being stored in the buffer.
1570
1571        Using the message buffer ties up the internal message callback, so
1572        :py:meth:`setMessageCallback()` should not be called after creating the
1573        message buffer.
1574        """
1575        libcsound.csoundCreateMessageBuffer(self.cs,  ct.c_int(toStdOut))
1576
1577    def firstMessage(self):
1578        """Returns the first message from the buffer."""
1579        s = libcsound.csoundGetFirstMessage(self.cs)
1580        return pstring(s)
1581
1582    def firstMessageAttr(self):
1583        """Returns the attribute parameter of the first message in the buffer."""
1584        return libcsound.csoundGetFirstMessageAttr(self.cs)
1585
1586    def popFirstMessage(self):
1587        """Removes the first message from the buffer."""
1588        libcsound.csoundPopFirstMessage(self.cs)
1589
1590    def messageCnt(self):
1591        """Returns the number of pending messages in the buffer."""
1592        return libcsound.csoundGetMessageCnt(self.cs)
1593
1594    def destroyMessageBuffer(self):
1595        """Releases all memory used by the message buffer."""
1596        libcsound.csoundDestroyMessageBuffer(self.cs)
1597
1598    #Channels, Control and Events
1599    def channelPtr(self, name, type_):
1600        """Returns a pointer to the specified channel and an error message.
1601
1602        If the channel is a control or an audio channel, the pointer is
1603        translated to an ndarray of MYFLT. If the channel is a string channel,
1604        the pointer is casted to :code:`ct.c_char_p`. The error message is either
1605        an empty string or a string describing the error that occured.
1606
1607        The channel is created first if it does not exist yet.
1608        *type_* must be the bitwise OR of exactly one of the following values,
1609
1610        CSOUND_CONTROL_CHANNEL
1611            control data (one MYFLT value)
1612        CSOUND_AUDIO_CHANNEL
1613            audio data (:py:meth:`ksmps()` MYFLT values)
1614        CSOUND_STRING_CHANNEL
1615            string data (MYFLT values with enough space to store
1616            :py:meth:`getChannelDatasize()` characters, including the
1617            NULL character at the end of the string)
1618
1619        and at least one of these:
1620
1621        CSOUND_INPUT_CHANNEL
1622
1623        CSOUND_OUTPUT_CHANNEL
1624
1625        If the channel already exists, it must match the data type
1626        (control, audio, or string), however, the input/output bits are
1627        OR'd with the new value. Note that audio and string channels
1628        can only be created after calling :py:meth:`compile_()`, because the
1629        storage size is not known until then.
1630
1631        Return value is zero on success, or a negative error code,
1632
1633        CSOUND_MEMORY
1634            there is not enough memory for allocating the channel
1635        CSOUND_ERROR
1636            the specified name or type is invalid
1637
1638        or, if a channel with the same name but incompatible type
1639        already exists, the type of the existing channel. In the case
1640        of any non-zero return value, \*p is set to NULL.
1641        Note: to find out the type of a channel without actually
1642        creating or changing it, set *type_* to zero, so that the return
1643        value will be either the type of the channel, or CSOUND_ERROR
1644        if it does not exist.
1645
1646        Operations on the pointer are not thread-safe by default. The host is
1647        required to take care of threadsafety by retrieving the channel lock
1648        with :py:meth:`channelLock()` and using :py:meth:`spinLock()` and
1649        :py:meth:`spinUnLock()` to protect access to the pointer.
1650
1651        See Top/threadsafe.c in the Csound library sources for
1652        examples. Optionally, use the channel get/set functions
1653        provided below, which are threadsafe by default.
1654        """
1655        length = 0
1656        chanType = type_ & CSOUND_CHANNEL_TYPE_MASK
1657        if chanType == CSOUND_CONTROL_CHANNEL:
1658            length = 1
1659        elif chanType == CSOUND_AUDIO_CHANNEL:
1660            length = libcsound.csoundGetKsmps(self.cs)
1661        ptr = ct.POINTER(MYFLT)()
1662        err = ''
1663        ret = libcsound.csoundGetChannelPtr(self.cs, ct.byref(ptr), cstring(name), type_)
1664        if ret == CSOUND_SUCCESS:
1665            if chanType == CSOUND_STRING_CHANNEL:
1666                return ct.cast(ptr, ct.c_char_p), err
1667            else:
1668                arrayType = np.ctypeslib.ndpointer(MYFLT, 1, (length,), 'C_CONTIGUOUS')
1669                p = ct.cast(ptr, arrayType)
1670                return arrFromPointer(p), err
1671        elif ret == CSOUND_MEMORY:
1672            err = 'Not enough memory for allocating channel'
1673        elif ret == CSOUND_ERROR:
1674            err = 'The specified channel name or type is not valid'
1675        elif ret == CSOUND_CONTROL_CHANNEL:
1676            err = 'A control channel named {} already exists'.format(name)
1677        elif ret == CSOUND_AUDIO_CHANNEL:
1678            err = 'An audio channel named {} already exists'.format(name)
1679        elif ret == CSOUND_STRING_CHANNEL:
1680            err = 'A string channel named {} already exists'.format(name)
1681        else:
1682            err = 'Unknown error'
1683        return None, err
1684
1685    def listChannels(self):
1686        """Returns a pointer and an error message.
1687
1688        The pointer points to a list of ControlChannelInfo objects for allocated
1689        channels. A ControlChannelInfo object contains the channel
1690        characteristics. The error message indicates if there is not enough
1691        memory for allocating the list or it is an empty string if there is no
1692        error. In the case of no channels or an error, the pointer is
1693        :code:`None`.
1694
1695        Notes: the caller is responsible for freeing the list returned by the
1696        C API with :py:meth:`deleteChannelList()`. The name pointers may become
1697        invalid after calling :py:meth:`reset()`.
1698        """
1699        cInfos = None
1700        err = ''
1701        ptr = ct.cast(ct.POINTER(ct.c_int)(), ct.POINTER(ControlChannelInfo))
1702        n = libcsound.csoundListChannels(self.cs, ct.byref(ptr))
1703        if n == CSOUND_MEMORY :
1704            err = 'There is not enough memory for allocating the list'
1705        if n > 0:
1706            cInfos = ct.cast(ptr, ct.POINTER(ControlChannelInfo * n)).contents
1707        return cInfos, err
1708
1709    def deleteChannelList(self, lst):
1710        """Releases a channel list previously returned by :py:meth:`listChannels()`."""
1711        ptr = ct.cast(lst, ct.POINTER(ControlChannelInfo))
1712        libcsound.csoundDeleteChannelList(self.cs, ptr)
1713
1714    def setControlChannelHints(self, name, hints):
1715        """Sets parameters hints for a control channel.
1716
1717        These hints have no internal function but can be used by front ends to
1718        construct GUIs or to constrain values. See the ControlChannelHints
1719        structure for details.
1720        Returns zero on success, or a non-zero error code on failure:
1721
1722        CSOUND_ERROR
1723            the channel does not exist, is not a control channel,
1724            or the specified parameters are invalid
1725        CSOUND_MEMORY
1726            could not allocate memory
1727        """
1728        return libcsound.csoundSetControlChannelHints(self.cs, cstring(name), hints)
1729
1730    def controlChannelHints(self, name):
1731        """Returns special parameters (if any) of a control channel.
1732
1733        Those parameters have been previously set with
1734        :py:meth:`setControlChannelHints()` or the :code:`chnparams` opcode.
1735
1736        The return values are a ControlChannelHints structure and
1737        CSOUND_SUCCESS if the channel exists and is a control channel,
1738        otherwise, :code:`None` and an error code are returned.
1739        """
1740        hints = ControlChannelHints()
1741        ret = libcsound.csoundGetControlChannelHints(self.cs, cstring(name), ct.byref(hints))
1742        if ret != CSOUND_SUCCESS:
1743            hints = None
1744        return hints, ret
1745
1746    def channelLock(self, name):
1747        """Recovers a pointer to a lock for the specified channel called *name*.
1748
1749        The returned lock can be locked/unlocked  with the :py:meth:`spinLock()`
1750        and :py:meth:`spinUnLock()` functions.
1751        Returns the address of the lock or NULL if the channel does not exist.
1752        """
1753        return libcsound.csoundGetChannelLock(self.cs, cstring(name))
1754
1755    def controlChannel(self, name):
1756        """Retrieves the value of control channel identified by *name*.
1757
1758        A second value is returned, which is the error (or success) code
1759        finding or accessing the channel.
1760        """
1761        err = ct.c_int(0)
1762        ret = libcsound.csoundGetControlChannel(self.cs, cstring(name), ct.byref(err))
1763        return ret, err
1764
1765    def setControlChannel(self, name, val):
1766        """Sets the value of control channel identified by *name*."""
1767        libcsound.csoundSetControlChannel(self.cs, cstring(name), MYFLT(val))
1768
1769    def audioChannel(self, name, samples):
1770        """Copies the audio channel identified by *name* into ndarray samples.
1771
1772        *samples* should contain enough memory for :py:meth:`ksmps()` MYFLTs.
1773        """
1774        ptr = samples.ctypes.data_as(ct.POINTER(MYFLT))
1775        libcsound.csoundGetAudioChannel(self.cs, cstring(name), ptr)
1776
1777    def setAudioChannel(self, name, samples):
1778        """Sets the audio channel *name* with data from the ndarray *samples*.
1779
1780        *samples* should contain at least :py:meth:`ksmps()` MYFLTs.
1781        """
1782        ptr = samples.ctypes.data_as(ct.POINTER(MYFLT))
1783        libcsound.csoundSetAudioChannel(self.cs, cstring(name), ptr)
1784
1785    def stringChannel(self, name, string):
1786        """Copies the string channel identified by *name* into *string*.
1787
1788        *string* should contain enough memory for the string
1789        (see :py:meth:`channelDatasize()` below).
1790        """
1791        libcsound.csoundGetStringChannel(self.cs, cstring(name), cstring(string))
1792
1793    def setStringChannel(self, name, string):
1794        """Sets the string channel identified by *name* with *string*."""
1795        libcsound.csoundSetStringChannel(self.cs, cstring(name), cstring(string))
1796
1797    def channelDatasize(self, name):
1798        """Returns the size of data stored in a channel.
1799
1800        For string channels this might change if the channel space gets
1801        reallocated. Since string variables use dynamic memory allocation in
1802        Csound6, this function can be called to get the space required for
1803        :py:meth:`stringChannel()`.
1804        """
1805        return libcsound.csoundGetChannelDatasize(self.cs, cstring(name))
1806
1807    def setInputChannelCallback(self, function):
1808        """Sets the function to call whenever the :code:`invalue` opcode is used."""
1809        self.inputChannelCbRef = CHANNELFUNC(function)
1810        libcsound.csoundSetInputChannelCallback(self.cs, self.inputChannelCbRef)
1811
1812    def setOutputChannelCallback(self, function):
1813        """Sets the function to call whenever the :code:`outvalue` opcode is used."""
1814        self.outputChannelCbRef = CHANNELFUNC(function)
1815        libcsound.csoundSetOutputChannelCallback(self.cs, self.outputChannelCbRef)
1816
1817    def setPvsChannel(self, fin, name):
1818        """Sends a PvsdatExt *fin* to the :code:`pvsin` opcode (f-rate) for channel *name*.
1819
1820        | Returns zero on success, CSOUND_ERROR if the index is invalid or
1821          fsig framesizes are incompatible.
1822        | CSOUND_MEMORY if there is not enough memory to extend the bus.
1823        """
1824        return libcsound.csoundSetPvsChannel(self.cs, ct.byref(fin), cstring(name))
1825
1826    def pvsChannel(self, fout, name):
1827        """Receives a PvsdatExt *fout* from the :code:`pvsout` opcode (f-rate) at channel *name*.
1828
1829        | Returns zero on success, CSOUND_ERROR if the index is invalid or
1830          if fsig framesizes are incompatible.
1831        | CSOUND_MEMORY if there is not enough memory to extend the bus.
1832        """
1833        return libcsound.csoundGetPvsChannel(self.cs, ct.byref(fout), cstring(name))
1834
1835    def scoreEvent(self, type_, pFields):
1836        """Sends a new score event.
1837
1838        | *type_* is the score event type ('a', 'i', 'q', 'f', or 'e').
1839        | *pFields* is a tuple, a list, or an ndarray of MYFLTs with all the
1840          pfields for this event, starting with the p1 value specified in
1841          pFields[0].
1842        """
1843        p = np.array(pFields).astype(MYFLT)
1844        ptr = p.ctypes.data_as(ct.POINTER(MYFLT))
1845        numFields = ct.c_long(p.size)
1846        return libcsound.csoundScoreEvent(self.cs, cchar(type_), ptr, numFields)
1847
1848    def scoreEventAsync(self, type_, pFields):
1849        """Asynchronous version of :py:meth:`scoreEvent()`."""
1850        p = np.array(pFields).astype(MYFLT)
1851        ptr = p.ctypes.data_as(ct.POINTER(MYFLT))
1852        numFields = ct.c_long(p.size)
1853        libcsound.csoundScoreEventAsync(self.cs, cchar(type_), ptr, numFields)
1854
1855    def scoreEventAbsolute(self, type_, pFields, timeOffset):
1856        """Like :py:meth:`scoreEvent()`, this function inserts a score event.
1857
1858        The event is inserted at absolute time with respect to the start of
1859        performance, or from an offset set with timeOffset.
1860        """
1861        p = np.array(pFields).astype(MYFLT)
1862        ptr = p.ctypes.data_as(ct.POINTER(MYFLT))
1863        numFields = ct.c_long(p.size)
1864        return libcsound.csoundScoreEventAbsolute(self.cs, cchar(type_), ptr, numFields, ct.c_double(timeOffset))
1865
1866    def scoreEventAbsoluteAsync(self, type_, pFields, timeOffset):
1867        """Asynchronous version of :py:meth:`scoreEventAbsolute()`."""
1868        p = np.array(pFields).astype(MYFLT)
1869        ptr = p.ctypes.data_as(ct.POINTER(MYFLT))
1870        numFields = ct.c_long(p.size)
1871        libcsound.csoundScoreEventAbsoluteAsync(self.cs, cchar(type_), ptr, numFields, ct.c_double(timeOffset))
1872
1873    def inputMessage(self, message):
1874        """Inputs a NULL-terminated string (as if from a console).
1875
1876        Used for line events.
1877        """
1878        libcsound.csoundInputMessage(self.cs, cstring(message))
1879
1880    def inputMessageAsync(self, message):
1881        """Asynchronous version of :py:meth:`inputMessage()`."""
1882        libcsound.csoundInputMessageAsync(self.cs, cstring(message))
1883
1884    def killInstance(self, instr, instrName, mode, allowRelease):
1885        """Kills off one or more running instances of an instrument.
1886
1887        The instances are identified by *instr* (number) or *instrName* (name).
1888        If *instrName* is :code:`None`, the instrument number is used.
1889
1890        | *mode* is a sum of the following values:
1891        | 0, 1, 2: kill all instances (0), oldest only (1), or newest (2)
1892        | 4: only turnoff notes with exactly matching (fractional) instr number
1893        | 8: only turnoff notes with indefinite duration (p3 < 0 or MIDI).
1894
1895        If *allowRelease* is :code:`True`, the killed instances are allowed to
1896        release.
1897        """
1898        return libcsound.csoundKillInstance(self.cs, MYFLT(instr), cstring(instrName), mode, ct.c_int(allowRelease))
1899
1900    def registerSenseEventCallback(self, function, userData):
1901        """Registers a function to be called by :code:`sensevents()`.
1902
1903        This function will be called once in every control period. Any number
1904        of functions may be registered, and will be called in the order of
1905        registration.
1906
1907        The callback function takes two arguments: the Csound instance
1908        pointer, and the *userData* pointer as passed to this function.
1909
1910        This facility can be used to ensure a function is called synchronously
1911        before every csound control buffer processing. It is important
1912        to make sure no blocking operations are performed in the callback.
1913        The callbacks are cleared on :py:meth:`cleanup()`.
1914
1915        Returns zero on success.
1916        """
1917        self.senseEventCbRef = SENSEFUNC(function)
1918        return libcsound.csoundRegisterSenseEventCallback(self.cs, self.senseEventCbRef, ct.py_object(userData))
1919
1920    def keyPress(self, c):
1921        """Sets the ASCII code of the most recent key pressed.
1922
1923        This value is used by the :code:`sensekey` opcode if a callback for
1924        returning keyboard events is not set (see
1925        :py:meth:`registerKeyboardCallback()`).
1926        """
1927        libcsound.csoundKeyPress(self.cs, cchar(c))
1928
1929    def registerKeyboardCallback(self, function, userData, type_):
1930        """Registers general purpose callback functions for keyboard events.
1931
1932        These callbacks are called on every control period by the sensekey
1933        opcode.
1934
1935        The callback is preserved on :py:meth:`reset()`, and multiple
1936        callbacks may be set and will be called in reverse order of
1937        registration. If the same function is set again, it is only moved
1938        in the list of callbacks so that it will be called first, and the
1939        user data and type mask parameters are updated. *type_* can be the
1940        bitwise OR of callback types for which the function should be called,
1941        or zero for all types.
1942
1943        Returns zero on success, CSOUND_ERROR if the specified function
1944        pointer or type mask is invalid, and CSOUND_MEMORY if there is not
1945        enough memory.
1946
1947        The callback function takes the following arguments:
1948
1949        *userData*
1950            the "user data" pointer, as specified when setting the callback
1951        *p*
1952            data pointer, depending on the callback type
1953        *type_*
1954            callback type, can be one of the following (more may be added in
1955            future versions of Csound):
1956
1957            CSOUND_CALLBACK_KBD_EVENT
1958
1959            CSOUND_CALLBACK_KBD_TEXT
1960                called by the :code:`sensekey` opcode to fetch key codes. The
1961                data pointer is a pointer to a single value of type :code:`int`,
1962                for returning the key code, which can be in the range 1 to
1963                65535, or 0 if there is no keyboard event.
1964
1965                For CSOUND_CALLBACK_KBD_EVENT, both key press and release
1966                events should be returned (with 65536 (0x10000) added to the
1967                key code in the latter case) as unshifted ASCII codes.
1968                CSOUND_CALLBACK_KBD_TEXT expects key press events only as the
1969                actual text that is typed.
1970
1971        The return value should be zero on success, negative on error, and
1972        positive if the callback was ignored (for example because the type is
1973        not known).
1974        """
1975        if type_ == CSOUND_CALLBACK_KBD_EVENT:
1976            self.keyboardCbEventRef = KEYBOARDFUNC(function)
1977        else:
1978            self.keyboardCbTextRef = KEYBOARDFUNC(function)
1979        return libcsound.csoundRegisterKeyboardCallback(self.cs, KEYBOARDFUNC(function), ct.py_object(userData), ct.c_uint(type_))
1980
1981    def removeKeyboardCallback(self, function):
1982        """Removes a callback previously set with :py:meth:`registerKeyboardCallback()`."""
1983        libcsound.csoundRemoveKeyboardCallback(self.cs, KEYBOARDFUNC(function))
1984
1985    #Tables
1986    def tableLength(self, table):
1987        """Returns the length of a function table.
1988
1989        (Not including the guard point).
1990        If the table does not exist, returns -1.
1991        """
1992        return libcsound.csoundTableLength(self.cs, table)
1993
1994    def tableGet(self, table, index):
1995        """Returns the value of a slot in a function table.
1996
1997        The *table* number and *index* are assumed to be valid.
1998        """
1999        return libcsound.csoundTableGet(self.cs, table, index)
2000
2001    def tableSet(self, table, index, value):
2002        """Sets the value of a slot in a function table.
2003
2004        The *table* number and *index* are assumed to be valid.
2005        """
2006        libcsound.csoundTableSet(self.cs, table, index, MYFLT(value))
2007
2008    def tableCopyOut(self, table, dest):
2009        """Copies the contents of a function table into a supplied ndarray *dest*.
2010
2011        The *table* number is assumed to be valid, and the destination needs to
2012        have sufficient space to receive all the function table contents.
2013        """
2014        ptr = dest.ctypes.data_as(ct.POINTER(MYFLT))
2015        libcsound.csoundTableCopyOut(self.cs, table, ptr)
2016
2017    def tableCopyOutAsync(self, table, dest):
2018        """Asynchronous version of :py:meth:`tableCopyOut()`."""
2019        ptr = dest.ctypes.data_as(ct.POINTER(MYFLT))
2020        libcsound.csoundTableCopyOutAsync(self.cs, table, ptr)
2021
2022    def tableCopyIn(self, table, src):
2023        """Copies the contents of an ndarray *src* into a given function *table*.
2024
2025        The *table* number is assumed to be valid, and the table needs to
2026        have sufficient space to receive all the array contents.
2027        """
2028        ptr = src.ctypes.data_as(ct.POINTER(MYFLT))
2029        libcsound.csoundTableCopyIn(self.cs, table, ptr)
2030
2031    def tableCopyInAsync(self, table, src):
2032        """Asynchronous version of :py:meth:`tableCopyIn()`."""
2033        ptr = src.ctypes.data_as(ct.POINTER(MYFLT))
2034        libcsound.csoundTableCopyInAsync(self.cs, table, ptr)
2035
2036    def table(self, tableNum):
2037        """Returns a pointer to function table *tableNum* as an ndarray.
2038
2039        The ndarray does not include the guard point. If the table does not
2040        exist, :code:`None` is returned.
2041        """
2042        ptr = ct.POINTER(MYFLT)()
2043        size = libcsound.csoundGetTable(self.cs, ct.byref(ptr), tableNum)
2044        if size < 0:
2045            return None
2046        arrayType = np.ctypeslib.ndpointer(MYFLT, 1, (size,), 'C_CONTIGUOUS')
2047        p = ct.cast(ptr, arrayType)
2048        return arrFromPointer(p)
2049
2050    def tableArgs(self, tableNum):
2051        """Returns a pointer to the args used to generate a function table.
2052
2053        The pointer is returned as an ndarray. If the table does not exist,
2054        :code:`None` is returned.
2055
2056        NB: the argument list starts with the GEN number and is followed by
2057        its parameters. eg. f 1 0 1024 10 1 0.5  yields the list
2058        {10.0, 1.0, 0.5}
2059        """
2060        ptr = ct.POINTER(MYFLT)()
2061        size = libcsound.csoundGetTableArgs(self.cs, ct.byref(ptr), tableNum)
2062        if size < 0:
2063            return None
2064        arrayType = np.ctypeslib.ndpointer(MYFLT, 1, (size,), 'C_CONTIGUOUS')
2065        p = ct.cast(ptr, arrayType)
2066        return arrFromPointer(p)
2067
2068    def isNamedGEN(self, num):
2069        """Checks if a given GEN number *num* is a named GEN.
2070
2071        If so, it returns the string length. Otherwise it returns 0.
2072        """
2073        return libcsound.csoundIsNamedGEN(self.cs, num)
2074
2075    def namedGEN(self, num, nameLen):
2076        """Gets the GEN name from a GEN number, if this is a named GEN.
2077
2078        The final parameter is the max len of the string.
2079        """
2080        s = ct.create_string_buffer(nameLen)
2081        libcsound.csoundGetNamedGEN(self.cs, num, s, nameLen)
2082        return pstring(string_at(s, nameLen))
2083
2084    #Function Table Display
2085    def setIsGraphable(self, isGraphable):
2086        """Tells Csound whether external graphic table display is supported.
2087
2088        Return the previously set value (initially False).
2089        """
2090        ret = libcsound.csoundSetIsGraphable(self.cs, ct.c_int(isGraphable))
2091        return (ret != 0)
2092
2093    def setMakeGraphCallback(self, function):
2094        """Called by external software to set Csound's MakeGraph function."""
2095        self.makeGraphCbRef = MAKEGRAPHFUNC(function)
2096        libcsound.csoundSetMakeGraphCallback(self.cs, self.makeGraphCbRef)
2097
2098    def setDrawGraphCallback(self, function):
2099        """Called by external software to set Csound's DrawGraph function."""
2100        self.drawGraphCbRef = DRAWGRAPHFUNC(function)
2101        libcsound.csoundSetDrawGraphCallback(self.cs, self.drawGraphCbRef)
2102
2103    def setKillGraphCallback(self, function):
2104        """Called by external software to set Csound's KillGraph function."""
2105        self.killGraphCbRef = KILLGRAPHFUNC(function)
2106        libcsound.csoundSetKillGraphCallback(self.cs, self.killGraphCbRef)
2107
2108    def setExitGraphCallback(self, function):
2109        """Called by external software to set Csound's ExitGraph function."""
2110        self.exitGraphCbRef = EXITGRAPHFUNC(function)
2111        libcsound.csoundSetExitGraphCallback(self.cs, self.exitGraphCbRef)
2112
2113    #Opcodes
2114    def namedGens(self):
2115        """Finds the list of named gens."""
2116        lst = []
2117        ptr = libcsound.csoundGetNamedGens(self.cs)
2118        ptr = ct.cast(ptr, ct.POINTER(NamedGen))
2119        while (ptr):
2120            ng = ptr.contents
2121            lst.append((pstring(ng.name), int(ng.genum)))
2122            ptr = ng.next
2123        return lst
2124
2125    def newOpcodeList(self):
2126        """Gets an alphabetically sorted list of all opcodes.
2127
2128        Should be called after externals are loaded by :py:meth:`compile_()`.
2129        Returns a pointer to the list of OpcodeListEntry structures and the
2130        number of opcodes, or a negative error code on  failure.
2131        Make sure to call :py:meth:`disposeOpcodeList()` when done with the
2132        list.
2133        """
2134        opcodes = None
2135        ptr = ct.cast(ct.POINTER(ct.c_int)(), ct.POINTER(OpcodeListEntry))
2136        n = libcsound.csoundNewOpcodeList(self.cs, ct.byref(ptr))
2137        if n > 0:
2138            opcodes = ct.cast(ptr, ct.POINTER(OpcodeListEntry * n)).contents
2139        return opcodes, n
2140
2141    def disposeOpcodeList(self, lst):
2142        """Releases an opcode list."""
2143        ptr = ct.cast(lst, ct.POINTER(OpcodeListEntry))
2144        libcsound.csoundDisposeOpcodeList(self.cs, ptr)
2145
2146    def appendOpcode(self, opname, dsblksiz, flags, thread, outypes, intypes, iopfunc, kopfunc, aopfunc):
2147        """Appends an opcode implemented by external software.
2148
2149        This opcode is added to Csound's internal opcode list.
2150        The opcode list is extended by one slot, and the parameters are copied
2151        into the new slot.
2152
2153        Returns zero on success.
2154        """
2155        return libcsound.csoundAppendOpcode(self.cs, cstring(opname), dsblksiz, flags, thread,\
2156                                            cstring(outypes), cstring(intypes),\
2157                                            OPCODEFUNC(iopfunc),\
2158                                            OPCODEFUNC(kopfunc),
2159                                            OPCODEFUNC(aopfunc))
2160
2161    #Threading and Concurrency
2162    def setYieldCallback(self, function):
2163        """
2164        Called by external software to set a yield function.
2165
2166        This callback is used for checking system events, yielding cpu time
2167        for coopertative multitasking, etc.
2168
2169        This function is optional. It is often used as a way to 'turn off'
2170        Csound, allowing it to exit gracefully. In addition, some operations
2171        like utility analysis routines are not reentrant and you should use
2172        this function to do any kind of updating during the operation.
2173
2174        Returns an 'OK to continue' boolean.
2175        """
2176        self.yieldCbRef = YIELDFUNC(function)
2177        libcsound.csoundSetYieldCallback(self.cs, self.yieldCbRef)
2178
2179    def createThread(self, function, userdata):
2180        """Creates and starts a new thread of execution.
2181
2182        Returns an opaque pointer that represents the thread on success,
2183        or :code:`None` for failure.
2184        The *userdata* pointer is passed to the thread routine.
2185        """
2186        ret = libcsound.csoundCreateThread(THREADFUNC(function), ct.py_object(userdata))
2187        if (ret):
2188            return ret
2189        return None
2190
2191    def currentThreadId(self):
2192        """Returns the ID of the currently executing thread, or :code:`None`
2193        for failure.
2194
2195        NOTE: The return value can be used as a pointer
2196        to a thread object, but it should not be compared
2197        as a pointer. The pointed to values should be compared,
2198        and the user must free the pointer after use.
2199        """
2200        ret = libcsound.csoundGetCurrentThreadId()
2201        if (ret):
2202            return ret
2203        return None
2204
2205    def joinThread(self, thread):
2206        """Waits until the indicated thread's routine has finished.
2207
2208        Returns the value returned by the thread routine.
2209        """
2210        return libcsound.csoundJoinThread(thread)
2211
2212    def createThreadLock(self):
2213        """Creates and returns a monitor object, or :code:`None` if not successful.
2214
2215        The object is initially in signaled (notified) state.
2216        """
2217        ret = libcsound.csoundCreateThreadLock()
2218        if (ret):
2219            return ret
2220        return None
2221
2222    def waitThreadLock(self, lock, milliseconds):
2223        """Waits on the indicated monitor object for the indicated period.
2224
2225        The function returns either when the monitor object is notified,
2226        or when the period has elapsed, whichever is sooner; in the first case,
2227        zero is returned.
2228
2229        If *milliseconds* is zero and the object is not notified, the function
2230        will return immediately with a non-zero status.
2231        """
2232        return libcsound.csoundWaitThreadLock(lock, ct.c_uint(milliseconds))
2233
2234    def waitThreadLockNoTimeout(self, lock):
2235        """Waits on the indicated monitor object until it is notified.
2236
2237        This function is similar to :py:meth:`waitThreadLock()` with an infinite
2238        wait time, but may be more efficient.
2239        """
2240        libcsound.csoundWaitThreadLockNoTimeout(lock)
2241
2242    def notifyThreadLock(self, lock):
2243        """Notifies the indicated monitor object."""
2244        libcsound.csoundNotifyThreadLock(lock)
2245
2246    def destroyThreadLock(self, lock):
2247        """Destroys the indicated monitor object."""
2248        libcsound.csoundDestroyThreadLock(lock)
2249
2250    def createMutex(self, isRecursive):
2251        """Creates and returns a mutex object, or :code:`None` if not successful.
2252
2253        Mutexes can be faster than the more general purpose monitor objects
2254        returned by :py:meth:`createThreadLock()` on some platforms, and can
2255        also be recursive, but the result of unlocking a mutex that is owned by
2256        another thread or is not locked is undefined.
2257
2258        If *isRecursive'* id :code:`True`, the mutex can be re-locked multiple
2259        times by the same thread, requiring an equal number of unlock calls;
2260        otherwise, attempting to re-lock the mutex results in undefined
2261        behavior.
2262
2263        Note: the handles returned by :py:meth:`createThreadLock()` and
2264        :py:meth:`createMutex()` are not compatible.
2265        """
2266        ret = libcsound.csoundCreateMutex(ct.c_int(isRecursive))
2267        if ret:
2268            return ret
2269        return None
2270
2271    def lockMutex(self, mutex):
2272        """Acquires the indicated mutex object.
2273
2274        If it is already in use by another thread, the function waits until
2275        the mutex is released by the other thread.
2276        """
2277        libcsound.csoundLockMutex(mutex)
2278
2279    def lockMutexNoWait(self, mutex):
2280        """Acquire the indicated mutex object.
2281
2282        Returns zero, unless it is already in use by another thread, in which
2283        case a non-zero value is returned immediately, rather than waiting
2284        until the mutex becomes available.
2285
2286        Note: this function may be unimplemented on Windows.
2287        """
2288        return libcsound.csoundLockMutexNoWait(mutex)
2289
2290    def unlockMutex(self, mutex):
2291        """Releases the indicated mutex object.
2292
2293        The mutex should be owned by the current thread, otherwise the
2294        operation of this function is undefined. A recursive mutex needs
2295        to be unlocked as many times as it was locked previously.
2296        """
2297        libcsound.csoundUnlockMutex(mutex)
2298
2299    def destroyMutex(self, mutex):
2300        """Destroys the indicated mutex object.
2301
2302        Destroying a mutex that is currently owned by a thread results
2303        in undefined behavior.
2304        """
2305        libcsound.csoundDestroyMutex(mutex)
2306
2307    def createBarrier(self, max_):
2308        """Creates a Thread Barrier.
2309
2310        Max value parameter should be equal to the number of child threads
2311        using the barrier plus one for the master thread.
2312        """
2313        ret = libcsound.csoundCreateBarrier(ct.c_uint(max_))
2314        if (ret):
2315            return ret
2316        return None
2317
2318    def destroyBarrier(self, barrier):
2319        """Destroys a Thread Barrier."""
2320        return libcsound.csoundDestroyBarrier(barrier)
2321
2322    def waitBarrier(self, barrier):
2323        """Waits on the thread barrier."""
2324        return libcsound.csoundWaitBarrier(barrier)
2325
2326    #def createCondVar(self):
2327    #def condWait(self, condVar, mutex):
2328    #def condSignal(self, condVar):
2329    #def destroyCondVar(self, condVar):
2330
2331    def sleep(self, milliseconds):
2332        """Waits for at least the specified number of *milliseconds*.
2333
2334        It yields the CPU to other threads.
2335        """
2336        libcsound.csoundSleep(ct.c_uint(milliseconds))
2337
2338    def spinLockInit(self, spinlock):
2339        """Inits the spinlock.
2340
2341        If the spinlock is not locked, locks it and returns;
2342        if is is locked, waits until it is unlocked, then locks it and returns.
2343        Uses atomic compare and swap operations that are safe across processors
2344        and safe for out of order operations,
2345        and which are more efficient than operating system locks.
2346
2347        Use spinlocks to protect access to shared data, especially in functions
2348        that do little more than read or write such data, for example::
2349
2350            lock = ctypes.ct.c_int32(0)
2351            cs.spinLockInit(lock)
2352            def write(cs, frames, signal):
2353                cs.spinLock(lock)
2354                for frame in range(frames) :
2355                    global_buffer[frame] += signal[frame];
2356                cs.spinUnlock(lock)
2357        """
2358        return libcsound.csoundSpinLockInit(ct.byref(spinlock))
2359
2360    def spinLock(self, spinlock):
2361        """Locks the spinlock."""
2362        libcsound.csoundSpinLock(ct.byref(spinlock))
2363
2364    def spinTryLock(self,spinlock):
2365        """Tries the spinlock.
2366
2367        returns CSOUND_SUCCESS if lock could be acquired,
2368        CSOUND_ERROR, otherwise.
2369        """
2370        return libcsound.csoundSpinLock(ct.byref(spinlock))
2371
2372    def spinUnlock(self, spinlock):
2373        """Unlocks the spinlock."""
2374        libcsound.csoundSpinUnLock(ct.byref(spinlock))
2375
2376    #Miscellaneous Functions
2377    def runCommand(self, args, noWait):
2378        """Runs an external command with the arguments specified in list *args*.
2379
2380        args[0] is the name of the program to execute (if not a full path
2381        file name, it is searched in the directories defined by the PATH
2382        environment variable).
2383
2384        If *noWait* is :code:`False`, the function waits until the external
2385        program finishes, otherwise it returns immediately. In the first case,
2386        a non-negative return value is the exit status of the command (0 to
2387        255), otherwise it is the PID of the newly created process.
2388        On error, a negative value is returned.
2389        """
2390        n = len(args)
2391        argv = (ct.POINTER(ct.c_char_p) * (n+1))()
2392        for i in range(n):
2393            v = cstring(args[i])
2394            argv[i] = ct.cast(ct.pointer(ct.create_string_buffer(v)), ct.POINTER(ct.c_char_p))
2395        argv[n] = None
2396        return libcsound.csoundRunCommand(ct.cast(argv, ct.POINTER(ct.c_char_p)), ct.c_int(noWait))
2397
2398    def initTimerStruct(self, timerStruct):
2399        """Initializes a timer structure."""
2400        libcsound.csoundInitTimerStruct(ct.byref(timerStruct))
2401
2402    def realTime(self, timerStruct):
2403        """Returns the elapsed real time (in seconds).
2404
2405        The time is measured since the specified timer structure was initialised.
2406        """
2407        return libcsound.csoundGetRealTime(ct.byref(timerStruct))
2408
2409    def CPUTime(self, timerStruct):
2410        """Returns the elapsed CPU time (in seconds).
2411
2412        The time is measured since the specified timer structure was initialised.
2413        """
2414        return libcsound.csoundGetCPUTime(ct.byref(timerStruct))
2415
2416    def randomSeedFromTime(self):
2417        """Returns a 32-bit unsigned integer to be used as seed from current time."""
2418        return libcsound.csoundGetRandomSeedFromTime()
2419
2420    def setLanguage(self, lang_code):
2421        """Sets language to *lang_code*.
2422
2423        *lang_code* can be for example CSLANGUAGE_ENGLISH_UK or
2424        CSLANGUAGE_FRENCH or many others, (see n_getstr.h for the list of
2425        languages). This affects all Csound instances running in the address
2426        space of the current process. The special language code
2427        CSLANGUAGE_DEFAULT can be used to disable translation of messages and
2428        free all memory allocated by a previous call to setLanguage().
2429        setLanguage() loads all files for the selected language
2430        from the directory specified by the CSSTRNGS environment
2431        variable.
2432        """
2433        libcsound.csoundSetLanguage(lang_code)
2434
2435    def env(self, name, withCsoundInstance = True):
2436        """Gets the value of environment variable *name*.
2437
2438        The searching order is: local environment of Csound (if
2439        *withCsoundInstance* is :code:`True`), variables set with
2440        :py:meth:`setGlobalEnv()`,
2441        and system environment variables. If *withCsoundInstance* is
2442        :code:`True`, should be called after :py:meth:`compile_()`.
2443
2444        Return value is :code:`None` if the variable is not set.
2445        """
2446        if withCsoundInstance:
2447            ret = libcsound.csoundGetEnv(self.cs, cstring(name))
2448        else:
2449            ret = libcsound.csoundGetEnv(None, cstring(name))
2450        if (ret):
2451            return pstring(ret)
2452        return None
2453
2454    def setGlobalEnv(self, name, value):
2455        """Sets the global value of environment variable *name* to *value*.
2456
2457        The variable is deleted if *value* is :code:`None`. It is not safe to
2458        call this function while any Csound instances are active.
2459
2460        Returns zero on success.
2461        """
2462        return libcsound.csoundSetGlobalEnv(cstring(name), cstring(value))
2463
2464    def createGlobalVariable(self, name, nbytes):
2465        """Allocates *nbytes* bytes of memory.
2466
2467        This memory can be accessed later by calling
2468        :py:meth`queryGlobalVariable()` with the specified name; the space is
2469        cleared to zero.
2470
2471        Returns CSOUND_SUCCESS on success, CSOUND_ERROR in case of invalid
2472        parameters (zero *nbytes*, invalid or already used *name*), or
2473        CSOUND_MEMORY if there is not enough memory.
2474        """
2475        return libcsound.csoundCreateGlobalVariable(self.cs, cstring(name), ct.c_uint(nbytes))
2476
2477    def queryGlobalVariable(self, name):
2478        """Gets pointer to space allocated with the name *name*.
2479
2480        Return :code:`None` if the specified *name* is not defined.
2481        """
2482        ret = libcsound.csoundQueryGlobalVariable(self.cs, cstring(name))
2483        if (ret):
2484            return ret
2485        return None
2486
2487    def queryGlobalVariableNoCheck(self, name):
2488        """This function is the similar to :py:meth`queryGlobalVariable()`.
2489
2490        Except the variable is assumed to exist and no error checking is done.
2491        Faster, but may crash or return an invalid pointer if *name* is
2492        not defined.
2493        """
2494        return libcsound.csoundQueryGlobalVariableNoCheck(self.cs, cstring(name))
2495
2496    def destroyGlobalVariable(self, name):
2497        """Frees memory allocated for *name* and remove *name* from the database.
2498
2499        Return value is CSOUND_SUCCESS on success, or CSOUND_ERROR if the *name*
2500        is not defined.
2501        """
2502        return libcsound.csoundDestroyGlobalVariable(self.cs, cstring(name))
2503
2504    def runUtility(self, name, args):
2505        """Runs utility with the specified *name* and command line arguments.
2506
2507        Should be called after loading utility plugins.
2508        Use :py:meth`reset()` to clean up after calling this function.
2509        Returns zero if the utility was run successfully.
2510        """
2511        argc, argv = csoundArgList(args)
2512        return libcsound.csoundRunUtility(self.cs, cstring(name), argc, argv)
2513
2514    def listUtilities(self):
2515        """Returns a list of registered utility names.
2516
2517        The return value may be :code:`None` in case of an error.
2518        """
2519        ptr = libcsound.csoundListUtilities(self.cs)
2520        if (ptr):
2521            i = 0
2522            lst = []
2523            while (ptr[i]):
2524                lst.append(pstring(ptr[i]))
2525                i += 1
2526            libcsound.csoundDeleteUtilityList(self.cs, ptr)
2527            return lst
2528        return None
2529
2530    def utilityDescription(self, name):
2531        """Gets utility description.
2532
2533        Returns :code:`None` if the utility was not found, or it has no
2534        description, or an error occured.
2535        """
2536        ptr = libcsound.csoundGetUtilityDescription(self.cs, cstring(name))
2537        if (ptr):
2538            return pstring(ptr)
2539        return None
2540
2541    def rand31(self, seed):
2542        """Simple linear congruential random number generator::
2543
2544            seed = seed * 742938285 % 2147483647
2545
2546        The initial value of *seed* must be in the range 1 to 2147483646.
2547        Returns the next number from the pseudo-random sequence, in the range
2548        1 to 2147483646.
2549        """
2550        n = ct.c_int(seed)
2551        return libcsound.csoundRand31(ct.byref(n))
2552
2553    def seedRandMT(self, initKey):
2554        """Initializes Mersenne Twister (MT19937) random number generator.
2555
2556        *initKey* can be a single int, a list of int, or an ndarray of int.
2557        Those int values are converted to unsigned 32 bit values and used for
2558        seeding.
2559
2560        Returns a CsoundRandMTState stuct to be used by :py:meth`csoundRandMT()`.
2561        """
2562        state = CsoundRandMTState()
2563        if type(initKey) == int:
2564            if initKey < 0:
2565                initKey = -initKey
2566            libcsound.csoundSeedRandMT(ct.byref(state), None, ct.c_uint32(initKey))
2567        elif type(initKey) == list or type(initKey) == np.ndarray:
2568            n = len(initKey)
2569            lst = (ct.c_uint32 * n)()
2570            for i in range(n):
2571                k = initKey[i]
2572                if k < 0 :
2573                    k = -k
2574                lst[i] = ct.c_uint32(k)
2575            p = ct.pointer(lst)
2576            p = ct.cast(p, ct.POINTER(ct.c_uint32))
2577            libcsound.csoundSeedRandMT(ct.byref(state), p, ct.c_uint32(len(lst)))
2578        return state
2579
2580    def randMT(self, state):
2581        """Returns next random number from MT19937 generator.
2582
2583        The PRNG must be initialized first by calling :py:meth`csoundSeedRandMT()`.
2584        """
2585        return libcsound.csoundRandMT(ct.byref(state))
2586
2587    def createCircularBuffer(self, numelem, elemsize):
2588        """Creates a circular buffer with *numelem* number of elements.
2589
2590        The element's size is set from *elemsize*. It should be used like::
2591
2592            rb = cs.createCircularBuffer(1024, cs.sizeOfMYFLT())
2593        """
2594        return libcsound.csoundCreateCircularBuffer(self.cs, numelem, elemsize)
2595
2596    def readCircularBuffer(self, circularBuffer, out, items):
2597        """Reads from circular buffer.
2598
2599        *circular_buffer*
2600            pointer to an existing circular buffer
2601        *out*
2602            preallocated ndarray with at least items number of elements,
2603            where buffer contents will be read into
2604        *items*
2605            number of samples to be read
2606
2607        Returns the actual number of items read (0 <= n <= items).
2608        """
2609        if len(out) < items:
2610            return 0
2611        ptr = out.ctypes.data_as(ct.c_void_p)
2612        return libcsound.csoundReadCircularBuffer(self.cs, circularBuffer, ptr, items)
2613
2614    def peekCircularBuffer(self, circularBuffer, out, items):
2615        """Reads from circular buffer without removing them from the buffer.
2616
2617        *circular_buffer*
2618            pointer to an existing circular buffer
2619        *out*
2620            preallocated ndarray with at least items number of elements,
2621            where buffer contents will be read into
2622        *items*
2623            number of samples to be read
2624
2625        Returns the actual number of items read (0 <= n <= items).
2626        """
2627        if len(out) < items:
2628            return 0
2629        ptr = out.ctypes.data_as(ct.c_void_p)
2630        return libcsound.csoundPeekCircularBuffer(self.cs, circularBuffer, ptr, items)
2631
2632    def writeCircularBuffer(self, circularBuffer, in_, items):
2633        """Writes to circular buffer.
2634
2635        *circular_buffer*
2636            pointer to an existing circular buffer
2637        *in_*
2638            ndarray with at least items number of elements to be written
2639            into circular buffer
2640        *items*
2641            number of samples to write
2642
2643        Returns the actual number of items written (0 <= n <= items).
2644        """
2645        if len(in_) < items:
2646            return 0
2647        ptr = in_.ctypes.data_as(ct.c_void_p)
2648        return libcsound.csoundWriteCircularBuffer(self.cs, circularBuffer, ptr, items)
2649
2650    def flushCircularBuffer(self, circularBuffer):
2651        """Empties circular buffer of any remaining data.
2652
2653        This function should only be used if there is no reader actively
2654        getting data from the buffer.
2655
2656        *circular_buffer*
2657            pointer to an existing circular buffer
2658        """
2659        libcsound.csoundFlushCircularBuffer(self.cs, circularBuffer)
2660
2661    def destroyCircularBuffer(self, circularBuffer):
2662        """Frees circular buffer."""
2663        libcsound.csoundDestroyCircularBuffer(self.cs, circularBuffer)
2664
2665    def openLibrary(self, libraryPath):
2666        """Platform-independent function to load a shared library."""
2667        ptr = ct.POINTER(ct.c_int)()
2668        library = ct.cast(ptr, ct.c_void_p)
2669        ret = libcsound.csoundOpenLibrary(ct.byref(library), cstring(libraryPath))
2670        return ret, library
2671
2672    def closeLibrary(self, library):
2673        """Platform-independent function to unload a shared library."""
2674        return libcsound.csoundCloseLibrary(library)
2675
2676    def getLibrarySymbol(self, library, symbolName):
2677        """Platform-independent function to get a symbol address in a shared library."""
2678        return libcsound.csoundGetLibrarySymbol(library, cstring(symbolName))
2679
2680
2681if sys.platform.startswith('linux'):
2682    libcspt = ct.CDLL("libcsnd6.so")
2683elif sys.platform.startswith('win'):
2684    if sys.version_info.major <=3 and sys.version_info.minor < 8:
2685        libcspt = ct.cdll.csnd6
2686    else:
2687        libcspt = ct.CDLL(ctypes.util.find_library("csnd6"))
2688elif sys.platform.startswith('darwin'):
2689    libcspt = ct.CDLL("libcsnd6.6.0.dylib")
2690else:
2691    sys.exit("Don't know your system! Exiting...")
2692
2693libcspt.NewCsoundPT.restype = ct.c_void_p
2694libcspt.NewCsoundPT.argtypes = [ct.c_void_p]
2695libcspt.DeleteCsoundPT.argtypes = [ct.c_void_p]
2696libcspt.CsoundPTisRunning.argtypes = [ct.c_void_p]
2697PROCESSFUNC = ct.CFUNCTYPE(None, ct.c_void_p)
2698libcspt.CsoundPTgetProcessCB.restype = ct.c_void_p
2699libcspt.CsoundPTgetProcessCB.argtypes = [ct.c_void_p]
2700libcspt.CsoundPTsetProcessCB.argtypes = [ct.c_void_p, PROCESSFUNC, ct.c_void_p]
2701libcspt.CsoundPTgetCsound.restype = ct.c_void_p
2702libcspt.CsoundPTgetCsound.argtypes = [ct.c_void_p]
2703libcspt.CsoundPTgetStatus.argtypes = [ct.c_void_p]
2704libcspt.CsoundPTplay.argtypes = [ct.c_void_p]
2705libcspt.CsoundPTpause.argtypes = [ct.c_void_p]
2706libcspt.CsoundPTtogglePause.argtypes = [ct.c_void_p]
2707libcspt.CsoundPTstop.argtypes = [ct.c_void_p]
2708libcspt.CsoundPTrecord.argtypes = [ct.c_void_p, ct.c_char_p, ct.c_int, ct.c_int]
2709libcspt.CsoundPTstopRecord.argtypes = [ct.c_void_p]
2710libcspt.CsoundPTscoreEvent.argtypes = [ct.c_void_p, ct.c_int, ct.c_char, ct.c_int, ct.POINTER(MYFLT)]
2711libcspt.CsoundPTinputMessage.argtypes = [ct.c_void_p, ct.c_char_p]
2712libcspt.CsoundPTsetScoreOffsetSeconds.argtypes = [ct.c_void_p, ct.c_double]
2713libcspt.CsoundPTjoin.argtypes = [ct.c_void_p]
2714libcspt.CsoundPTflushMessageQueue.argtypes = [ct.c_void_p]
2715
2716
2717class CsoundPerformanceThread:
2718    """Performs a score in a separate thread until the end of score is reached.
2719
2720    The playback (which is paused by default) is stopped by calling
2721    :py:meth:`stop()`, or if an error occurs.
2722    The constructor takes a Csound instance pointer as argument; it assumes
2723    that :py:meth:`ctcsound.compile_()` was called successfully before creating
2724    the performance thread. Once the playback is stopped for one of the above
2725    mentioned reasons, the performance thread calls :py:meth:`ctcsound.cleanup()`
2726    and returns.
2727    """
2728    def __init__(self, csp):
2729        self.cpt = libcspt.NewCsoundPT(csp)
2730
2731    def __del__(self):
2732        libcspt.DeleteCsoundPT(self.cpt)
2733
2734    def isRunning(self):
2735        """Returns :code:`True` if the performance thread is running, :code:`False` otherwise."""
2736        return libcspt.CsoundPTisRunning(self.cpt) != 0
2737
2738    def processCB(self):
2739        """Returns the process callback."""
2740        return PROCESSFUNC(libcspt.CsoundPTgetProcessCB(self.cpt))
2741
2742    def setProcessCB(self, function, data):
2743        """Sets the process callback."""
2744        libcspt.CsoundPTsetProcessCB(self.cpt, PROCESSFUNC(function), ct.byref(data))
2745
2746    def csound(self):
2747        """Returns the Csound instance pointer."""
2748        return libcspt.CsoundPTgetCsound(self.cpt)
2749
2750    def status(self):
2751        """Returns the current status.
2752
2753        Zero if still playing, positive if the end of score was reached or
2754        performance was stopped, and negative if an error occured.
2755        """
2756        return libcspt.CsoundPTgetStatus(self.cpt)
2757
2758    def play(self):
2759        """Continues performance if it was paused."""
2760        libcspt.CsoundPTplay(self.cpt)
2761
2762    def pause(self):
2763        """Pauses performance (can be continued by calling :py:meth:`play()`)."""
2764        libcspt.CsoundPTpause(self.cpt)
2765
2766    def togglePause(self):
2767        """Pauses or continues performance, depending on current state."""
2768        libcspt.CsoundPTtogglePause(self.cpt)
2769
2770    def stop(self):
2771        """Stops performance (cannot be continued)."""
2772        libcspt.CsoundPTstop(self.cpt)
2773
2774    def record(self, filename, samplebits, numbufs):
2775        """Starts recording the output from Csound.
2776
2777        The sample rate and number of channels are taken directly from the
2778        running Csound instance.
2779        """
2780        libcspt.CsoundPTrecord(self.cpt, cstring(filename), samplebits, numbufs)
2781
2782    def stopRecord(self):
2783        """Stops recording and closes audio file."""
2784        libcspt.CsoundPTstopRecord(self.cpt)
2785
2786    def scoreEvent(self, absp2mode, opcod, pFields):
2787        """Sends a score event.
2788
2789        The event has type *opcod* (e.g. 'i' for a note event).
2790        *pFields* is tuple, a list, or an ndarray of MYFLTs with all the pfields
2791        for this event, starting with the p1 value specified in *pFields[0]*.
2792        If *absp2mode* is non-zero, the start time of the event is measured
2793        from the beginning of performance, instead of the default of relative
2794        to the current time.
2795        """
2796        p = np.array(pFields).astype(MYFLT)
2797        ptr = p.ctypes.data_as(ct.POINTER(MYFLT))
2798        numFields = p.size
2799        libcspt.CsoundPTscoreEvent(self.cpt, ct.c_int(absp2mode), cchar(opcod), numFields, ptr)
2800
2801    def inputMessage(self, s):
2802        """Sends a score event as a string, similarly to line events (-L)."""
2803        libcspt.CsoundPTinputMessage(self.cpt, cstring(s))
2804
2805    def setScoreOffsetSeconds(self, timeVal):
2806        """Sets the playback time pointer to the specified value (in seconds)."""
2807        libcspt.CsoundPTsetScoreOffsetSeconds(self.cpt, ct.c_double(timeVal))
2808
2809    def join(self):
2810        """Waits until the performance is finished or fails.
2811
2812        Returns a positive value if the end of score was reached or
2813        :py:meth:`stop()` was called, and a negative value if an error occured.
2814        Also releases any resources associated with the performance thread
2815        object.
2816        """
2817        return libcspt.CsoundPTjoin(self.cpt)
2818
2819    def flushMessageQueue(self):
2820        """Waits until all pending messages are actually received.
2821
2822        (pause, send score event, etc.)
2823        """
2824        libcspt.CsoundPTflushMessageQueue(self.cpt)
2825
2826