xref: /aosp_15_r20/external/sonivox/jet_tools/JetCreator/eas.py (revision f81fb7c475c4b71ff83bdcc517de2a8c174e4e5c)
1*f81fb7c4SAndroid Build Coastguard Worker
2*f81fb7c4SAndroid Build Coastguard Workerfrom __future__ import with_statement
3*f81fb7c4SAndroid Build Coastguard Worker
4*f81fb7c4SAndroid Build Coastguard Workerimport threading
5*f81fb7c4SAndroid Build Coastguard Workerimport logging
6*f81fb7c4SAndroid Build Coastguard Workerimport time
7*f81fb7c4SAndroid Build Coastguard Workerfrom ctypes import *
8*f81fb7c4SAndroid Build Coastguard Workerfrom JetUtils import OsWindows
9*f81fb7c4SAndroid Build Coastguard Worker
10*f81fb7c4SAndroid Build Coastguard Worker
11*f81fb7c4SAndroid Build Coastguard Worker# stream state
12*f81fb7c4SAndroid Build Coastguard WorkerEAS_STATE_READY = 0
13*f81fb7c4SAndroid Build Coastguard WorkerEAS_STATE_PLAY = 1
14*f81fb7c4SAndroid Build Coastguard WorkerEAS_STATE_STOPPING = 2
15*f81fb7c4SAndroid Build Coastguard WorkerEAS_STATE_PAUSING = 3
16*f81fb7c4SAndroid Build Coastguard WorkerEAS_STATE_STOPPED = 4
17*f81fb7c4SAndroid Build Coastguard WorkerEAS_STATE_PAUSED = 5
18*f81fb7c4SAndroid Build Coastguard WorkerEAS_STATE_OPEN = 6
19*f81fb7c4SAndroid Build Coastguard WorkerEAS_STATE_ERROR = 7
20*f81fb7c4SAndroid Build Coastguard WorkerEAS_STATE_EMPTY = 8
21*f81fb7c4SAndroid Build Coastguard Worker
22*f81fb7c4SAndroid Build Coastguard Worker# EAS error codes
23*f81fb7c4SAndroid Build Coastguard WorkerEAS_SUCCESS	= 0
24*f81fb7c4SAndroid Build Coastguard WorkerEAS_FAILURE = -1
25*f81fb7c4SAndroid Build Coastguard WorkerEAS_ERROR_INVALID_MODULE = -2
26*f81fb7c4SAndroid Build Coastguard WorkerEAS_ERROR_MALLOC_FAILED = -3
27*f81fb7c4SAndroid Build Coastguard WorkerEAS_ERROR_FILE_POS = -4
28*f81fb7c4SAndroid Build Coastguard WorkerEAS_ERROR_INVALID_FILE_MODE = -5
29*f81fb7c4SAndroid Build Coastguard WorkerEAS_ERROR_FILE_SEEK = -6
30*f81fb7c4SAndroid Build Coastguard WorkerEAS_ERROR_FILE_LENGTH = -7
31*f81fb7c4SAndroid Build Coastguard WorkerEAS_ERROR_NOT_IMPLEMENTED = -8
32*f81fb7c4SAndroid Build Coastguard WorkerEAS_ERROR_CLOSE_FAILED = -9
33*f81fb7c4SAndroid Build Coastguard WorkerEAS_ERROR_FILE_OPEN_FAILED = -10
34*f81fb7c4SAndroid Build Coastguard WorkerEAS_ERROR_INVALID_HANDLE = -11
35*f81fb7c4SAndroid Build Coastguard WorkerEAS_ERROR_NO_MIX_BUFFER = -12
36*f81fb7c4SAndroid Build Coastguard WorkerEAS_ERROR_PARAMETER_RANGE = -13
37*f81fb7c4SAndroid Build Coastguard WorkerEAS_ERROR_MAX_FILES_OPEN = -14
38*f81fb7c4SAndroid Build Coastguard WorkerEAS_ERROR_UNRECOGNIZED_FORMAT = -15
39*f81fb7c4SAndroid Build Coastguard WorkerEAS_BUFFER_SIZE_MISMATCH = -16
40*f81fb7c4SAndroid Build Coastguard WorkerEAS_ERROR_FILE_FORMAT = -17
41*f81fb7c4SAndroid Build Coastguard WorkerEAS_ERROR_SMF_NOT_INITIALIZED = -18
42*f81fb7c4SAndroid Build Coastguard WorkerEAS_ERROR_LOCATE_BEYOND_END = -19
43*f81fb7c4SAndroid Build Coastguard WorkerEAS_ERROR_INVALID_PCM_TYPE = -20
44*f81fb7c4SAndroid Build Coastguard WorkerEAS_ERROR_MAX_PCM_STREAMS = -21
45*f81fb7c4SAndroid Build Coastguard WorkerEAS_ERROR_NO_VOICE_ALLOCATED = -22
46*f81fb7c4SAndroid Build Coastguard WorkerEAS_ERROR_INVALID_CHANNEL = -23
47*f81fb7c4SAndroid Build Coastguard WorkerEAS_ERROR_ALREADY_STOPPED = -24
48*f81fb7c4SAndroid Build Coastguard WorkerEAS_ERROR_FILE_READ_FAILED = -25
49*f81fb7c4SAndroid Build Coastguard WorkerEAS_ERROR_HANDLE_INTEGRITY = -26
50*f81fb7c4SAndroid Build Coastguard WorkerEAS_ERROR_MAX_STREAMS_OPEN = -27
51*f81fb7c4SAndroid Build Coastguard WorkerEAS_ERROR_INVALID_PARAMETER = -28
52*f81fb7c4SAndroid Build Coastguard WorkerEAS_ERROR_FEATURE_NOT_AVAILABLE = -29
53*f81fb7c4SAndroid Build Coastguard WorkerEAS_ERROR_SOUND_LIBRARY = -30
54*f81fb7c4SAndroid Build Coastguard WorkerEAS_ERROR_NOT_VALID_IN_THIS_STATE = -31
55*f81fb7c4SAndroid Build Coastguard WorkerEAS_ERROR_NO_VIRTUAL_SYNTHESIZER = -32
56*f81fb7c4SAndroid Build Coastguard WorkerEAS_ERROR_FILE_ALREADY_OPEN = -33
57*f81fb7c4SAndroid Build Coastguard WorkerEAS_ERROR_FILE_ALREADY_CLOSED = -34
58*f81fb7c4SAndroid Build Coastguard WorkerEAS_ERROR_INCOMPATIBLE_VERSION = -35
59*f81fb7c4SAndroid Build Coastguard WorkerEAS_ERROR_QUEUE_IS_FULL = -36
60*f81fb7c4SAndroid Build Coastguard WorkerEAS_ERROR_QUEUE_IS_EMPTY = -37
61*f81fb7c4SAndroid Build Coastguard WorkerEAS_ERROR_FEATURE_ALREADY_ACTIVE = -38
62*f81fb7c4SAndroid Build Coastguard Worker
63*f81fb7c4SAndroid Build Coastguard Worker# special result codes
64*f81fb7c4SAndroid Build Coastguard WorkerEAS_EOF = 3
65*f81fb7c4SAndroid Build Coastguard WorkerEAS_STREAM_BUFFERING = 4
66*f81fb7c4SAndroid Build Coastguard Worker
67*f81fb7c4SAndroid Build Coastguard Worker# buffer full error returned from Render
68*f81fb7c4SAndroid Build Coastguard WorkerEAS_BUFFER_FULL = 5
69*f81fb7c4SAndroid Build Coastguard Worker
70*f81fb7c4SAndroid Build Coastguard Worker# file types
71*f81fb7c4SAndroid Build Coastguard Workerfile_types = (
72*f81fb7c4SAndroid Build Coastguard Worker	'Unknown',
73*f81fb7c4SAndroid Build Coastguard Worker	'SMF Type 0 (.mid)',
74*f81fb7c4SAndroid Build Coastguard Worker	'SMF Type 1 (.mid)',
75*f81fb7c4SAndroid Build Coastguard Worker	'SMAF - Unknown type (.mmf)',
76*f81fb7c4SAndroid Build Coastguard Worker	'SMAF MA-2 (.mmf)',
77*f81fb7c4SAndroid Build Coastguard Worker	'SMAF MA-3 (.mmf)',
78*f81fb7c4SAndroid Build Coastguard Worker	'SMAF MA-5 (.mmf)',
79*f81fb7c4SAndroid Build Coastguard Worker	'CMX/QualComm  (.pmd)',
80*f81fb7c4SAndroid Build Coastguard Worker	'MFi (NTT/DoCoMo i-mode)',
81*f81fb7c4SAndroid Build Coastguard Worker	'OTA/Nokia (.ott)',
82*f81fb7c4SAndroid Build Coastguard Worker	'iMelody (.imy)',
83*f81fb7c4SAndroid Build Coastguard Worker	'RTX/RTTTL (.rtx)',
84*f81fb7c4SAndroid Build Coastguard Worker	'XMF Type 0 (.xmf)',
85*f81fb7c4SAndroid Build Coastguard Worker	'XMF Type 1 (.xmf)',
86*f81fb7c4SAndroid Build Coastguard Worker	'WAVE/PCM (.wav)',
87*f81fb7c4SAndroid Build Coastguard Worker	'WAVE/IMA-ADPCM (.wav)',
88*f81fb7c4SAndroid Build Coastguard Worker	'MMAPI Tone Control (.js)'
89*f81fb7c4SAndroid Build Coastguard Worker)
90*f81fb7c4SAndroid Build Coastguard Worker
91*f81fb7c4SAndroid Build Coastguard Workerstream_states = (
92*f81fb7c4SAndroid Build Coastguard Worker	'Ready',
93*f81fb7c4SAndroid Build Coastguard Worker	'Play',
94*f81fb7c4SAndroid Build Coastguard Worker	'Stopping',
95*f81fb7c4SAndroid Build Coastguard Worker	'Stopped',
96*f81fb7c4SAndroid Build Coastguard Worker	'Pausing',
97*f81fb7c4SAndroid Build Coastguard Worker	'Paused',
98*f81fb7c4SAndroid Build Coastguard Worker	'Open',
99*f81fb7c4SAndroid Build Coastguard Worker	'Error',
100*f81fb7c4SAndroid Build Coastguard Worker	'Empty'
101*f81fb7c4SAndroid Build Coastguard Worker)
102*f81fb7c4SAndroid Build Coastguard Worker
103*f81fb7c4SAndroid Build Coastguard Worker# iMode play modes
104*f81fb7c4SAndroid Build Coastguard WorkerIMODE_PLAY_ALL = 0
105*f81fb7c4SAndroid Build Coastguard WorkerIMODE_PLAY_PARTIAL = 1
106*f81fb7c4SAndroid Build Coastguard Worker
107*f81fb7c4SAndroid Build Coastguard Worker# callback type for metadata
108*f81fb7c4SAndroid Build Coastguard WorkerEAS_METADATA_CBFUNC = CFUNCTYPE(c_int, c_int, c_char_p, c_ulong)
109*f81fb7c4SAndroid Build Coastguard Worker
110*f81fb7c4SAndroid Build Coastguard Worker# callbacks for external audio
111*f81fb7c4SAndroid Build Coastguard WorkerEAS_EXT_PRG_CHG_FUNC = CFUNCTYPE(c_int, c_void_p, c_void_p)
112*f81fb7c4SAndroid Build Coastguard WorkerEAS_EXT_EVENT_FUNC = CFUNCTYPE(c_int, c_void_p, c_void_p)
113*f81fb7c4SAndroid Build Coastguard Worker
114*f81fb7c4SAndroid Build Coastguard Worker# callback for aux mixer decoder
115*f81fb7c4SAndroid Build Coastguard WorkerEAS_DECODER_FUNC = CFUNCTYPE(c_void_p, c_void_p, c_int, c_int)
116*f81fb7c4SAndroid Build Coastguard Worker
117*f81fb7c4SAndroid Build Coastguard Worker# DLL path
118*f81fb7c4SAndroid Build Coastguard Workerif OsWindows():
119*f81fb7c4SAndroid Build Coastguard Worker	EAS_DLL_PATH = "EASDLL.dll"
120*f81fb7c4SAndroid Build Coastguard Workerelse:
121*f81fb7c4SAndroid Build Coastguard Worker	EAS_DLL_PATH = "libEASLIb.dylib"
122*f81fb7c4SAndroid Build Coastguard Worker
123*f81fb7c4SAndroid Build Coastguard Workereas_dll = None
124*f81fb7c4SAndroid Build Coastguard Worker
125*f81fb7c4SAndroid Build Coastguard Worker# logger
126*f81fb7c4SAndroid Build Coastguard Workereas_logger = None
127*f81fb7c4SAndroid Build Coastguard Worker
128*f81fb7c4SAndroid Build Coastguard Worker#---------------------------------------------------------------
129*f81fb7c4SAndroid Build Coastguard Worker# InitEASModule
130*f81fb7c4SAndroid Build Coastguard Worker#---------------------------------------------------------------
131*f81fb7c4SAndroid Build Coastguard Workerdef InitEASModule (dll_path=None):
132*f81fb7c4SAndroid Build Coastguard Worker	global eas_dll
133*f81fb7c4SAndroid Build Coastguard Worker	global eas_logger
134*f81fb7c4SAndroid Build Coastguard Worker
135*f81fb7c4SAndroid Build Coastguard Worker
136*f81fb7c4SAndroid Build Coastguard Worker	# initialize logger
137*f81fb7c4SAndroid Build Coastguard Worker	if eas_logger is None:
138*f81fb7c4SAndroid Build Coastguard Worker		eas_logger = logging.getLogger('EAS')
139*f81fb7c4SAndroid Build Coastguard Worker
140*f81fb7c4SAndroid Build Coastguard Worker	# initialize path to DLL
141*f81fb7c4SAndroid Build Coastguard Worker	if dll_path is None:
142*f81fb7c4SAndroid Build Coastguard Worker		dll_path=EAS_DLL_PATH
143*f81fb7c4SAndroid Build Coastguard Worker
144*f81fb7c4SAndroid Build Coastguard Worker	# intialize DLL
145*f81fb7c4SAndroid Build Coastguard Worker	if eas_dll is None:
146*f81fb7c4SAndroid Build Coastguard Worker		eas_dll = cdll.LoadLibrary(dll_path)
147*f81fb7c4SAndroid Build Coastguard Worker
148*f81fb7c4SAndroid Build Coastguard Worker#---------------------------------------------------------------
149*f81fb7c4SAndroid Build Coastguard Worker# S_JET_CONFIG
150*f81fb7c4SAndroid Build Coastguard Worker#---------------------------------------------------------------
151*f81fb7c4SAndroid Build Coastguard Workerclass S_JET_CONFIG (Structure):
152*f81fb7c4SAndroid Build Coastguard Worker	_fields_ = [('appLowNote', c_ubyte)]
153*f81fb7c4SAndroid Build Coastguard Worker
154*f81fb7c4SAndroid Build Coastguard Worker#---------------------------------------------------------------
155*f81fb7c4SAndroid Build Coastguard Worker# S_EXT_AUDIO_PRG_CHG
156*f81fb7c4SAndroid Build Coastguard Worker#---------------------------------------------------------------
157*f81fb7c4SAndroid Build Coastguard Workerclass S_EXT_AUDIO_PRG_CHG (Structure):
158*f81fb7c4SAndroid Build Coastguard Worker	_fields_ = [('bank', c_ushort),
159*f81fb7c4SAndroid Build Coastguard Worker				('program', c_ubyte),
160*f81fb7c4SAndroid Build Coastguard Worker				('channel', c_ubyte)]
161*f81fb7c4SAndroid Build Coastguard Worker
162*f81fb7c4SAndroid Build Coastguard Worker#---------------------------------------------------------------
163*f81fb7c4SAndroid Build Coastguard Worker# S_EXT_AUDIO_EVENT
164*f81fb7c4SAndroid Build Coastguard Worker#---------------------------------------------------------------
165*f81fb7c4SAndroid Build Coastguard Workerclass S_EXT_AUDIO_EVENT (Structure):
166*f81fb7c4SAndroid Build Coastguard Worker	_fields_ = [('channel', c_ubyte),
167*f81fb7c4SAndroid Build Coastguard Worker				('note', c_ubyte),
168*f81fb7c4SAndroid Build Coastguard Worker				('velocity', c_ubyte),
169*f81fb7c4SAndroid Build Coastguard Worker				('noteOn', c_ubyte)]
170*f81fb7c4SAndroid Build Coastguard Worker
171*f81fb7c4SAndroid Build Coastguard Worker#---------------------------------------------------------------
172*f81fb7c4SAndroid Build Coastguard Worker# S_MIDI_CONTROLLERS
173*f81fb7c4SAndroid Build Coastguard Worker#---------------------------------------------------------------
174*f81fb7c4SAndroid Build Coastguard Workerclass S_MIDI_CONTROLLERS (Structure):
175*f81fb7c4SAndroid Build Coastguard Worker	_fields_ = [('modWheel', c_ubyte),
176*f81fb7c4SAndroid Build Coastguard Worker				('volume', c_ubyte),
177*f81fb7c4SAndroid Build Coastguard Worker				('pan', c_ubyte),
178*f81fb7c4SAndroid Build Coastguard Worker				('expression', c_ubyte),
179*f81fb7c4SAndroid Build Coastguard Worker				('channelPressure', c_ubyte)]
180*f81fb7c4SAndroid Build Coastguard Worker
181*f81fb7c4SAndroid Build Coastguard Worker#---------------------------------------------------------------
182*f81fb7c4SAndroid Build Coastguard Worker# WAVEFORMAT
183*f81fb7c4SAndroid Build Coastguard Worker#---------------------------------------------------------------
184*f81fb7c4SAndroid Build Coastguard Workerclass WAVEFORMAT (Structure):
185*f81fb7c4SAndroid Build Coastguard Worker	_fields_ = [('wFormatTag', c_ushort),
186*f81fb7c4SAndroid Build Coastguard Worker				('nChannels', c_ushort),
187*f81fb7c4SAndroid Build Coastguard Worker				('nSamplesPerSec', c_ulong),
188*f81fb7c4SAndroid Build Coastguard Worker				('nAvgBytesPerSec', c_ulong),
189*f81fb7c4SAndroid Build Coastguard Worker				('nBlockAlign', c_ushort),
190*f81fb7c4SAndroid Build Coastguard Worker				('wBitsPerSample', c_ushort)]
191*f81fb7c4SAndroid Build Coastguard Worker
192*f81fb7c4SAndroid Build Coastguard Worker#---------------------------------------------------------------
193*f81fb7c4SAndroid Build Coastguard Worker# EAS_Exception
194*f81fb7c4SAndroid Build Coastguard Worker#---------------------------------------------------------------
195*f81fb7c4SAndroid Build Coastguard Workerclass EAS_Exception (Exception):
196*f81fb7c4SAndroid Build Coastguard Worker	def __init__ (self, result_code, msg, function=None):
197*f81fb7c4SAndroid Build Coastguard Worker		self.msg = msg
198*f81fb7c4SAndroid Build Coastguard Worker		self.result_code = result_code
199*f81fb7c4SAndroid Build Coastguard Worker		self.function = function
200*f81fb7c4SAndroid Build Coastguard Worker	def __str__ (self):
201*f81fb7c4SAndroid Build Coastguard Worker		return self.msg
202*f81fb7c4SAndroid Build Coastguard Worker
203*f81fb7c4SAndroid Build Coastguard Worker#---------------------------------------------------------------
204*f81fb7c4SAndroid Build Coastguard Worker# Log callback function
205*f81fb7c4SAndroid Build Coastguard Worker#---------------------------------------------------------------
206*f81fb7c4SAndroid Build Coastguard Worker# map EAS severity levels to the Python logging module
207*f81fb7c4SAndroid Build Coastguard Workerseverity_mapping = (logging.CRITICAL, logging.CRITICAL, logging.ERROR, logging.WARNING, logging.INFO, logging.DEBUG)
208*f81fb7c4SAndroid Build Coastguard WorkerLOG_FUNC_TYPE = CFUNCTYPE(c_int, c_int, c_char_p)
209*f81fb7c4SAndroid Build Coastguard Workerdef Log (level, msg):
210*f81fb7c4SAndroid Build Coastguard Worker	eas_logger.log(severity_mapping[level], msg)
211*f81fb7c4SAndroid Build Coastguard Worker	return level
212*f81fb7c4SAndroid Build Coastguard WorkerLogCallback = LOG_FUNC_TYPE(Log)
213*f81fb7c4SAndroid Build Coastguard Worker
214*f81fb7c4SAndroid Build Coastguard Worker#---------------------------------------------------------------
215*f81fb7c4SAndroid Build Coastguard Worker# EAS_Stream
216*f81fb7c4SAndroid Build Coastguard Worker#---------------------------------------------------------------
217*f81fb7c4SAndroid Build Coastguard Workerclass EAS_Stream (object):
218*f81fb7c4SAndroid Build Coastguard Worker	def __init__ (self, handle, eas):
219*f81fb7c4SAndroid Build Coastguard Worker		eas_logger.debug('EAS_Stream.__init__')
220*f81fb7c4SAndroid Build Coastguard Worker		self.handle = handle
221*f81fb7c4SAndroid Build Coastguard Worker		self.eas = eas
222*f81fb7c4SAndroid Build Coastguard Worker
223*f81fb7c4SAndroid Build Coastguard Worker	def SetVolume (self, volume):
224*f81fb7c4SAndroid Build Coastguard Worker		"""Set the stream volume"""
225*f81fb7c4SAndroid Build Coastguard Worker		eas_logger.debug('Call EAS_SetVolume: volume=%d' % volume)
226*f81fb7c4SAndroid Build Coastguard Worker		with self.eas.lock:
227*f81fb7c4SAndroid Build Coastguard Worker			result = eas_dll.EAS_SetVolume(self.eas.handle, self.handle, volume)
228*f81fb7c4SAndroid Build Coastguard Worker			if result:
229*f81fb7c4SAndroid Build Coastguard Worker				raise EAS_Exception(result, 'EAS_SetVolume error %d on file %s' % (result, self.path), 'EAS_SetVolume')
230*f81fb7c4SAndroid Build Coastguard Worker
231*f81fb7c4SAndroid Build Coastguard Worker	def GetVolume (self):
232*f81fb7c4SAndroid Build Coastguard Worker		"""Get the stream volume."""
233*f81fb7c4SAndroid Build Coastguard Worker		eas_logger.debug('Call EAS_GetVolume')
234*f81fb7c4SAndroid Build Coastguard Worker		with self.eas.lock:
235*f81fb7c4SAndroid Build Coastguard Worker			volume = eas_dll.EAS_GetVolume(self.eas.handle, self.handle)
236*f81fb7c4SAndroid Build Coastguard Worker			if volume < 0:
237*f81fb7c4SAndroid Build Coastguard Worker				raise EAS_Exception(volume, 'EAS_GetVolume error %d on file %s' % (volume, self.path), 'EAS_GetVolume')
238*f81fb7c4SAndroid Build Coastguard Worker		eas_logger.debug('EAS_GetVolume: volume=%d' % volume)
239*f81fb7c4SAndroid Build Coastguard Worker		return volume
240*f81fb7c4SAndroid Build Coastguard Worker
241*f81fb7c4SAndroid Build Coastguard Worker	def SetPriority (self, priority):
242*f81fb7c4SAndroid Build Coastguard Worker		"""Set the stream priority"""
243*f81fb7c4SAndroid Build Coastguard Worker		eas_logger.debug('Call EAS_SetPriority: priority=%d' % priority)
244*f81fb7c4SAndroid Build Coastguard Worker		with self.eas.lock:
245*f81fb7c4SAndroid Build Coastguard Worker			result = eas_dll.EAS_SetPriority(self.eas.handle, self.handle, priority)
246*f81fb7c4SAndroid Build Coastguard Worker			if result:
247*f81fb7c4SAndroid Build Coastguard Worker				raise EAS_Exception(result, 'EAS_SetPriority error %d on file %s' % (result, self.path), 'EAS_SetPriority')
248*f81fb7c4SAndroid Build Coastguard Worker
249*f81fb7c4SAndroid Build Coastguard Worker	def GetPriority (self):
250*f81fb7c4SAndroid Build Coastguard Worker		"""Get the stream priority."""
251*f81fb7c4SAndroid Build Coastguard Worker		eas_logger.debug('Call EAS_GetPriority')
252*f81fb7c4SAndroid Build Coastguard Worker		priority = c_int(0)
253*f81fb7c4SAndroid Build Coastguard Worker		with self.eas.lock:
254*f81fb7c4SAndroid Build Coastguard Worker			result = eas_dll.EAS_GetPriority(self.eas.handle, self.handle, byref(priority))
255*f81fb7c4SAndroid Build Coastguard Worker			if result:
256*f81fb7c4SAndroid Build Coastguard Worker				raise EAS_Exception(result, 'EAS_GetPriority error %d on file %s' % (result, self.path), 'EAS_GetPriority')
257*f81fb7c4SAndroid Build Coastguard Worker		eas_logger.debug('EAS_GetPriority: priority=%d' % priority.value)
258*f81fb7c4SAndroid Build Coastguard Worker		return priority.value
259*f81fb7c4SAndroid Build Coastguard Worker
260*f81fb7c4SAndroid Build Coastguard Worker	def SetTransposition (self, transposition):
261*f81fb7c4SAndroid Build Coastguard Worker		"""Set the transposition of a stream."""
262*f81fb7c4SAndroid Build Coastguard Worker		eas_logger.debug('Call EAS_SetTransposition: transposition=%d' % transposition)
263*f81fb7c4SAndroid Build Coastguard Worker		with self.eas.lock:
264*f81fb7c4SAndroid Build Coastguard Worker			result = eas_dll.EAS_SetTransposition(self.eas.handle, self.handle, transposition)
265*f81fb7c4SAndroid Build Coastguard Worker			if result:
266*f81fb7c4SAndroid Build Coastguard Worker				raise EAS_Exception(result, 'EAS_SetTransposition error %d on file %s' % (result, self.path), 'EAS_SetTransposition')
267*f81fb7c4SAndroid Build Coastguard Worker
268*f81fb7c4SAndroid Build Coastguard Worker	def SetPolyphony (self, polyphony):
269*f81fb7c4SAndroid Build Coastguard Worker		"""Set the polyphony of a stream."""
270*f81fb7c4SAndroid Build Coastguard Worker		eas_logger.debug('Call EAS_SetPolyphony: polyphony=%d' % polyphony)
271*f81fb7c4SAndroid Build Coastguard Worker		with self.eas.lock:
272*f81fb7c4SAndroid Build Coastguard Worker			result = eas_dll.EAS_SetPolyphony(self.eas.handle, self.handle, polyphony)
273*f81fb7c4SAndroid Build Coastguard Worker			if result:
274*f81fb7c4SAndroid Build Coastguard Worker				raise EAS_Exception(result, 'EAS_SetPolyphony error %d on file %s' % (result, self.path), 'EAS_SetPolyphony')
275*f81fb7c4SAndroid Build Coastguard Worker
276*f81fb7c4SAndroid Build Coastguard Worker	def GetPolyphony (self):
277*f81fb7c4SAndroid Build Coastguard Worker		"""Get the polyphony of a stream."""
278*f81fb7c4SAndroid Build Coastguard Worker		eas_logger.debug('Call EAS_GetPolyphony')
279*f81fb7c4SAndroid Build Coastguard Worker		polyphony = c_int(0)
280*f81fb7c4SAndroid Build Coastguard Worker		with self.eas.lock:
281*f81fb7c4SAndroid Build Coastguard Worker			result = eas_dll.EAS_GetPolyphony(self.eas.handle, self.handle, byref(polyphony))
282*f81fb7c4SAndroid Build Coastguard Worker			if result:
283*f81fb7c4SAndroid Build Coastguard Worker				raise EAS_Exception(result, 'EAS_GetPolyphony error %d on file %s' % (result, self.path), 'EAS_GetPolyphony')
284*f81fb7c4SAndroid Build Coastguard Worker		eas_logger.debug('EAS_SetPolyphony: polyphony=%d' % polyphony.value)
285*f81fb7c4SAndroid Build Coastguard Worker		return polyphony.value
286*f81fb7c4SAndroid Build Coastguard Worker
287*f81fb7c4SAndroid Build Coastguard Worker	def SelectLib (self, test_lib=False):
288*f81fb7c4SAndroid Build Coastguard Worker		eas_logger.debug('Call EAS_SelectLib: test_lib=%s' % test_lib)
289*f81fb7c4SAndroid Build Coastguard Worker		with self.eas.lock:
290*f81fb7c4SAndroid Build Coastguard Worker			result = eas_dll.EAS_SelectLib(self.eas.handle, self.handle, test_lib)
291*f81fb7c4SAndroid Build Coastguard Worker			if result:
292*f81fb7c4SAndroid Build Coastguard Worker				raise EAS_Exception(result, 'EAS_SelectLib error %d on file %s' % (result, self.path), 'EAS_SelectLib')
293*f81fb7c4SAndroid Build Coastguard Worker
294*f81fb7c4SAndroid Build Coastguard Worker	def LoadDLSCollection (self, path):
295*f81fb7c4SAndroid Build Coastguard Worker		eas_logger.debug('Call EAS_LoadDLSCollection: lib_path=%d' % path)
296*f81fb7c4SAndroid Build Coastguard Worker		with self.eas.lock:
297*f81fb7c4SAndroid Build Coastguard Worker			result = eas_dll.EAS_LoadDLSCollection(self.eas.handle, self.handle, path)
298*f81fb7c4SAndroid Build Coastguard Worker			if result:
299*f81fb7c4SAndroid Build Coastguard Worker				raise EAS_Exception(result, 'EAS_LoadDLSCollection error %d on file %s lib %s' % (result, self.path, path), 'EAS_LoadDLSCollection')
300*f81fb7c4SAndroid Build Coastguard Worker
301*f81fb7c4SAndroid Build Coastguard Worker	def RegExtAudioCallback (self, user_data, prog_chg_func, event_func):
302*f81fb7c4SAndroid Build Coastguard Worker		"""Register an external audio callback."""
303*f81fb7c4SAndroid Build Coastguard Worker		eas_logger.debug('Call EAS_RegExtAudioCallback')
304*f81fb7c4SAndroid Build Coastguard Worker		if prog_chg_func is not None:
305*f81fb7c4SAndroid Build Coastguard Worker			prog_chg_func = EAS_EXT_PRG_CHG_FUNC(prog_chg_func)
306*f81fb7c4SAndroid Build Coastguard Worker		else:
307*f81fb7c4SAndroid Build Coastguard Worker			prog_chg_func = 0
308*f81fb7c4SAndroid Build Coastguard Worker		if event_func is not None:
309*f81fb7c4SAndroid Build Coastguard Worker			event_func = EAS_EXT_EVENT_FUNC(event_func)
310*f81fb7c4SAndroid Build Coastguard Worker		else:
311*f81fb7c4SAndroid Build Coastguard Worker			event_func = 0
312*f81fb7c4SAndroid Build Coastguard Worker		with self.eas.lock:
313*f81fb7c4SAndroid Build Coastguard Worker			result = eas_dll.EAS_RegExtAudioCallback(self.eas.handle, self.handle, user_data, prog_chg_func, event_func)
314*f81fb7c4SAndroid Build Coastguard Worker			if result:
315*f81fb7c4SAndroid Build Coastguard Worker				raise EAS_Exception(result, 'EAS_RegExtAudioCallback error %d on file %s' % (result, self.path), 'EAS_RegExtAudioCallback')
316*f81fb7c4SAndroid Build Coastguard Worker
317*f81fb7c4SAndroid Build Coastguard Worker	def SetPlayMode (self, play_mode):
318*f81fb7c4SAndroid Build Coastguard Worker		"""Set play mode on a stream."""
319*f81fb7c4SAndroid Build Coastguard Worker		eas_logger.debug('Call EAS_SetPlayMode: play_mode=%d' % play_mode)
320*f81fb7c4SAndroid Build Coastguard Worker		with self.eas.lock:
321*f81fb7c4SAndroid Build Coastguard Worker			result = eas_dll.EAS_SetPlayMode(self.eas.handle, self.handle, play_mode)
322*f81fb7c4SAndroid Build Coastguard Worker			if result:
323*f81fb7c4SAndroid Build Coastguard Worker				raise EAS_Exception(result, 'EAS_SetPlayMode error %d on file %s' % (result, self.path), 'EAS_SetPlayMode')
324*f81fb7c4SAndroid Build Coastguard Worker
325*f81fb7c4SAndroid Build Coastguard Worker"""
326*f81fb7c4SAndroid Build Coastguard WorkerEAS_PUBLIC EAS_RESULT EAS_GetMIDIControllers (EAS_DATA_HANDLE pEASData, EAS_HANDLE streamHandle, EAS_U8 channel, S_MIDI_CONTROLLERS *pControl);
327*f81fb7c4SAndroid Build Coastguard Worker"""
328*f81fb7c4SAndroid Build Coastguard Worker
329*f81fb7c4SAndroid Build Coastguard Worker#---------------------------------------------------------------
330*f81fb7c4SAndroid Build Coastguard Worker# EAS_File
331*f81fb7c4SAndroid Build Coastguard Worker#---------------------------------------------------------------
332*f81fb7c4SAndroid Build Coastguard Workerclass EAS_File (EAS_Stream):
333*f81fb7c4SAndroid Build Coastguard Worker	def __init__ (self, path, handle, eas):
334*f81fb7c4SAndroid Build Coastguard Worker		EAS_Stream.__init__(self, handle, eas)
335*f81fb7c4SAndroid Build Coastguard Worker		eas_logger.debug('EAS_File.__init__')
336*f81fb7c4SAndroid Build Coastguard Worker		self.path = path
337*f81fb7c4SAndroid Build Coastguard Worker		self.prepared = False
338*f81fb7c4SAndroid Build Coastguard Worker
339*f81fb7c4SAndroid Build Coastguard Worker	def Prepare (self):
340*f81fb7c4SAndroid Build Coastguard Worker		"""Prepare an audio file for playback"""
341*f81fb7c4SAndroid Build Coastguard Worker		if self.prepared:
342*f81fb7c4SAndroid Build Coastguard Worker			eas_logger.warning('Prepare already called on file %s' % self.path)
343*f81fb7c4SAndroid Build Coastguard Worker		else:
344*f81fb7c4SAndroid Build Coastguard Worker			with self.eas.lock:
345*f81fb7c4SAndroid Build Coastguard Worker				eas_logger.debug('Call EAS_Prepare for file: %s' % self.path)
346*f81fb7c4SAndroid Build Coastguard Worker				result = eas_dll.EAS_Prepare(self.eas.handle, self.handle)
347*f81fb7c4SAndroid Build Coastguard Worker				if result:
348*f81fb7c4SAndroid Build Coastguard Worker					raise EAS_Exception(result, 'EAS_Prepare error %d on file %s' % (result, self.path), 'EAS_Prepare')
349*f81fb7c4SAndroid Build Coastguard Worker				self.prepared = True
350*f81fb7c4SAndroid Build Coastguard Worker
351*f81fb7c4SAndroid Build Coastguard Worker	def State (self):
352*f81fb7c4SAndroid Build Coastguard Worker		"""Get stream state."""
353*f81fb7c4SAndroid Build Coastguard Worker		with self.eas.lock:
354*f81fb7c4SAndroid Build Coastguard Worker			eas_logger.debug('Call EAS_State for file: %s' % self.path)
355*f81fb7c4SAndroid Build Coastguard Worker			state = c_long(-1)
356*f81fb7c4SAndroid Build Coastguard Worker			result = eas_dll.EAS_State(self.eas.handle, self.handle, byref(state))
357*f81fb7c4SAndroid Build Coastguard Worker			if result:
358*f81fb7c4SAndroid Build Coastguard Worker				raise EAS_Exception(result, 'EAS_State error %d on file %s' % (result, self.path), 'EAS_State')
359*f81fb7c4SAndroid Build Coastguard Worker			eas_logger.debug('EAS_State: file=%s, state=%s' % (self.path, stream_states[state.value]))
360*f81fb7c4SAndroid Build Coastguard Worker			return state.value
361*f81fb7c4SAndroid Build Coastguard Worker
362*f81fb7c4SAndroid Build Coastguard Worker	def Close (self):
363*f81fb7c4SAndroid Build Coastguard Worker		"""Close audio file."""
364*f81fb7c4SAndroid Build Coastguard Worker		if hasattr(self, 'handle'):
365*f81fb7c4SAndroid Build Coastguard Worker			with self.eas.lock:
366*f81fb7c4SAndroid Build Coastguard Worker				eas_logger.debug('Call EAS_CloseFile for file: %s' % self.path)
367*f81fb7c4SAndroid Build Coastguard Worker				result = eas_dll.EAS_CloseFile(self.eas.handle, self.handle)
368*f81fb7c4SAndroid Build Coastguard Worker				if result:
369*f81fb7c4SAndroid Build Coastguard Worker					raise EAS_Exception(result, 'EAS_CloseFile error %d on file %s' % (result, self.path), 'EAS_CloseFile')
370*f81fb7c4SAndroid Build Coastguard Worker
371*f81fb7c4SAndroid Build Coastguard Worker				# remove file from the EAS object
372*f81fb7c4SAndroid Build Coastguard Worker				self.eas.audio_streams.remove(self)
373*f81fb7c4SAndroid Build Coastguard Worker
374*f81fb7c4SAndroid Build Coastguard Worker			# clean up references
375*f81fb7c4SAndroid Build Coastguard Worker			del self.handle
376*f81fb7c4SAndroid Build Coastguard Worker			del self.eas
377*f81fb7c4SAndroid Build Coastguard Worker			del self.path
378*f81fb7c4SAndroid Build Coastguard Worker
379*f81fb7c4SAndroid Build Coastguard Worker	def Pause (self):
380*f81fb7c4SAndroid Build Coastguard Worker		"""Pause a stream."""
381*f81fb7c4SAndroid Build Coastguard Worker		eas_logger.debug('Call EAS_Pause')
382*f81fb7c4SAndroid Build Coastguard Worker		with self.eas.lock:
383*f81fb7c4SAndroid Build Coastguard Worker			result = eas_dll.EAS_Pause(self.eas.handle, self.handle)
384*f81fb7c4SAndroid Build Coastguard Worker			if result:
385*f81fb7c4SAndroid Build Coastguard Worker				raise EAS_Exception(result, 'EAS_Pause error %d on file %s' % (result, self.path), 'EAS_Pause')
386*f81fb7c4SAndroid Build Coastguard Worker
387*f81fb7c4SAndroid Build Coastguard Worker	def Resume (self):
388*f81fb7c4SAndroid Build Coastguard Worker		"""Resume a stream."""
389*f81fb7c4SAndroid Build Coastguard Worker		eas_logger.debug('Call EAS_Resume')
390*f81fb7c4SAndroid Build Coastguard Worker		with self.eas.lock:
391*f81fb7c4SAndroid Build Coastguard Worker			result = eas_dll.EAS_Resume(self.eas.handle, self.handle)
392*f81fb7c4SAndroid Build Coastguard Worker			if result:
393*f81fb7c4SAndroid Build Coastguard Worker				raise EAS_Exception(result, 'EAS_Resume error %d on file %s' % (result, self.path), 'EAS_Resume')
394*f81fb7c4SAndroid Build Coastguard Worker
395*f81fb7c4SAndroid Build Coastguard Worker	def Locate (self, secs, offset=False):
396*f81fb7c4SAndroid Build Coastguard Worker		"""Set the playback position of a stream in seconds."""
397*f81fb7c4SAndroid Build Coastguard Worker		eas_logger.debug('Call EAS_Locate: location=%.3f, relative=%s' % (secs, offset))
398*f81fb7c4SAndroid Build Coastguard Worker		with self.eas.lock:
399*f81fb7c4SAndroid Build Coastguard Worker			result = eas_dll.EAS_Locate(self.eas.handle, self.handle, int(secs * 1000 + 0.5), offset)
400*f81fb7c4SAndroid Build Coastguard Worker			if result:
401*f81fb7c4SAndroid Build Coastguard Worker				raise EAS_Exception(result, 'EAS_Locate error %d on file %s' % (result, self.path), 'EAS_Locate')
402*f81fb7c4SAndroid Build Coastguard Worker
403*f81fb7c4SAndroid Build Coastguard Worker	def GetLocation (self):
404*f81fb7c4SAndroid Build Coastguard Worker		"""Get the stream location in seconds."""
405*f81fb7c4SAndroid Build Coastguard Worker		eas_logger.debug('Call EAS_GetLocation')
406*f81fb7c4SAndroid Build Coastguard Worker		msecs = c_int(0)
407*f81fb7c4SAndroid Build Coastguard Worker		with self.eas.lock:
408*f81fb7c4SAndroid Build Coastguard Worker			result = eas_dll.EAS_GetLocation(self.eas.handle, self.handle, byref(msecs))
409*f81fb7c4SAndroid Build Coastguard Worker			if result:
410*f81fb7c4SAndroid Build Coastguard Worker				raise EAS_Exception(result, 'EAS_GetLocation error %d on file %s' % (result, self.path), 'EAS_GetLocation')
411*f81fb7c4SAndroid Build Coastguard Worker		msecs = float(msecs.value) / 1000
412*f81fb7c4SAndroid Build Coastguard Worker		eas_logger.debug('EAS_GetLocation: location=%.3f' % msecs)
413*f81fb7c4SAndroid Build Coastguard Worker		return msecs
414*f81fb7c4SAndroid Build Coastguard Worker
415*f81fb7c4SAndroid Build Coastguard Worker	def GetFileType (self):
416*f81fb7c4SAndroid Build Coastguard Worker		"""Get the file type."""
417*f81fb7c4SAndroid Build Coastguard Worker		eas_logger.debug('Call EAS_GetFileType')
418*f81fb7c4SAndroid Build Coastguard Worker		file_type = c_int(0)
419*f81fb7c4SAndroid Build Coastguard Worker		with self.eas.lock:
420*f81fb7c4SAndroid Build Coastguard Worker			result = eas_dll.EAS_GetFileType(self.eas.handle, self.handle, byref(file_type))
421*f81fb7c4SAndroid Build Coastguard Worker			if result:
422*f81fb7c4SAndroid Build Coastguard Worker				raise EAS_Exception(result, 'EAS_GetFileType error %d on file %s' % (result, self.path), 'EAS_GetFileType')
423*f81fb7c4SAndroid Build Coastguard Worker		file_type = file_type.value
424*f81fb7c4SAndroid Build Coastguard Worker		if file_type < len(file_types):
425*f81fb7c4SAndroid Build Coastguard Worker			file_desc = file_types[file_type]
426*f81fb7c4SAndroid Build Coastguard Worker		else:
427*f81fb7c4SAndroid Build Coastguard Worker			file_desc = 'Unrecognized type %d' % file_type
428*f81fb7c4SAndroid Build Coastguard Worker		eas_logger.debug('EAS_GetFileType: type=%d, desc=%s' % (file_type, file_desc))
429*f81fb7c4SAndroid Build Coastguard Worker		return (file_type, file_desc)
430*f81fb7c4SAndroid Build Coastguard Worker
431*f81fb7c4SAndroid Build Coastguard Worker	def SetRepeat (self, count):
432*f81fb7c4SAndroid Build Coastguard Worker		"""Set the repeat count of a stream."""
433*f81fb7c4SAndroid Build Coastguard Worker		eas_logger.debug('Call EAS_SetRepeat: count=%d' % count)
434*f81fb7c4SAndroid Build Coastguard Worker		with self.eas.lock:
435*f81fb7c4SAndroid Build Coastguard Worker			result = eas_dll.EAS_SetRepeat(self.eas.handle, self.handle, count)
436*f81fb7c4SAndroid Build Coastguard Worker			if result:
437*f81fb7c4SAndroid Build Coastguard Worker				raise EAS_Exception(result, 'EAS_SetRepeat error %d on file %s' % (result, self.path), 'EAS_SetRepeat')
438*f81fb7c4SAndroid Build Coastguard Worker
439*f81fb7c4SAndroid Build Coastguard Worker	def GetRepeat (self):
440*f81fb7c4SAndroid Build Coastguard Worker		"""Get the repeat count of a stream."""
441*f81fb7c4SAndroid Build Coastguard Worker		eas_logger.debug('Call EAS_GetRepeat')
442*f81fb7c4SAndroid Build Coastguard Worker		count = c_int(0)
443*f81fb7c4SAndroid Build Coastguard Worker		with self.eas.lock:
444*f81fb7c4SAndroid Build Coastguard Worker			result = eas_dll.EAS_GetRepeat(self.eas.handle, self.handle, byref(count))
445*f81fb7c4SAndroid Build Coastguard Worker			if result:
446*f81fb7c4SAndroid Build Coastguard Worker				raise EAS_Exception(result, 'EAS_GetRepeat error %d on file %s' % (result, self.path), 'EAS_GetRepeat')
447*f81fb7c4SAndroid Build Coastguard Worker		eas_logger.debug('EAS_GetRepeat: count=%d' % count.value)
448*f81fb7c4SAndroid Build Coastguard Worker		return count.value
449*f81fb7c4SAndroid Build Coastguard Worker
450*f81fb7c4SAndroid Build Coastguard Worker	def SetPlaybackRate (self, rate):
451*f81fb7c4SAndroid Build Coastguard Worker		"""Set the playback rate of a stream."""
452*f81fb7c4SAndroid Build Coastguard Worker		eas_logger.debug('Call EAS_SetPlaybackRate')
453*f81fb7c4SAndroid Build Coastguard Worker		with self.eas.lock:
454*f81fb7c4SAndroid Build Coastguard Worker			result = eas_dll.EAS_SetPlaybackRate(self.eas.handle, self.handle, rate)
455*f81fb7c4SAndroid Build Coastguard Worker			if result:
456*f81fb7c4SAndroid Build Coastguard Worker				raise EAS_Exception(result, 'EAS_SetPlaybackRate error %d on file %s' % (result, self.path), 'EAS_SetPlaybackRate')
457*f81fb7c4SAndroid Build Coastguard Worker
458*f81fb7c4SAndroid Build Coastguard Worker	def ParseMetaData (self):
459*f81fb7c4SAndroid Build Coastguard Worker		"""Parse the metadata in a file."""
460*f81fb7c4SAndroid Build Coastguard Worker		eas_logger.debug('Call EAS_ParseMetaData')
461*f81fb7c4SAndroid Build Coastguard Worker		length = c_int(0)
462*f81fb7c4SAndroid Build Coastguard Worker		with self.eas.lock:
463*f81fb7c4SAndroid Build Coastguard Worker			result = eas_dll.EAS_ParseMetaData(self.eas.handle, self.handle, byref(length))
464*f81fb7c4SAndroid Build Coastguard Worker			if result:
465*f81fb7c4SAndroid Build Coastguard Worker				raise EAS_Exception(result, 'EAS_ParseMetaData error %d on file %s' % (result, self.path), 'EAS_ParseMetaData')
466*f81fb7c4SAndroid Build Coastguard Worker		return float(length.value) / 1000.0
467*f81fb7c4SAndroid Build Coastguard Worker
468*f81fb7c4SAndroid Build Coastguard Worker	def RegisterMetaDataCallback (self, func, buf, buf_size, user_data):
469*f81fb7c4SAndroid Build Coastguard Worker		"""Register a metadata callback."""
470*f81fb7c4SAndroid Build Coastguard Worker		eas_logger.debug('Call EAS_RegisterMetaDataCallback')
471*f81fb7c4SAndroid Build Coastguard Worker		with self.eas.lock:
472*f81fb7c4SAndroid Build Coastguard Worker			if func is not None:
473*f81fb7c4SAndroid Build Coastguard Worker				callback = EAS_METADATA_CBFUNC(func)
474*f81fb7c4SAndroid Build Coastguard Worker			else:
475*f81fb7c4SAndroid Build Coastguard Worker				callback = 0
476*f81fb7c4SAndroid Build Coastguard Worker			result = eas_dll.EAS_RegisterMetaDataCallback(self.eas.handle, self.handle, callback, buf, buf_size, user_data)
477*f81fb7c4SAndroid Build Coastguard Worker			if result:
478*f81fb7c4SAndroid Build Coastguard Worker				raise EAS_Exception(result, 'EAS_RegisterMetaDataCallback error %d on file %s' % (result, self.path), 'EAS_RegisterMetaDataCallback')
479*f81fb7c4SAndroid Build Coastguard Worker
480*f81fb7c4SAndroid Build Coastguard Worker	def GetWaveFmtChunk (self):
481*f81fb7c4SAndroid Build Coastguard Worker		"""Get the file type."""
482*f81fb7c4SAndroid Build Coastguard Worker		eas_logger.debug('Call EAS_GetWaveFmtChunk')
483*f81fb7c4SAndroid Build Coastguard Worker		wave_fmt_chunk = c_void_p(0)
484*f81fb7c4SAndroid Build Coastguard Worker		with self.eas.lock:
485*f81fb7c4SAndroid Build Coastguard Worker			result = eas_dll.EAS_GetWaveFmtChunk(self.eas.handle, self.handle, byref(wave_fmt_chunk))
486*f81fb7c4SAndroid Build Coastguard Worker			if result:
487*f81fb7c4SAndroid Build Coastguard Worker				raise EAS_Exception(result, 'EAS_GetWaveFmtChunk error %d on file %s' % (result, self.path), 'EAS_GetWaveFmtChunk')
488*f81fb7c4SAndroid Build Coastguard Worker		return cast(wave_fmt_chunk, POINTER(WAVEFORMAT)).contents
489*f81fb7c4SAndroid Build Coastguard Worker
490*f81fb7c4SAndroid Build Coastguard Worker	def Play (self, max_time=None):
491*f81fb7c4SAndroid Build Coastguard Worker		"""Plays the file to the end or max_time."""
492*f81fb7c4SAndroid Build Coastguard Worker		eas_logger.debug('EAS_File.Play')
493*f81fb7c4SAndroid Build Coastguard Worker		if not self.prepared:
494*f81fb7c4SAndroid Build Coastguard Worker			self.Prepare()
495*f81fb7c4SAndroid Build Coastguard Worker		if max_time is not None:
496*f81fb7c4SAndroid Build Coastguard Worker			max_time += self.eas.GetRenderTime()
497*f81fb7c4SAndroid Build Coastguard Worker		while self.State() not in (EAS_STATE_STOPPED, EAS_STATE_ERROR, EAS_STATE_EMPTY):
498*f81fb7c4SAndroid Build Coastguard Worker			self.eas.Render()
499*f81fb7c4SAndroid Build Coastguard Worker			if max_time is not None:
500*f81fb7c4SAndroid Build Coastguard Worker				if self.eas.GetRenderTime() >= max_time:
501*f81fb7c4SAndroid Build Coastguard Worker					eas_logger.info('Max render time exceeded - stopping playback')
502*f81fb7c4SAndroid Build Coastguard Worker					self.Pause()
503*f81fb7c4SAndroid Build Coastguard Worker					self.eas.Render()
504*f81fb7c4SAndroid Build Coastguard Worker					break
505*f81fb7c4SAndroid Build Coastguard Worker
506*f81fb7c4SAndroid Build Coastguard Worker#---------------------------------------------------------------
507*f81fb7c4SAndroid Build Coastguard Worker# EAS_MIDIStream
508*f81fb7c4SAndroid Build Coastguard Worker#---------------------------------------------------------------
509*f81fb7c4SAndroid Build Coastguard Workerclass EAS_MIDIStream (EAS_Stream):
510*f81fb7c4SAndroid Build Coastguard Worker	def Write(self, data):
511*f81fb7c4SAndroid Build Coastguard Worker		"""Write data to MIDI stream."""
512*f81fb7c4SAndroid Build Coastguard Worker		with self.eas.lock:
513*f81fb7c4SAndroid Build Coastguard Worker			result = eas_dll.EAS_WriteMIDIStream(self.eas.handle, self.handle, data, len(data))
514*f81fb7c4SAndroid Build Coastguard Worker			if result:
515*f81fb7c4SAndroid Build Coastguard Worker				raise EAS_Exception(result, 'EAS_WriteMIDIStream error %d' % result, 'EAS_WriteMIDIStream')
516*f81fb7c4SAndroid Build Coastguard Worker
517*f81fb7c4SAndroid Build Coastguard Worker	def Close (self):
518*f81fb7c4SAndroid Build Coastguard Worker		"""Close MIDI stream."""
519*f81fb7c4SAndroid Build Coastguard Worker		if hasattr(self, 'handle'):
520*f81fb7c4SAndroid Build Coastguard Worker			with self.eas.lock:
521*f81fb7c4SAndroid Build Coastguard Worker				eas_logger.debug('Call EAS_CloseMIDIStream')
522*f81fb7c4SAndroid Build Coastguard Worker				result = eas_dll.EAS_CloseMIDIStream(self.eas.handle, self.handle)
523*f81fb7c4SAndroid Build Coastguard Worker				if result:
524*f81fb7c4SAndroid Build Coastguard Worker					raise EAS_Exception(result, 'EAS_CloseFile error %d' % result, 'EAS_CloseMIDIStream')
525*f81fb7c4SAndroid Build Coastguard Worker
526*f81fb7c4SAndroid Build Coastguard Worker				# remove file from the EAS object
527*f81fb7c4SAndroid Build Coastguard Worker				self.eas.audio_streams.remove(self)
528*f81fb7c4SAndroid Build Coastguard Worker
529*f81fb7c4SAndroid Build Coastguard Worker			# clean up references
530*f81fb7c4SAndroid Build Coastguard Worker			del self.handle
531*f81fb7c4SAndroid Build Coastguard Worker			del self.eas
532*f81fb7c4SAndroid Build Coastguard Worker
533*f81fb7c4SAndroid Build Coastguard Worker#---------------------------------------------------------------
534*f81fb7c4SAndroid Build Coastguard Worker# EAS_Config
535*f81fb7c4SAndroid Build Coastguard Worker#---------------------------------------------------------------
536*f81fb7c4SAndroid Build Coastguard Workerclass EAS_Config (Structure):
537*f81fb7c4SAndroid Build Coastguard Worker	_fields_ = [('libVersion', c_ulong),
538*f81fb7c4SAndroid Build Coastguard Worker				('checkedVersion', c_int),
539*f81fb7c4SAndroid Build Coastguard Worker				('maxVoices', c_long),
540*f81fb7c4SAndroid Build Coastguard Worker				('numChannels', c_long),
541*f81fb7c4SAndroid Build Coastguard Worker				('sampleRate', c_long),
542*f81fb7c4SAndroid Build Coastguard Worker				('mixBufferSize', c_long),
543*f81fb7c4SAndroid Build Coastguard Worker				('filterEnabled', c_int),
544*f81fb7c4SAndroid Build Coastguard Worker				('buildTimeStamp', c_ulong),
545*f81fb7c4SAndroid Build Coastguard Worker				('buildGUID', c_char_p)]
546*f81fb7c4SAndroid Build Coastguard Worker
547*f81fb7c4SAndroid Build Coastguard Worker#---------------------------------------------------------------
548*f81fb7c4SAndroid Build Coastguard Worker# EAS
549*f81fb7c4SAndroid Build Coastguard Worker#---------------------------------------------------------------
550*f81fb7c4SAndroid Build Coastguard Workerclass EAS (object):
551*f81fb7c4SAndroid Build Coastguard Worker	def __init__ (self, handle=None, dll_path=None, log_file=None):
552*f81fb7c4SAndroid Build Coastguard Worker		if eas_dll is None:
553*f81fb7c4SAndroid Build Coastguard Worker			InitEASModule(dll_path)
554*f81fb7c4SAndroid Build Coastguard Worker		if log_file is not None:
555*f81fb7c4SAndroid Build Coastguard Worker			eas_logger.addHandler(log_file)
556*f81fb7c4SAndroid Build Coastguard Worker		eas_logger.debug('EAS.__init__')
557*f81fb7c4SAndroid Build Coastguard Worker		self.Init(handle)
558*f81fb7c4SAndroid Build Coastguard Worker
559*f81fb7c4SAndroid Build Coastguard Worker	def __del__ (self):
560*f81fb7c4SAndroid Build Coastguard Worker		eas_logger.debug('EAS.__del__')
561*f81fb7c4SAndroid Build Coastguard Worker		self.Shutdown()
562*f81fb7c4SAndroid Build Coastguard Worker
563*f81fb7c4SAndroid Build Coastguard Worker	def Init (self, handle=None):
564*f81fb7c4SAndroid Build Coastguard Worker		"""Initializes the EAS Library."""
565*f81fb7c4SAndroid Build Coastguard Worker		eas_logger.debug('EAS.Init')
566*f81fb7c4SAndroid Build Coastguard Worker
567*f81fb7c4SAndroid Build Coastguard Worker		# if we are already initialized, shutdown first
568*f81fb7c4SAndroid Build Coastguard Worker		if hasattr(self, 'handle'):
569*f81fb7c4SAndroid Build Coastguard Worker			eas_logger.debug('EAS.Init called with library already initalized')
570*f81fb7c4SAndroid Build Coastguard Worker			self.ShutDown()
571*f81fb7c4SAndroid Build Coastguard Worker
572*f81fb7c4SAndroid Build Coastguard Worker		# setup the logging function
573*f81fb7c4SAndroid Build Coastguard Worker		eas_dll.SetLogCallback(LogCallback)
574*f81fb7c4SAndroid Build Coastguard Worker
575*f81fb7c4SAndroid Build Coastguard Worker		# create some members
576*f81fb7c4SAndroid Build Coastguard Worker		self.handle = c_void_p(0)
577*f81fb7c4SAndroid Build Coastguard Worker		self.audio_streams = []
578*f81fb7c4SAndroid Build Coastguard Worker		self.output_streams = []
579*f81fb7c4SAndroid Build Coastguard Worker		self.aux_mixer = None
580*f81fb7c4SAndroid Build Coastguard Worker
581*f81fb7c4SAndroid Build Coastguard Worker		# create a sync lock
582*f81fb7c4SAndroid Build Coastguard Worker		self.lock = threading.RLock()
583*f81fb7c4SAndroid Build Coastguard Worker		with self.lock:
584*f81fb7c4SAndroid Build Coastguard Worker			# set log callback
585*f81fb7c4SAndroid Build Coastguard Worker
586*f81fb7c4SAndroid Build Coastguard Worker			# get library configuration
587*f81fb7c4SAndroid Build Coastguard Worker			self.Config()
588*f81fb7c4SAndroid Build Coastguard Worker
589*f81fb7c4SAndroid Build Coastguard Worker			# initialize library
590*f81fb7c4SAndroid Build Coastguard Worker			if handle is None:
591*f81fb7c4SAndroid Build Coastguard Worker				self.do_shutdown = True
592*f81fb7c4SAndroid Build Coastguard Worker				eas_logger.debug('Call EAS_Init')
593*f81fb7c4SAndroid Build Coastguard Worker				result = eas_dll.EAS_Init(byref(self.handle))
594*f81fb7c4SAndroid Build Coastguard Worker				if result:
595*f81fb7c4SAndroid Build Coastguard Worker					raise EAS_Exception(result, 'EAS_Init error %d' % result, 'EAS_Init')
596*f81fb7c4SAndroid Build Coastguard Worker			else:
597*f81fb7c4SAndroid Build Coastguard Worker				self.do_shutdown = False
598*f81fb7c4SAndroid Build Coastguard Worker				self.handle = handle
599*f81fb7c4SAndroid Build Coastguard Worker
600*f81fb7c4SAndroid Build Coastguard Worker			# allocate audio buffer for rendering
601*f81fb7c4SAndroid Build Coastguard Worker			AudioBufferType = c_ubyte * (2 * self.config.mixBufferSize * self.config.numChannels)
602*f81fb7c4SAndroid Build Coastguard Worker			self.audio_buffer = AudioBufferType()
603*f81fb7c4SAndroid Build Coastguard Worker			self.buf_size = self.config.mixBufferSize
604*f81fb7c4SAndroid Build Coastguard Worker
605*f81fb7c4SAndroid Build Coastguard Worker	def Config (self):
606*f81fb7c4SAndroid Build Coastguard Worker		"""Retrieves the EAS library configuration"""
607*f81fb7c4SAndroid Build Coastguard Worker		if not hasattr(self, 'config'):
608*f81fb7c4SAndroid Build Coastguard Worker			eas_logger.debug('Call EAS_Config')
609*f81fb7c4SAndroid Build Coastguard Worker			eas_dll.EAS_Config.restype = POINTER(EAS_Config)
610*f81fb7c4SAndroid Build Coastguard Worker			self.config = eas_dll.EAS_Config()[0]
611*f81fb7c4SAndroid Build Coastguard Worker		eas_logger.debug("libVersion=%08x, maxVoices=%d, numChannels=%d, sampleRate = %d, mixBufferSize=%d" %
612*f81fb7c4SAndroid Build Coastguard Worker			(self.config.libVersion, self.config.maxVoices, self.config.numChannels, self.config.sampleRate, self.config.mixBufferSize))
613*f81fb7c4SAndroid Build Coastguard Worker
614*f81fb7c4SAndroid Build Coastguard Worker	def Shutdown (self):
615*f81fb7c4SAndroid Build Coastguard Worker		"""Shuts down the EAS library"""
616*f81fb7c4SAndroid Build Coastguard Worker		eas_logger.debug('EAS.Shutdown')
617*f81fb7c4SAndroid Build Coastguard Worker		if hasattr(self, 'handle'):
618*f81fb7c4SAndroid Build Coastguard Worker			with self.lock:
619*f81fb7c4SAndroid Build Coastguard Worker				# close audio streams
620*f81fb7c4SAndroid Build Coastguard Worker				audio_streams = self.audio_streams
621*f81fb7c4SAndroid Build Coastguard Worker				for f in audio_streams:
622*f81fb7c4SAndroid Build Coastguard Worker					eas_logger.warning('Stream was not closed before EAS_Shutdown')
623*f81fb7c4SAndroid Build Coastguard Worker					f.Close()
624*f81fb7c4SAndroid Build Coastguard Worker
625*f81fb7c4SAndroid Build Coastguard Worker				# close output streams
626*f81fb7c4SAndroid Build Coastguard Worker				output_streams = self.output_streams
627*f81fb7c4SAndroid Build Coastguard Worker				for s in output_streams:
628*f81fb7c4SAndroid Build Coastguard Worker					s.close()
629*f81fb7c4SAndroid Build Coastguard Worker
630*f81fb7c4SAndroid Build Coastguard Worker				# shutdown library
631*f81fb7c4SAndroid Build Coastguard Worker				if self.do_shutdown:
632*f81fb7c4SAndroid Build Coastguard Worker					eas_logger.debug('Call EAS_Shutdown')
633*f81fb7c4SAndroid Build Coastguard Worker					result = eas_dll.EAS_Shutdown(self.handle)
634*f81fb7c4SAndroid Build Coastguard Worker					if result:
635*f81fb7c4SAndroid Build Coastguard Worker						raise EAS_Exception(result, 'EAS_Shutdown error %d' % result, 'EAS_Shutdown')
636*f81fb7c4SAndroid Build Coastguard Worker				del self.handle
637*f81fb7c4SAndroid Build Coastguard Worker
638*f81fb7c4SAndroid Build Coastguard Worker	def OpenFile (self, path):
639*f81fb7c4SAndroid Build Coastguard Worker		"""Opens an audio file to be played by the EAS library and
640*f81fb7c4SAndroid Build Coastguard Worker		returns an EAS_File object
641*f81fb7c4SAndroid Build Coastguard Worker
642*f81fb7c4SAndroid Build Coastguard Worker		Arguments:
643*f81fb7c4SAndroid Build Coastguard Worker			path - path to audio file
644*f81fb7c4SAndroid Build Coastguard Worker
645*f81fb7c4SAndroid Build Coastguard Worker		Returns:
646*f81fb7c4SAndroid Build Coastguard Worker			EAS_File
647*f81fb7c4SAndroid Build Coastguard Worker
648*f81fb7c4SAndroid Build Coastguard Worker		"""
649*f81fb7c4SAndroid Build Coastguard Worker		with self.lock:
650*f81fb7c4SAndroid Build Coastguard Worker			eas_logger.debug('Call EAS_OpenFile for file: %s' % path)
651*f81fb7c4SAndroid Build Coastguard Worker			stream_handle = c_void_p(0)
652*f81fb7c4SAndroid Build Coastguard Worker			result = eas_dll.EAS_OpenFile(self.handle, path, byref(stream_handle))
653*f81fb7c4SAndroid Build Coastguard Worker			if result:
654*f81fb7c4SAndroid Build Coastguard Worker				raise EAS_Exception(result, 'EAS_OpenFile error %d on file %s' % (result, path), 'EAS_OpenFile')
655*f81fb7c4SAndroid Build Coastguard Worker
656*f81fb7c4SAndroid Build Coastguard Worker			# create file object and save in list
657*f81fb7c4SAndroid Build Coastguard Worker			stream = EAS_File(path, stream_handle, self)
658*f81fb7c4SAndroid Build Coastguard Worker			self.audio_streams.append(stream)
659*f81fb7c4SAndroid Build Coastguard Worker			return stream
660*f81fb7c4SAndroid Build Coastguard Worker
661*f81fb7c4SAndroid Build Coastguard Worker	def OpenMIDIStream (self, stream=None):
662*f81fb7c4SAndroid Build Coastguard Worker		"""Opens a MIDI stream.
663*f81fb7c4SAndroid Build Coastguard Worker
664*f81fb7c4SAndroid Build Coastguard Worker		Arguments:
665*f81fb7c4SAndroid Build Coastguard Worker			stream - open stream object. If None, a new synth
666*f81fb7c4SAndroid Build Coastguard Worker			is created.
667*f81fb7c4SAndroid Build Coastguard Worker
668*f81fb7c4SAndroid Build Coastguard Worker		Returns:
669*f81fb7c4SAndroid Build Coastguard Worker			EAS_MIDIStream
670*f81fb7c4SAndroid Build Coastguard Worker
671*f81fb7c4SAndroid Build Coastguard Worker		"""
672*f81fb7c4SAndroid Build Coastguard Worker		with self.lock:
673*f81fb7c4SAndroid Build Coastguard Worker			eas_logger.debug('Call EAS_OpenMIDIStream')
674*f81fb7c4SAndroid Build Coastguard Worker			stream_handle = c_void_p(0)
675*f81fb7c4SAndroid Build Coastguard Worker			if stream.handle is not None:
676*f81fb7c4SAndroid Build Coastguard Worker				result = eas_dll.EAS_OpenMIDIStream(self.handle, byref(stream_handle), stream.handle)
677*f81fb7c4SAndroid Build Coastguard Worker			else:
678*f81fb7c4SAndroid Build Coastguard Worker				result = eas_dll.EAS_OpenMIDIStream(self.handle, byref(stream_handle), 0)
679*f81fb7c4SAndroid Build Coastguard Worker			if result:
680*f81fb7c4SAndroid Build Coastguard Worker				raise EAS_Exception(result, 'EAS_OpenMIDIStream error %d' % result, 'EAS_OpenMIDIStream')
681*f81fb7c4SAndroid Build Coastguard Worker
682*f81fb7c4SAndroid Build Coastguard Worker			# create stream object and save in list
683*f81fb7c4SAndroid Build Coastguard Worker			stream = EAS_MIDIStream(stream_handle, self)
684*f81fb7c4SAndroid Build Coastguard Worker			self.audio_streams.append(stream)
685*f81fb7c4SAndroid Build Coastguard Worker			return stream
686*f81fb7c4SAndroid Build Coastguard Worker
687*f81fb7c4SAndroid Build Coastguard Worker	def OpenToneControlStream (self, path):
688*f81fb7c4SAndroid Build Coastguard Worker		"""Opens an MMAPI tone control file to be played by the EAS
689*f81fb7c4SAndroid Build Coastguard Worker		library and returns an EAS_File object
690*f81fb7c4SAndroid Build Coastguard Worker
691*f81fb7c4SAndroid Build Coastguard Worker		Arguments:
692*f81fb7c4SAndroid Build Coastguard Worker			path - path to audio file
693*f81fb7c4SAndroid Build Coastguard Worker
694*f81fb7c4SAndroid Build Coastguard Worker		Returns:
695*f81fb7c4SAndroid Build Coastguard Worker			EAS_File
696*f81fb7c4SAndroid Build Coastguard Worker
697*f81fb7c4SAndroid Build Coastguard Worker		"""
698*f81fb7c4SAndroid Build Coastguard Worker		with self.lock:
699*f81fb7c4SAndroid Build Coastguard Worker			eas_logger.debug('Call EAS_MMAPIToneControl for file: %s' % path)
700*f81fb7c4SAndroid Build Coastguard Worker			stream_handle = c_void_p(0)
701*f81fb7c4SAndroid Build Coastguard Worker			result = eas_dll.EAS_MMAPIToneControl(self.handle, path, byref(stream_handle))
702*f81fb7c4SAndroid Build Coastguard Worker			if result:
703*f81fb7c4SAndroid Build Coastguard Worker				raise EAS_Exception(result, 'EAS_MMAPIToneControl error %d on file %s' % (result, path), 'EAS_OpenToneControlStream')
704*f81fb7c4SAndroid Build Coastguard Worker
705*f81fb7c4SAndroid Build Coastguard Worker			# create file object and save in list
706*f81fb7c4SAndroid Build Coastguard Worker			stream = EAS_File(path, stream_handle, self)
707*f81fb7c4SAndroid Build Coastguard Worker			self.audio_streams.append(stream)
708*f81fb7c4SAndroid Build Coastguard Worker			return stream
709*f81fb7c4SAndroid Build Coastguard Worker
710*f81fb7c4SAndroid Build Coastguard Worker	def Attach (self, stream):
711*f81fb7c4SAndroid Build Coastguard Worker		"""Attach a file or output device to the EAS output.
712*f81fb7c4SAndroid Build Coastguard Worker
713*f81fb7c4SAndroid Build Coastguard Worker		The stream object must support the following methods as
714*f81fb7c4SAndroid Build Coastguard Worker		defined in the Python wave module:
715*f81fb7c4SAndroid Build Coastguard Worker			close()
716*f81fb7c4SAndroid Build Coastguard Worker			setparams()
717*f81fb7c4SAndroid Build Coastguard Worker			writeframesraw()
718*f81fb7c4SAndroid Build Coastguard Worker
719*f81fb7c4SAndroid Build Coastguard Worker		Arguments:
720*f81fb7c4SAndroid Build Coastguard Worker			stream - open wave object
721*f81fb7c4SAndroid Build Coastguard Worker
722*f81fb7c4SAndroid Build Coastguard Worker		"""
723*f81fb7c4SAndroid Build Coastguard Worker		self.output_streams.append(stream)
724*f81fb7c4SAndroid Build Coastguard Worker		stream.setparams((self.config.numChannels, 2, self.config.sampleRate, 0, 'NONE', None))
725*f81fb7c4SAndroid Build Coastguard Worker
726*f81fb7c4SAndroid Build Coastguard Worker	def Detach (self, stream):
727*f81fb7c4SAndroid Build Coastguard Worker		"""Detach a file or output device from the EAS output. See
728*f81fb7c4SAndroid Build Coastguard Worker		EAS.Attach for more details. It is the responsibility of
729*f81fb7c4SAndroid Build Coastguard Worker		the caller to close the wave file or stream.
730*f81fb7c4SAndroid Build Coastguard Worker
731*f81fb7c4SAndroid Build Coastguard Worker		Arguments:
732*f81fb7c4SAndroid Build Coastguard Worker			stream - open and attached wave object
733*f81fb7c4SAndroid Build Coastguard Worker		"""
734*f81fb7c4SAndroid Build Coastguard Worker		self.output_streams.remove(stream)
735*f81fb7c4SAndroid Build Coastguard Worker
736*f81fb7c4SAndroid Build Coastguard Worker	def StartWave (self, dev_num=0, sampleRate=None, maxBufSize=None):
737*f81fb7c4SAndroid Build Coastguard Worker		"""Route the audio output to the indicated wave device. Note
738*f81fb7c4SAndroid Build Coastguard Worker		that this can cause EASDLL.EAS_RenderWaveOut to return an
739*f81fb7c4SAndroid Build Coastguard Worker		error code if all the output buffers are full. In this case,
740*f81fb7c4SAndroid Build Coastguard Worker		the render thread should sleep a bit and try again.
741*f81fb7c4SAndroid Build Coastguard Worker		Unfortunately, due to the nature of the MMSYSTEM interface,
742*f81fb7c4SAndroid Build Coastguard Worker		there is no simple way to suspend the render thread.
743*f81fb7c4SAndroid Build Coastguard Worker
744*f81fb7c4SAndroid Build Coastguard Worker		"""
745*f81fb7c4SAndroid Build Coastguard Worker		if sampleRate == None:
746*f81fb7c4SAndroid Build Coastguard Worker			sampleRate = self.config.sampleRate
747*f81fb7c4SAndroid Build Coastguard Worker		if maxBufSize == None:
748*f81fb7c4SAndroid Build Coastguard Worker			maxBufSize = self.config.mixBufferSize
749*f81fb7c4SAndroid Build Coastguard Worker		with self.lock:
750*f81fb7c4SAndroid Build Coastguard Worker			result = eas_dll.OpenWaveOutDevice(dev_num, sampleRate, maxBufSize)
751*f81fb7c4SAndroid Build Coastguard Worker			if result:
752*f81fb7c4SAndroid Build Coastguard Worker				raise EAS_Exception(result, 'OpenWaveOutDevice error %d' % result, 'OpenWaveOutDevice')
753*f81fb7c4SAndroid Build Coastguard Worker
754*f81fb7c4SAndroid Build Coastguard Worker	def StopWave (self):
755*f81fb7c4SAndroid Build Coastguard Worker		"""Stop routing audio output to the audio device."""
756*f81fb7c4SAndroid Build Coastguard Worker		with self.lock:
757*f81fb7c4SAndroid Build Coastguard Worker			result = eas_dll.CloseWaveOutDevice()
758*f81fb7c4SAndroid Build Coastguard Worker			if result:
759*f81fb7c4SAndroid Build Coastguard Worker				raise EAS_Exception(result, 'CloseWaveOutDevice error %d' % result, 'CloseWaveOutDevice')
760*f81fb7c4SAndroid Build Coastguard Worker
761*f81fb7c4SAndroid Build Coastguard Worker	def Render (self, count=None, secs=None):
762*f81fb7c4SAndroid Build Coastguard Worker		"""Calls EAS_Render to render audio.
763*f81fb7c4SAndroid Build Coastguard Worker
764*f81fb7c4SAndroid Build Coastguard Worker		Arguments
765*f81fb7c4SAndroid Build Coastguard Worker			count - number of buffers to render
766*f81fb7c4SAndroid Build Coastguard Worker			secs - number of seconds to render
767*f81fb7c4SAndroid Build Coastguard Worker
768*f81fb7c4SAndroid Build Coastguard Worker		If both count and secs are None, render a single buffer.
769*f81fb7c4SAndroid Build Coastguard Worker
770*f81fb7c4SAndroid Build Coastguard Worker		"""
771*f81fb7c4SAndroid Build Coastguard Worker
772*f81fb7c4SAndroid Build Coastguard Worker		# determine number of buffers to render
773*f81fb7c4SAndroid Build Coastguard Worker		if count is None:
774*f81fb7c4SAndroid Build Coastguard Worker			if secs is not None:
775*f81fb7c4SAndroid Build Coastguard Worker				count = int(secs * float(self.config.sampleRate) / float(self.buf_size) + 0.5)
776*f81fb7c4SAndroid Build Coastguard Worker			else:
777*f81fb7c4SAndroid Build Coastguard Worker				count = 1
778*f81fb7c4SAndroid Build Coastguard Worker
779*f81fb7c4SAndroid Build Coastguard Worker		# render buffers
780*f81fb7c4SAndroid Build Coastguard Worker		eas_logger.debug('rendering %d buffers' % count)
781*f81fb7c4SAndroid Build Coastguard Worker		samplesRendered = c_long(0)
782*f81fb7c4SAndroid Build Coastguard Worker		with self.lock:
783*f81fb7c4SAndroid Build Coastguard Worker			for c in range(count):
784*f81fb7c4SAndroid Build Coastguard Worker				# render a buffer of audio
785*f81fb7c4SAndroid Build Coastguard Worker				eas_logger.debug('rendering buffer')
786*f81fb7c4SAndroid Build Coastguard Worker				while 1:
787*f81fb7c4SAndroid Build Coastguard Worker					if self.aux_mixer is None:
788*f81fb7c4SAndroid Build Coastguard Worker						result = eas_dll.EAS_RenderWaveOut(self.handle, byref(self.audio_buffer), self.buf_size, byref(samplesRendered))
789*f81fb7c4SAndroid Build Coastguard Worker					else:
790*f81fb7c4SAndroid Build Coastguard Worker						result = eas_dll.EAS_RenderAuxMixer(self.handle, byref(self.audio_buffer), byref(samplesRendered))
791*f81fb7c4SAndroid Build Coastguard Worker
792*f81fb7c4SAndroid Build Coastguard Worker					if result == 0:
793*f81fb7c4SAndroid Build Coastguard Worker						break;
794*f81fb7c4SAndroid Build Coastguard Worker					if result == EAS_BUFFER_FULL:
795*f81fb7c4SAndroid Build Coastguard Worker						time.sleep(0.01)
796*f81fb7c4SAndroid Build Coastguard Worker					else:
797*f81fb7c4SAndroid Build Coastguard Worker						raise EAS_Exception(result, 'EAS_Render error %d' % result, 'EAS_Render')
798*f81fb7c4SAndroid Build Coastguard Worker
799*f81fb7c4SAndroid Build Coastguard Worker				# output to attached streams
800*f81fb7c4SAndroid Build Coastguard Worker				for s in self.output_streams:
801*f81fb7c4SAndroid Build Coastguard Worker					s.writeframesraw(self.audio_buffer)
802*f81fb7c4SAndroid Build Coastguard Worker
803*f81fb7c4SAndroid Build Coastguard Worker	def GetRenderTime (self):
804*f81fb7c4SAndroid Build Coastguard Worker		"""Get the render time in seconds."""
805*f81fb7c4SAndroid Build Coastguard Worker		eas_logger.debug('Call EAS_GetRenderTime')
806*f81fb7c4SAndroid Build Coastguard Worker		msecs = c_int(0)
807*f81fb7c4SAndroid Build Coastguard Worker		with self.lock:
808*f81fb7c4SAndroid Build Coastguard Worker			result = eas_dll.EAS_GetRenderTime(self.handle, byref(msecs))
809*f81fb7c4SAndroid Build Coastguard Worker			if result:
810*f81fb7c4SAndroid Build Coastguard Worker				raise EAS_Exception(result, 'EAS_GetRenderTime error %d' % result, 'EAS_GetRenderTime')
811*f81fb7c4SAndroid Build Coastguard Worker		msecs = float(msecs.value) / 1000
812*f81fb7c4SAndroid Build Coastguard Worker		eas_logger.debug('EAS_GetRenderTime: time=%.3f' % msecs)
813*f81fb7c4SAndroid Build Coastguard Worker		return msecs
814*f81fb7c4SAndroid Build Coastguard Worker
815*f81fb7c4SAndroid Build Coastguard Worker	def SetVolume (self, volume):
816*f81fb7c4SAndroid Build Coastguard Worker		"""Set the master volume"""
817*f81fb7c4SAndroid Build Coastguard Worker		eas_logger.debug('Call EAS_SetVolume: volume=%d' % volume)
818*f81fb7c4SAndroid Build Coastguard Worker		with self.lock:
819*f81fb7c4SAndroid Build Coastguard Worker			result = eas_dll.EAS_SetVolume(self.handle, 0, volume)
820*f81fb7c4SAndroid Build Coastguard Worker			if result:
821*f81fb7c4SAndroid Build Coastguard Worker					raise EAS_Exception(result, 'EAS_SetVolume error %d' % result, 'EAS_SetVolume')
822*f81fb7c4SAndroid Build Coastguard Worker
823*f81fb7c4SAndroid Build Coastguard Worker	def GetVolume (self):
824*f81fb7c4SAndroid Build Coastguard Worker		"""Get the stream volume."""
825*f81fb7c4SAndroid Build Coastguard Worker		eas_logger.debug('Call EAS_GetVolume')
826*f81fb7c4SAndroid Build Coastguard Worker		volume = c_int(0)
827*f81fb7c4SAndroid Build Coastguard Worker		with self.lock:
828*f81fb7c4SAndroid Build Coastguard Worker			result = eas_dll.EAS_GetVolume(self.handle, 0, byref(volume))
829*f81fb7c4SAndroid Build Coastguard Worker			if result:
830*f81fb7c4SAndroid Build Coastguard Worker				raise EAS_Exception(result, 'EAS_GetVolume error %d' % result, 'EAS_GetVolume')
831*f81fb7c4SAndroid Build Coastguard Worker		eas_logger.debug('EAS_GetVolume: volume=%d' % volume.value)
832*f81fb7c4SAndroid Build Coastguard Worker		return volume.value
833*f81fb7c4SAndroid Build Coastguard Worker
834*f81fb7c4SAndroid Build Coastguard Worker	def SetPolyphony (self, polyphony, synth_num=0):
835*f81fb7c4SAndroid Build Coastguard Worker		"""Set the polyphony of a synth."""
836*f81fb7c4SAndroid Build Coastguard Worker		eas_logger.debug('Call EAS_SetSynthPolyphony: synth_num=%d, polyphony=%d' % (synth_num, polyphony))
837*f81fb7c4SAndroid Build Coastguard Worker		with self.lock:
838*f81fb7c4SAndroid Build Coastguard Worker			result = eas_dll.EAS_SetSynthPolyphony(self.handle, synth_num, polyphony)
839*f81fb7c4SAndroid Build Coastguard Worker			if result:
840*f81fb7c4SAndroid Build Coastguard Worker				raise EAS_Exception(result, 'EAS_SetSynthPolyphony error %d on synth %d' % (result, synth_num), 'EAS_SetPolyphony')
841*f81fb7c4SAndroid Build Coastguard Worker
842*f81fb7c4SAndroid Build Coastguard Worker	def GetPolyphony (self, synth_num=0):
843*f81fb7c4SAndroid Build Coastguard Worker		"""Get the polyphony of a synth."""
844*f81fb7c4SAndroid Build Coastguard Worker		eas_logger.debug('Call EAS_GetSynthPolyphony: synth_num=%d' % synth_num)
845*f81fb7c4SAndroid Build Coastguard Worker		polyphony = c_int(0)
846*f81fb7c4SAndroid Build Coastguard Worker		with self.lock:
847*f81fb7c4SAndroid Build Coastguard Worker			result = eas_dll.EAS_GetSynthPolyphony(self.handle, synth_num, byref(polyphony))
848*f81fb7c4SAndroid Build Coastguard Worker			if result:
849*f81fb7c4SAndroid Build Coastguard Worker				raise EAS_Exception(result, 'EAS_GetSynthPolyphony error %d on synth %d' % (result, synth_num), 'EAS_GetPolyphony')
850*f81fb7c4SAndroid Build Coastguard Worker		eas_logger.debug('Call EAS_GetSynthPolyphony: synth_num=%d, polyphony=%d' % (synth_num, polyphony.value))
851*f81fb7c4SAndroid Build Coastguard Worker		return polyphony.value
852*f81fb7c4SAndroid Build Coastguard Worker
853*f81fb7c4SAndroid Build Coastguard Worker	def SetMaxLoad (self, max_load):
854*f81fb7c4SAndroid Build Coastguard Worker		"""Set the maximum parser load."""
855*f81fb7c4SAndroid Build Coastguard Worker		eas_logger.debug('Call EAS_SetMaxLoad: max_load=%d' % max_load)
856*f81fb7c4SAndroid Build Coastguard Worker		with self.lock:
857*f81fb7c4SAndroid Build Coastguard Worker			result = eas_dll.EAS_SetMaxLoad(self.handle, max_load)
858*f81fb7c4SAndroid Build Coastguard Worker			if result:
859*f81fb7c4SAndroid Build Coastguard Worker				raise EAS_Exception(result, 'EAS_SetMaxLoad error %d' % result, 'EAS_SetMaxLoad')
860*f81fb7c4SAndroid Build Coastguard Worker
861*f81fb7c4SAndroid Build Coastguard Worker	def SetParameter (self, module, param, value):
862*f81fb7c4SAndroid Build Coastguard Worker		"""Set a module parameter."""
863*f81fb7c4SAndroid Build Coastguard Worker		eas_logger.debug('Call EAS_SetParameter: module=%d, param=%d, value=%d' % (module, param, value))
864*f81fb7c4SAndroid Build Coastguard Worker		with self.lock:
865*f81fb7c4SAndroid Build Coastguard Worker			result = eas_dll.EAS_SetParameter(self.handle, module, param, value)
866*f81fb7c4SAndroid Build Coastguard Worker			if result:
867*f81fb7c4SAndroid Build Coastguard Worker				raise EAS_Exception(result, 'EAS_SetParameter error %d (param=%d, value=%d)' % (result, param, value), 'EAS_SetParameter')
868*f81fb7c4SAndroid Build Coastguard Worker
869*f81fb7c4SAndroid Build Coastguard Worker	def GetParameter (self, module, param):
870*f81fb7c4SAndroid Build Coastguard Worker		"""Get the polyphony of a synth."""
871*f81fb7c4SAndroid Build Coastguard Worker		eas_logger.debug('Call EAS_GetParameter: module=%d, param=%d' % (module, param))
872*f81fb7c4SAndroid Build Coastguard Worker		value = c_int(0)
873*f81fb7c4SAndroid Build Coastguard Worker		with self.lock:
874*f81fb7c4SAndroid Build Coastguard Worker			result = eas_dll.EAS_GetParameter(self.handle, module, param, byref(value))
875*f81fb7c4SAndroid Build Coastguard Worker			if result:
876*f81fb7c4SAndroid Build Coastguard Worker				raise EAS_Exception(result, 'EAS_SetParameter error %d (param=%d)' % (result, param), 'EAS_GetParameter')
877*f81fb7c4SAndroid Build Coastguard Worker		eas_logger.debug('Call EAS_SetParameter: module=%d, param=%d, value=%d' % (module, param, value.value))
878*f81fb7c4SAndroid Build Coastguard Worker		return value.value
879*f81fb7c4SAndroid Build Coastguard Worker
880*f81fb7c4SAndroid Build Coastguard Worker	def SelectLib (self, test_lib=False):
881*f81fb7c4SAndroid Build Coastguard Worker		eas_logger.debug('Call EAS_SelectLib: test_lib=%s' % test_lib)
882*f81fb7c4SAndroid Build Coastguard Worker		easdll = cdll.LoadLibrary('EASDLL')
883*f81fb7c4SAndroid Build Coastguard Worker		with self.lock:
884*f81fb7c4SAndroid Build Coastguard Worker			result = eas_dll.EAS_SelectLib(self.handle, 0, test_lib)
885*f81fb7c4SAndroid Build Coastguard Worker			if result:
886*f81fb7c4SAndroid Build Coastguard Worker				raise EAS_Exception(result, 'EAS_SelectLib error %d' % result, 'EAS_SelectLib')
887*f81fb7c4SAndroid Build Coastguard Worker
888*f81fb7c4SAndroid Build Coastguard Worker	def LoadDLSCollection (self, path):
889*f81fb7c4SAndroid Build Coastguard Worker		eas_logger.debug('Call EAS_LoadDLSCollection: lib_path=%s' % path)
890*f81fb7c4SAndroid Build Coastguard Worker		with self.lock:
891*f81fb7c4SAndroid Build Coastguard Worker			result = eas_dll.EAS_LoadDLSCollection(self.handle, 0, path)
892*f81fb7c4SAndroid Build Coastguard Worker			if result:
893*f81fb7c4SAndroid Build Coastguard Worker				raise EAS_Exception(result, 'EAS_LoadDLSCollection error %d lib %s' % (result, path), 'EAS_LoadDLSCollection')
894*f81fb7c4SAndroid Build Coastguard Worker
895*f81fb7c4SAndroid Build Coastguard Worker	def SetAuxMixerHook (self, aux_mixer):
896*f81fb7c4SAndroid Build Coastguard Worker
897*f81fb7c4SAndroid Build Coastguard Worker		# if aux mixer has bigger buffer, re-allocate buffer
898*f81fb7c4SAndroid Build Coastguard Worker		if (aux_mixer is not None) and (aux_mixer.buf_size > self.config.mixBufferSize):
899*f81fb7c4SAndroid Build Coastguard Worker			buf_size = aux_mixer.buf_size
900*f81fb7c4SAndroid Build Coastguard Worker		else:
901*f81fb7c4SAndroid Build Coastguard Worker			buf_size = self.config.mixBufferSize
902*f81fb7c4SAndroid Build Coastguard Worker
903*f81fb7c4SAndroid Build Coastguard Worker		# allocate audio buffer for rendering
904*f81fb7c4SAndroid Build Coastguard Worker		AudioBufferType = c_ubyte * (2 * buf_size * self.config.numChannels)
905*f81fb7c4SAndroid Build Coastguard Worker		self.audio_buffer = AudioBufferType()
906*f81fb7c4SAndroid Build Coastguard Worker		self.buf_size = buf_size
907*f81fb7c4SAndroid Build Coastguard Worker		self.aux_mixer = aux_mixer
908*f81fb7c4SAndroid Build Coastguard Worker
909*f81fb7c4SAndroid Build Coastguard Worker	def SetDebugLevel (self, level=3):
910*f81fb7c4SAndroid Build Coastguard Worker		"""Sets the EAS debug level."""
911*f81fb7c4SAndroid Build Coastguard Worker		with self.lock:
912*f81fb7c4SAndroid Build Coastguard Worker			eas_logger.debug('Call EAS_SetDebugLevel')
913*f81fb7c4SAndroid Build Coastguard Worker			eas_dll.EAS_DLLSetDebugLevel(self.handle, level)
914*f81fb7c4SAndroid Build Coastguard Worker
915*f81fb7c4SAndroid Build Coastguard Worker#---------------------------------------------------------------
916*f81fb7c4SAndroid Build Coastguard Worker# EASAuxMixer
917*f81fb7c4SAndroid Build Coastguard Worker#---------------------------------------------------------------
918*f81fb7c4SAndroid Build Coastguard Workerclass EASAuxMixer (object):
919*f81fb7c4SAndroid Build Coastguard Worker	def __init__ (self, eas=None, num_streams=3, sample_rate=44100, max_sample_rate=44100):
920*f81fb7c4SAndroid Build Coastguard Worker		eas_logger.debug('EASAuxMixer.__init__')
921*f81fb7c4SAndroid Build Coastguard Worker		self.Init(eas, num_streams, sample_rate, max_sample_rate)
922*f81fb7c4SAndroid Build Coastguard Worker
923*f81fb7c4SAndroid Build Coastguard Worker	def __del__ (self):
924*f81fb7c4SAndroid Build Coastguard Worker		eas_logger.debug('EASAuxMixer.__del__')
925*f81fb7c4SAndroid Build Coastguard Worker		self.Shutdown()
926*f81fb7c4SAndroid Build Coastguard Worker
927*f81fb7c4SAndroid Build Coastguard Worker	def Init (self, eas=None, num_streams=3, sample_rate=44100, max_sample_rate=44100):
928*f81fb7c4SAndroid Build Coastguard Worker		"""Initializes the EAS Auxilliary Mixer."""
929*f81fb7c4SAndroid Build Coastguard Worker		eas_logger.debug('EASAuxMixer.Init')
930*f81fb7c4SAndroid Build Coastguard Worker
931*f81fb7c4SAndroid Build Coastguard Worker		if hasattr(self, 'eas'):
932*f81fb7c4SAndroid Build Coastguard Worker			raise EAS_Exception(-1, 'EASAuxMixer already initialized', 'EASAuxMixer.Init')
933*f81fb7c4SAndroid Build Coastguard Worker
934*f81fb7c4SAndroid Build Coastguard Worker		# initialize EAS, if necessary
935*f81fb7c4SAndroid Build Coastguard Worker		if eas is None:
936*f81fb7c4SAndroid Build Coastguard Worker			eas_logger.debug('No EAS handle --- initializing EAS')
937*f81fb7c4SAndroid Build Coastguard Worker			eas = EAS()
938*f81fb7c4SAndroid Build Coastguard Worker			self.alloc_eas = True
939*f81fb7c4SAndroid Build Coastguard Worker		else:
940*f81fb7c4SAndroid Build Coastguard Worker			self.alloc_eas = False
941*f81fb7c4SAndroid Build Coastguard Worker		self.eas = eas
942*f81fb7c4SAndroid Build Coastguard Worker
943*f81fb7c4SAndroid Build Coastguard Worker		# initialize library
944*f81fb7c4SAndroid Build Coastguard Worker		eas_logger.debug('Call EAS_InitAuxMixer')
945*f81fb7c4SAndroid Build Coastguard Worker		buf_size = c_int(0)
946*f81fb7c4SAndroid Build Coastguard Worker		result = eas_dll.EAS_InitAuxMixer(eas.handle, num_streams, sample_rate, max_sample_rate, byref(buf_size))
947*f81fb7c4SAndroid Build Coastguard Worker		if result:
948*f81fb7c4SAndroid Build Coastguard Worker			raise EAS_Exception(result, 'EAS_InitAuxMixer error %d' % result, 'EAS_InitAuxMixer')
949*f81fb7c4SAndroid Build Coastguard Worker		self.buf_size = buf_size.value
950*f81fb7c4SAndroid Build Coastguard Worker		self.streams = []
951*f81fb7c4SAndroid Build Coastguard Worker		eas.SetAuxMixerHook(self)
952*f81fb7c4SAndroid Build Coastguard Worker
953*f81fb7c4SAndroid Build Coastguard Worker	def Shutdown (self):
954*f81fb7c4SAndroid Build Coastguard Worker		"""Shuts down the EAS Auxilliary Mixer"""
955*f81fb7c4SAndroid Build Coastguard Worker		eas_logger.debug('EASAuxMixer.Shutdown')
956*f81fb7c4SAndroid Build Coastguard Worker		if not hasattr(self, 'eas'):
957*f81fb7c4SAndroid Build Coastguard Worker			return
958*f81fb7c4SAndroid Build Coastguard Worker
959*f81fb7c4SAndroid Build Coastguard Worker		with self.eas.lock:
960*f81fb7c4SAndroid Build Coastguard Worker			if len(self.streams):
961*f81fb7c4SAndroid Build Coastguard Worker				eas_logger.warning('Stream was not closed before EAS_ShutdownAuxMixer')
962*f81fb7c4SAndroid Build Coastguard Worker				for stream in self.streams:
963*f81fb7c4SAndroid Build Coastguard Worker					self.CloseStream(stream)
964*f81fb7c4SAndroid Build Coastguard Worker
965*f81fb7c4SAndroid Build Coastguard Worker			self.eas.SetAuxMixerHook(None)
966*f81fb7c4SAndroid Build Coastguard Worker
967*f81fb7c4SAndroid Build Coastguard Worker			# shutdown library
968*f81fb7c4SAndroid Build Coastguard Worker			eas_logger.debug('Call EAS_ShutdownAuxMixer')
969*f81fb7c4SAndroid Build Coastguard Worker			result = eas_dll.EAS_ShutdownAuxMixer(self.eas.handle)
970*f81fb7c4SAndroid Build Coastguard Worker			if result:
971*f81fb7c4SAndroid Build Coastguard Worker				raise EAS_Exception(result, 'EAS_ShutdownAuxMixer error %d' % result, 'EAS_ShutdownAuxMixer')
972*f81fb7c4SAndroid Build Coastguard Worker
973*f81fb7c4SAndroid Build Coastguard Worker			# if we created the EAS reference here, shut it down
974*f81fb7c4SAndroid Build Coastguard Worker			if self.alloc_eas:
975*f81fb7c4SAndroid Build Coastguard Worker				self.eas.Shutdown()
976*f81fb7c4SAndroid Build Coastguard Worker				self.alloc_eas = False
977*f81fb7c4SAndroid Build Coastguard Worker			del self.eas
978*f81fb7c4SAndroid Build Coastguard Worker
979*f81fb7c4SAndroid Build Coastguard Worker	def OpenStream (self, decoder_func, inst_data, sample_rate, num_channels):
980*f81fb7c4SAndroid Build Coastguard Worker		"""Opens an audio file to be played by the JET library and
981*f81fb7c4SAndroid Build Coastguard Worker		returns a JET_File object
982*f81fb7c4SAndroid Build Coastguard Worker
983*f81fb7c4SAndroid Build Coastguard Worker		Arguments:
984*f81fb7c4SAndroid Build Coastguard Worker			callback - callback function to decode more audio
985*f81fb7c4SAndroid Build Coastguard Worker
986*f81fb7c4SAndroid Build Coastguard Worker		"""
987*f81fb7c4SAndroid Build Coastguard Worker		with self.eas.lock:
988*f81fb7c4SAndroid Build Coastguard Worker			eas_logger.debug('Call EAS_OpenAudioStream')
989*f81fb7c4SAndroid Build Coastguard Worker			decoder_func = EAS_DECODER_FUNC(decoder_func)
990*f81fb7c4SAndroid Build Coastguard Worker			stream_handle = c_void_p(0)
991*f81fb7c4SAndroid Build Coastguard Worker			result = eas_dll.EAS_OpenAudioStream(self.eas.handle, decoder_func, inst_data, sample_rate, num_channels, stream_handle)
992*f81fb7c4SAndroid Build Coastguard Worker			if result:
993*f81fb7c4SAndroid Build Coastguard Worker				raise EAS_Exception(result, 'EAS_OpenAudioStream error %d on file %s' % (result, path), 'EAS_OpenAudioStream')
994*f81fb7c4SAndroid Build Coastguard Worker			self.streams.add(stream_handle)
995*f81fb7c4SAndroid Build Coastguard Worker			return stream_handle
996*f81fb7c4SAndroid Build Coastguard Worker
997*f81fb7c4SAndroid Build Coastguard Worker	def CloseStream (self, stream_handle):
998*f81fb7c4SAndroid Build Coastguard Worker		"""Closes an open audio stream."""
999*f81fb7c4SAndroid Build Coastguard Worker		with self.eas.lock:
1000*f81fb7c4SAndroid Build Coastguard Worker			eas_logger.debug('Call EAS_CloseAudioStream')
1001*f81fb7c4SAndroid Build Coastguard Worker			result = eas_dll.JET_CloseFile(self.eas.handle, stream_handle)
1002*f81fb7c4SAndroid Build Coastguard Worker			if result:
1003*f81fb7c4SAndroid Build Coastguard Worker				raise EAS_Exception(result, 'EAS_CloseAudioStream error %d' % result, 'EAS_CloseAudioStream')
1004*f81fb7c4SAndroid Build Coastguard Worker
1005*f81fb7c4SAndroid Build Coastguard Worker#---------------------------------------------------------------
1006*f81fb7c4SAndroid Build Coastguard Worker# JET_Status
1007*f81fb7c4SAndroid Build Coastguard Worker#---------------------------------------------------------------
1008*f81fb7c4SAndroid Build Coastguard Workerclass JET_Status (Structure):
1009*f81fb7c4SAndroid Build Coastguard Worker	_fields_ = [('currentUserID', c_int),
1010*f81fb7c4SAndroid Build Coastguard Worker				('segmentRepeatCount', c_int),
1011*f81fb7c4SAndroid Build Coastguard Worker				('numQueuedSegments', c_int),
1012*f81fb7c4SAndroid Build Coastguard Worker				('paused', c_int),
1013*f81fb7c4SAndroid Build Coastguard Worker				('location', c_long),
1014*f81fb7c4SAndroid Build Coastguard Worker				('currentPlayingSegment', c_int),
1015*f81fb7c4SAndroid Build Coastguard Worker				('currentQueuedSegment', c_int),
1016*f81fb7c4SAndroid Build Coastguard Worker				]
1017*f81fb7c4SAndroid Build Coastguard Worker
1018*f81fb7c4SAndroid Build Coastguard Worker#---------------------------------------------------------------
1019*f81fb7c4SAndroid Build Coastguard Worker# JET_File
1020*f81fb7c4SAndroid Build Coastguard Worker#---------------------------------------------------------------
1021*f81fb7c4SAndroid Build Coastguard Workerclass JET_File (object):
1022*f81fb7c4SAndroid Build Coastguard Worker	def __init__ (self, handle, jet):
1023*f81fb7c4SAndroid Build Coastguard Worker		eas_logger.debug('JET_File.__init__')
1024*f81fb7c4SAndroid Build Coastguard Worker		self.handle = handle
1025*f81fb7c4SAndroid Build Coastguard Worker		self.jet = jet
1026*f81fb7c4SAndroid Build Coastguard Worker
1027*f81fb7c4SAndroid Build Coastguard Worker#---------------------------------------------------------------
1028*f81fb7c4SAndroid Build Coastguard Worker# JET
1029*f81fb7c4SAndroid Build Coastguard Worker#---------------------------------------------------------------
1030*f81fb7c4SAndroid Build Coastguard Workerclass JET (object):
1031*f81fb7c4SAndroid Build Coastguard Worker	def __init__ (self, eas=None):
1032*f81fb7c4SAndroid Build Coastguard Worker		# eas_logger.debug('JET.__init__')
1033*f81fb7c4SAndroid Build Coastguard Worker		self.Init(eas)
1034*f81fb7c4SAndroid Build Coastguard Worker
1035*f81fb7c4SAndroid Build Coastguard Worker	def __del__ (self):
1036*f81fb7c4SAndroid Build Coastguard Worker		eas_logger.debug('JET.__del__')
1037*f81fb7c4SAndroid Build Coastguard Worker		self.Shutdown()
1038*f81fb7c4SAndroid Build Coastguard Worker
1039*f81fb7c4SAndroid Build Coastguard Worker	def Init (self, eas=None, config=None):
1040*f81fb7c4SAndroid Build Coastguard Worker		"""Initializes the JET Library."""
1041*f81fb7c4SAndroid Build Coastguard Worker		# eas_logger.debug('JET.Init')
1042*f81fb7c4SAndroid Build Coastguard Worker
1043*f81fb7c4SAndroid Build Coastguard Worker		if hasattr(self, 'eas'):
1044*f81fb7c4SAndroid Build Coastguard Worker			raise EAS_Exception(-1, 'JET library already initialized', 'Jet.Init')
1045*f81fb7c4SAndroid Build Coastguard Worker
1046*f81fb7c4SAndroid Build Coastguard Worker		# create some members
1047*f81fb7c4SAndroid Build Coastguard Worker		if eas is None:
1048*f81fb7c4SAndroid Build Coastguard Worker			# eas_logger.debug('No EAS handle --- initializing EAS')
1049*f81fb7c4SAndroid Build Coastguard Worker			eas = EAS()
1050*f81fb7c4SAndroid Build Coastguard Worker			self.alloc_eas = True
1051*f81fb7c4SAndroid Build Coastguard Worker		else:
1052*f81fb7c4SAndroid Build Coastguard Worker			self.alloc_eas = False
1053*f81fb7c4SAndroid Build Coastguard Worker		self.eas = eas
1054*f81fb7c4SAndroid Build Coastguard Worker		self.fileOpen = False
1055*f81fb7c4SAndroid Build Coastguard Worker
1056*f81fb7c4SAndroid Build Coastguard Worker		# handle configuration
1057*f81fb7c4SAndroid Build Coastguard Worker		if config is None:
1058*f81fb7c4SAndroid Build Coastguard Worker			config_handle = c_void_p(0)
1059*f81fb7c4SAndroid Build Coastguard Worker			config_size = 0
1060*f81fb7c4SAndroid Build Coastguard Worker		else:
1061*f81fb7c4SAndroid Build Coastguard Worker			jet_config = S_JET_CONFIG()
1062*f81fb7c4SAndroid Build Coastguard Worker			jet_config.appLowNote = config.appLowNote
1063*f81fb7c4SAndroid Build Coastguard Worker			config_handle = c_void_p(jet_config)
1064*f81fb7c4SAndroid Build Coastguard Worker			config_size = jet_config.sizeof()
1065*f81fb7c4SAndroid Build Coastguard Worker
1066*f81fb7c4SAndroid Build Coastguard Worker		# initialize library
1067*f81fb7c4SAndroid Build Coastguard Worker		# eas_logger.debug('Call JET_Init')
1068*f81fb7c4SAndroid Build Coastguard Worker		result = eas_dll.JET_Init(eas.handle, config_handle, config_size)
1069*f81fb7c4SAndroid Build Coastguard Worker		if result:
1070*f81fb7c4SAndroid Build Coastguard Worker			raise EAS_Exception(result, 'JET_Init error %d' % result, 'JET_Init')
1071*f81fb7c4SAndroid Build Coastguard Worker
1072*f81fb7c4SAndroid Build Coastguard Worker	def Shutdown (self):
1073*f81fb7c4SAndroid Build Coastguard Worker		"""Shuts down the JET library"""
1074*f81fb7c4SAndroid Build Coastguard Worker		eas_logger.debug('JET.Shutdown')
1075*f81fb7c4SAndroid Build Coastguard Worker		if not hasattr(self, 'eas'):
1076*f81fb7c4SAndroid Build Coastguard Worker			return
1077*f81fb7c4SAndroid Build Coastguard Worker
1078*f81fb7c4SAndroid Build Coastguard Worker		with self.eas.lock:
1079*f81fb7c4SAndroid Build Coastguard Worker			if self.fileOpen:
1080*f81fb7c4SAndroid Build Coastguard Worker				eas_logger.warning('Stream was not closed before JET_Shutdown')
1081*f81fb7c4SAndroid Build Coastguard Worker				self.CloseFile()
1082*f81fb7c4SAndroid Build Coastguard Worker
1083*f81fb7c4SAndroid Build Coastguard Worker			# shutdown library
1084*f81fb7c4SAndroid Build Coastguard Worker			eas_logger.debug('Call JET_Shutdown')
1085*f81fb7c4SAndroid Build Coastguard Worker			result = eas_dll.JET_Shutdown(self.eas.handle)
1086*f81fb7c4SAndroid Build Coastguard Worker			if result:
1087*f81fb7c4SAndroid Build Coastguard Worker				raise EAS_Exception(result, 'JET_Shutdown error %d' % result, 'JET_Shutdown')
1088*f81fb7c4SAndroid Build Coastguard Worker
1089*f81fb7c4SAndroid Build Coastguard Worker			# if we created the EAS reference here, shut it down
1090*f81fb7c4SAndroid Build Coastguard Worker			if self.alloc_eas:
1091*f81fb7c4SAndroid Build Coastguard Worker				self.eas.Shutdown()
1092*f81fb7c4SAndroid Build Coastguard Worker				self.alloc_eas = False
1093*f81fb7c4SAndroid Build Coastguard Worker			del self.eas
1094*f81fb7c4SAndroid Build Coastguard Worker
1095*f81fb7c4SAndroid Build Coastguard Worker	def OpenFile (self, path):
1096*f81fb7c4SAndroid Build Coastguard Worker		"""Opens an audio file to be played by the JET library and
1097*f81fb7c4SAndroid Build Coastguard Worker		returns a JET_File object
1098*f81fb7c4SAndroid Build Coastguard Worker
1099*f81fb7c4SAndroid Build Coastguard Worker		Arguments:
1100*f81fb7c4SAndroid Build Coastguard Worker			path - path to audio file
1101*f81fb7c4SAndroid Build Coastguard Worker
1102*f81fb7c4SAndroid Build Coastguard Worker		"""
1103*f81fb7c4SAndroid Build Coastguard Worker		with self.eas.lock:
1104*f81fb7c4SAndroid Build Coastguard Worker			eas_logger.debug('Call JET_OpenFile for file: %s' % path)
1105*f81fb7c4SAndroid Build Coastguard Worker			result = eas_dll.JET_OpenFile(self.eas.handle, path)
1106*f81fb7c4SAndroid Build Coastguard Worker			if result:
1107*f81fb7c4SAndroid Build Coastguard Worker				raise EAS_Exception(result, 'JET_OpenFile error %d on file %s' % (result, path), 'JET_OpenFile')
1108*f81fb7c4SAndroid Build Coastguard Worker
1109*f81fb7c4SAndroid Build Coastguard Worker	def CloseFile (self):
1110*f81fb7c4SAndroid Build Coastguard Worker		"""Closes an open audio file."""
1111*f81fb7c4SAndroid Build Coastguard Worker		with self.eas.lock:
1112*f81fb7c4SAndroid Build Coastguard Worker			eas_logger.debug('Call JET_CloseFile')
1113*f81fb7c4SAndroid Build Coastguard Worker			result = eas_dll.JET_CloseFile(self.eas.handle)
1114*f81fb7c4SAndroid Build Coastguard Worker			if result:
1115*f81fb7c4SAndroid Build Coastguard Worker				raise EAS_Exception(result, 'JET_CloseFile error %d' % result, 'JET_CloseFile')
1116*f81fb7c4SAndroid Build Coastguard Worker
1117*f81fb7c4SAndroid Build Coastguard Worker	def QueueSegment (self, userID, seg_num, dls_num=-1, repeat=0, tranpose=0, mute_flags=0):
1118*f81fb7c4SAndroid Build Coastguard Worker		"""Queue a segment for playback.
1119*f81fb7c4SAndroid Build Coastguard Worker
1120*f81fb7c4SAndroid Build Coastguard Worker		Arguments:
1121*f81fb7c4SAndroid Build Coastguard Worker			seg_num - segment number to queue
1122*f81fb7c4SAndroid Build Coastguard Worker			repeat - repeat count (-1=repeat forever, 0=no repeat, 1+ = play n+1 times)
1123*f81fb7c4SAndroid Build Coastguard Worker			tranpose - transpose amount (+/-12)
1124*f81fb7c4SAndroid Build Coastguard Worker
1125*f81fb7c4SAndroid Build Coastguard Worker			"""
1126*f81fb7c4SAndroid Build Coastguard Worker		with self.eas.lock:
1127*f81fb7c4SAndroid Build Coastguard Worker			eas_logger.debug('Call JET_QueueSegment')
1128*f81fb7c4SAndroid Build Coastguard Worker			result = eas_dll.JET_QueueSegment(self.eas.handle, seg_num, dls_num, repeat, tranpose, mute_flags, userID)
1129*f81fb7c4SAndroid Build Coastguard Worker			if result:
1130*f81fb7c4SAndroid Build Coastguard Worker				raise EAS_Exception(result, 'JET_QueueSegment error %d' % result, 'JET_QueueSegment')
1131*f81fb7c4SAndroid Build Coastguard Worker
1132*f81fb7c4SAndroid Build Coastguard Worker	def Clear_Queue(self):
1133*f81fb7c4SAndroid Build Coastguard Worker		"""Kills the queue."""
1134*f81fb7c4SAndroid Build Coastguard Worker		with self.eas.lock:
1135*f81fb7c4SAndroid Build Coastguard Worker			eas_logger.debug('Call JET_Clear_Queue')
1136*f81fb7c4SAndroid Build Coastguard Worker			result = eas_dll.JET_Clear_Queue(self.eas.handle)
1137*f81fb7c4SAndroid Build Coastguard Worker			if result:
1138*f81fb7c4SAndroid Build Coastguard Worker				raise EAS_Exception(result, 'JET_Clear_Queue error %d' % result, 'JET_Clear_Queue')
1139*f81fb7c4SAndroid Build Coastguard Worker
1140*f81fb7c4SAndroid Build Coastguard Worker	def GetAppEvent(self):
1141*f81fb7c4SAndroid Build Coastguard Worker		"""Gets an App event."""
1142*f81fb7c4SAndroid Build Coastguard Worker		with self.eas.lock:
1143*f81fb7c4SAndroid Build Coastguard Worker			eas_logger.debug('Call JET_GetEvent')
1144*f81fb7c4SAndroid Build Coastguard Worker			result = eas_dll.JET_GetEvent(self.eas.handle, 0, 0)
1145*f81fb7c4SAndroid Build Coastguard Worker			return result
1146*f81fb7c4SAndroid Build Coastguard Worker
1147*f81fb7c4SAndroid Build Coastguard Worker	def Play(self):
1148*f81fb7c4SAndroid Build Coastguard Worker		"""Starts JET playback."""
1149*f81fb7c4SAndroid Build Coastguard Worker		with self.eas.lock:
1150*f81fb7c4SAndroid Build Coastguard Worker			eas_logger.debug('Call JET_Play')
1151*f81fb7c4SAndroid Build Coastguard Worker			result = eas_dll.JET_Play(self.eas.handle)
1152*f81fb7c4SAndroid Build Coastguard Worker			if result:
1153*f81fb7c4SAndroid Build Coastguard Worker				raise EAS_Exception(result, 'JET_Play error %d' % result, 'JET_Play')
1154*f81fb7c4SAndroid Build Coastguard Worker
1155*f81fb7c4SAndroid Build Coastguard Worker	def Pause(self):
1156*f81fb7c4SAndroid Build Coastguard Worker		"""Pauses JET playback."""
1157*f81fb7c4SAndroid Build Coastguard Worker		with self.eas.lock:
1158*f81fb7c4SAndroid Build Coastguard Worker			eas_logger.debug('Call JET_Pause')
1159*f81fb7c4SAndroid Build Coastguard Worker			result = eas_dll.JET_Pause(self.eas.handle)
1160*f81fb7c4SAndroid Build Coastguard Worker			if result:
1161*f81fb7c4SAndroid Build Coastguard Worker				raise EAS_Exception(result, 'JET_Pause error %d' % result, 'JET_Pause')
1162*f81fb7c4SAndroid Build Coastguard Worker
1163*f81fb7c4SAndroid Build Coastguard Worker	def Render (self, count=None, secs=None):
1164*f81fb7c4SAndroid Build Coastguard Worker		"""Calls EAS_Render to render audio.
1165*f81fb7c4SAndroid Build Coastguard Worker
1166*f81fb7c4SAndroid Build Coastguard Worker		Arguments
1167*f81fb7c4SAndroid Build Coastguard Worker			count - number of buffers to render
1168*f81fb7c4SAndroid Build Coastguard Worker			secs - number of seconds to render
1169*f81fb7c4SAndroid Build Coastguard Worker
1170*f81fb7c4SAndroid Build Coastguard Worker		If both count and secs are None, render a single buffer.
1171*f81fb7c4SAndroid Build Coastguard Worker
1172*f81fb7c4SAndroid Build Coastguard Worker		"""
1173*f81fb7c4SAndroid Build Coastguard Worker		# calls JET.Render
1174*f81fb7c4SAndroid Build Coastguard Worker		with self.eas.lock:
1175*f81fb7c4SAndroid Build Coastguard Worker			self.eas.Render(count, secs)
1176*f81fb7c4SAndroid Build Coastguard Worker
1177*f81fb7c4SAndroid Build Coastguard Worker	def Status (self):
1178*f81fb7c4SAndroid Build Coastguard Worker		"""Get JET status."""
1179*f81fb7c4SAndroid Build Coastguard Worker		with self.eas.lock:
1180*f81fb7c4SAndroid Build Coastguard Worker			eas_logger.debug('Call JET_Status')
1181*f81fb7c4SAndroid Build Coastguard Worker			status = JET_Status()
1182*f81fb7c4SAndroid Build Coastguard Worker			result = eas_dll.JET_Status(self.eas.handle, byref(status))
1183*f81fb7c4SAndroid Build Coastguard Worker			if result:
1184*f81fb7c4SAndroid Build Coastguard Worker				raise EAS_Exception(result, 'JET_Status error %d' % result, 'JET_Status')
1185*f81fb7c4SAndroid Build Coastguard Worker			eas_logger.debug("currentUserID=%d, repeatCount=%d, numQueuedSegments=%d, paused=%d" %
1186*f81fb7c4SAndroid Build Coastguard Worker				(status.currentUserID, status.segmentRepeatCount, status.numQueuedSegments, status.paused))
1187*f81fb7c4SAndroid Build Coastguard Worker			return status
1188*f81fb7c4SAndroid Build Coastguard Worker
1189*f81fb7c4SAndroid Build Coastguard Worker	def SetVolume (self, volume):
1190*f81fb7c4SAndroid Build Coastguard Worker		"""Set the JET volume"""
1191*f81fb7c4SAndroid Build Coastguard Worker		eas_logger.debug('Call JET_SetVolume')
1192*f81fb7c4SAndroid Build Coastguard Worker		with self.eas.lock:
1193*f81fb7c4SAndroid Build Coastguard Worker			result = eas_dll.JET_SetVolume(self.eas.handle, volume)
1194*f81fb7c4SAndroid Build Coastguard Worker			if result:
1195*f81fb7c4SAndroid Build Coastguard Worker					raise EAS_Exception(result, 'JET_SetVolume error %d' % result, 'JET_SetVolume')
1196*f81fb7c4SAndroid Build Coastguard Worker
1197*f81fb7c4SAndroid Build Coastguard Worker	def SetTransposition (self, transposition):
1198*f81fb7c4SAndroid Build Coastguard Worker		"""Set the transposition of a stream."""
1199*f81fb7c4SAndroid Build Coastguard Worker		eas_logger.debug('Call JET_SetTransposition')
1200*f81fb7c4SAndroid Build Coastguard Worker		with self.eas.lock:
1201*f81fb7c4SAndroid Build Coastguard Worker			result = eas_dll.JET_SetTransposition(self.eas.handle, transposition)
1202*f81fb7c4SAndroid Build Coastguard Worker			if result:
1203*f81fb7c4SAndroid Build Coastguard Worker				raise EAS_Exception(result, 'JET_SetTransposition error %d' % result, 'JET_SetTransposition')
1204*f81fb7c4SAndroid Build Coastguard Worker
1205*f81fb7c4SAndroid Build Coastguard Worker	def TriggerClip (self, clipID):
1206*f81fb7c4SAndroid Build Coastguard Worker		"""Trigger a clip in the current segment."""
1207*f81fb7c4SAndroid Build Coastguard Worker		eas_logger.debug('Call JET_TriggerClip')
1208*f81fb7c4SAndroid Build Coastguard Worker		with self.eas.lock:
1209*f81fb7c4SAndroid Build Coastguard Worker			result = eas_dll.JET_TriggerClip(self.eas.handle, clipID)
1210*f81fb7c4SAndroid Build Coastguard Worker			if result:
1211*f81fb7c4SAndroid Build Coastguard Worker				raise EAS_Exception(result, 'JET_SetTransposition error %d' % result, 'JET_TriggerClip')
1212*f81fb7c4SAndroid Build Coastguard Worker
1213*f81fb7c4SAndroid Build Coastguard Worker	def SetMuteFlag (self, track_num, mute, sync=True):
1214*f81fb7c4SAndroid Build Coastguard Worker		"""Trigger a clip in the current segment."""
1215*f81fb7c4SAndroid Build Coastguard Worker		eas_logger.debug('Call JET_SetMuteFlag')
1216*f81fb7c4SAndroid Build Coastguard Worker		with self.eas.lock:
1217*f81fb7c4SAndroid Build Coastguard Worker			result = eas_dll.JET_SetMuteFlag(self.eas.handle, track_num, mute, sync)
1218*f81fb7c4SAndroid Build Coastguard Worker			if result:
1219*f81fb7c4SAndroid Build Coastguard Worker				raise EAS_Exception(result, 'JET_SetMuteFlag error %d' % result, 'JET_SetMuteFlag')
1220*f81fb7c4SAndroid Build Coastguard Worker
1221*f81fb7c4SAndroid Build Coastguard Worker	def SetMuteFlags (self, mute_flags, sync=True):
1222*f81fb7c4SAndroid Build Coastguard Worker		"""Trigger a clip in the current segment."""
1223*f81fb7c4SAndroid Build Coastguard Worker		eas_logger.debug('Call JET_SetMuteFlags')
1224*f81fb7c4SAndroid Build Coastguard Worker		with self.eas.lock:
1225*f81fb7c4SAndroid Build Coastguard Worker			result = eas_dll.JET_SetMuteFlags(self.eas.handle, mute_flags, sync)
1226*f81fb7c4SAndroid Build Coastguard Worker			if result:
1227*f81fb7c4SAndroid Build Coastguard Worker				raise EAS_Exception(result, 'JET_SetMuteFlag error %d' % result, 'JET_SetMuteFlags')
1228*f81fb7c4SAndroid Build Coastguard Worker
1229*f81fb7c4SAndroid Build Coastguard Worker
1230