summaryrefslogtreecommitdiffstats
path: root/jet_tools/JetCreator/eas.py
diff options
context:
space:
mode:
Diffstat (limited to 'jet_tools/JetCreator/eas.py')
-rwxr-xr-xjet_tools/JetCreator/eas.py1229
1 files changed, 1229 insertions, 0 deletions
diff --git a/jet_tools/JetCreator/eas.py b/jet_tools/JetCreator/eas.py
new file mode 100755
index 0000000..127314b
--- /dev/null
+++ b/jet_tools/JetCreator/eas.py
@@ -0,0 +1,1229 @@
+
+from __future__ import with_statement
+
+import threading
+import logging
+import time
+from ctypes import *
+from JetUtils import OsWindows
+
+
+# stream state
+EAS_STATE_READY = 0
+EAS_STATE_PLAY = 1
+EAS_STATE_STOPPING = 2
+EAS_STATE_PAUSING = 3
+EAS_STATE_STOPPED = 4
+EAS_STATE_PAUSED = 5
+EAS_STATE_OPEN = 6
+EAS_STATE_ERROR = 7
+EAS_STATE_EMPTY = 8
+
+# EAS error codes
+EAS_SUCCESS = 0
+EAS_FAILURE = -1
+EAS_ERROR_INVALID_MODULE = -2
+EAS_ERROR_MALLOC_FAILED = -3
+EAS_ERROR_FILE_POS = -4
+EAS_ERROR_INVALID_FILE_MODE = -5
+EAS_ERROR_FILE_SEEK = -6
+EAS_ERROR_FILE_LENGTH = -7
+EAS_ERROR_NOT_IMPLEMENTED = -8
+EAS_ERROR_CLOSE_FAILED = -9
+EAS_ERROR_FILE_OPEN_FAILED = -10
+EAS_ERROR_INVALID_HANDLE = -11
+EAS_ERROR_NO_MIX_BUFFER = -12
+EAS_ERROR_PARAMETER_RANGE = -13
+EAS_ERROR_MAX_FILES_OPEN = -14
+EAS_ERROR_UNRECOGNIZED_FORMAT = -15
+EAS_BUFFER_SIZE_MISMATCH = -16
+EAS_ERROR_FILE_FORMAT = -17
+EAS_ERROR_SMF_NOT_INITIALIZED = -18
+EAS_ERROR_LOCATE_BEYOND_END = -19
+EAS_ERROR_INVALID_PCM_TYPE = -20
+EAS_ERROR_MAX_PCM_STREAMS = -21
+EAS_ERROR_NO_VOICE_ALLOCATED = -22
+EAS_ERROR_INVALID_CHANNEL = -23
+EAS_ERROR_ALREADY_STOPPED = -24
+EAS_ERROR_FILE_READ_FAILED = -25
+EAS_ERROR_HANDLE_INTEGRITY = -26
+EAS_ERROR_MAX_STREAMS_OPEN = -27
+EAS_ERROR_INVALID_PARAMETER = -28
+EAS_ERROR_FEATURE_NOT_AVAILABLE = -29
+EAS_ERROR_SOUND_LIBRARY = -30
+EAS_ERROR_NOT_VALID_IN_THIS_STATE = -31
+EAS_ERROR_NO_VIRTUAL_SYNTHESIZER = -32
+EAS_ERROR_FILE_ALREADY_OPEN = -33
+EAS_ERROR_FILE_ALREADY_CLOSED = -34
+EAS_ERROR_INCOMPATIBLE_VERSION = -35
+EAS_ERROR_QUEUE_IS_FULL = -36
+EAS_ERROR_QUEUE_IS_EMPTY = -37
+EAS_ERROR_FEATURE_ALREADY_ACTIVE = -38
+
+# special result codes
+EAS_EOF = 3
+EAS_STREAM_BUFFERING = 4
+
+# buffer full error returned from Render
+EAS_BUFFER_FULL = 5
+
+# file types
+file_types = (
+ 'Unknown',
+ 'SMF Type 0 (.mid)',
+ 'SMF Type 1 (.mid)',
+ 'SMAF - Unknown type (.mmf)',
+ 'SMAF MA-2 (.mmf)',
+ 'SMAF MA-3 (.mmf)',
+ 'SMAF MA-5 (.mmf)',
+ 'CMX/QualComm (.pmd)',
+ 'MFi (NTT/DoCoMo i-mode)',
+ 'OTA/Nokia (.ott)',
+ 'iMelody (.imy)',
+ 'RTX/RTTTL (.rtx)',
+ 'XMF Type 0 (.xmf)',
+ 'XMF Type 1 (.xmf)',
+ 'WAVE/PCM (.wav)',
+ 'WAVE/IMA-ADPCM (.wav)',
+ 'MMAPI Tone Control (.js)'
+)
+
+stream_states = (
+ 'Ready',
+ 'Play',
+ 'Stopping',
+ 'Stopped',
+ 'Pausing',
+ 'Paused',
+ 'Open',
+ 'Error',
+ 'Empty'
+)
+
+# iMode play modes
+IMODE_PLAY_ALL = 0
+IMODE_PLAY_PARTIAL = 1
+
+# callback type for metadata
+EAS_METADATA_CBFUNC = CFUNCTYPE(c_int, c_int, c_char_p, c_ulong)
+
+# callbacks for external audio
+EAS_EXT_PRG_CHG_FUNC = CFUNCTYPE(c_int, c_void_p, c_void_p)
+EAS_EXT_EVENT_FUNC = CFUNCTYPE(c_int, c_void_p, c_void_p)
+
+# callback for aux mixer decoder
+EAS_DECODER_FUNC = CFUNCTYPE(c_void_p, c_void_p, c_int, c_int)
+
+# DLL path
+if OsWindows():
+ EAS_DLL_PATH = "EASDLL.dll"
+else:
+ EAS_DLL_PATH = "libEASLIb.dylib"
+
+eas_dll = None
+
+# logger
+eas_logger = None
+
+#---------------------------------------------------------------
+# InitEASModule
+#---------------------------------------------------------------
+def InitEASModule (dll_path=None):
+ global eas_dll
+ global eas_logger
+
+
+ # initialize logger
+ if eas_logger is None:
+ eas_logger = logging.getLogger('EAS')
+
+ # initialize path to DLL
+ if dll_path is None:
+ dll_path=EAS_DLL_PATH
+
+ # intialize DLL
+ if eas_dll is None:
+ eas_dll = cdll.LoadLibrary(dll_path)
+
+#---------------------------------------------------------------
+# S_JET_CONFIG
+#---------------------------------------------------------------
+class S_JET_CONFIG (Structure):
+ _fields_ = [('appLowNote', c_ubyte)]
+
+#---------------------------------------------------------------
+# S_EXT_AUDIO_PRG_CHG
+#---------------------------------------------------------------
+class S_EXT_AUDIO_PRG_CHG (Structure):
+ _fields_ = [('bank', c_ushort),
+ ('program', c_ubyte),
+ ('channel', c_ubyte)]
+
+#---------------------------------------------------------------
+# S_EXT_AUDIO_EVENT
+#---------------------------------------------------------------
+class S_EXT_AUDIO_EVENT (Structure):
+ _fields_ = [('channel', c_ubyte),
+ ('note', c_ubyte),
+ ('velocity', c_ubyte),
+ ('noteOn', c_ubyte)]
+
+#---------------------------------------------------------------
+# S_MIDI_CONTROLLERS
+#---------------------------------------------------------------
+class S_MIDI_CONTROLLERS (Structure):
+ _fields_ = [('modWheel', c_ubyte),
+ ('volume', c_ubyte),
+ ('pan', c_ubyte),
+ ('expression', c_ubyte),
+ ('channelPressure', c_ubyte)]
+
+#---------------------------------------------------------------
+# WAVEFORMAT
+#---------------------------------------------------------------
+class WAVEFORMAT (Structure):
+ _fields_ = [('wFormatTag', c_ushort),
+ ('nChannels', c_ushort),
+ ('nSamplesPerSec', c_ulong),
+ ('nAvgBytesPerSec', c_ulong),
+ ('nBlockAlign', c_ushort),
+ ('wBitsPerSample', c_ushort)]
+
+#---------------------------------------------------------------
+# EAS_Exception
+#---------------------------------------------------------------
+class EAS_Exception (Exception):
+ def __init__ (self, result_code, msg, function=None):
+ self.msg = msg
+ self.result_code = result_code
+ self.function = function
+ def __str__ (self):
+ return self.msg
+
+#---------------------------------------------------------------
+# Log callback function
+#---------------------------------------------------------------
+# map EAS severity levels to the Python logging module
+severity_mapping = (logging.CRITICAL, logging.CRITICAL, logging.ERROR, logging.WARNING, logging.INFO, logging.DEBUG)
+LOG_FUNC_TYPE = CFUNCTYPE(c_int, c_int, c_char_p)
+def Log (level, msg):
+ eas_logger.log(severity_mapping[level], msg)
+ return level
+LogCallback = LOG_FUNC_TYPE(Log)
+
+#---------------------------------------------------------------
+# EAS_Stream
+#---------------------------------------------------------------
+class EAS_Stream (object):
+ def __init__ (self, handle, eas):
+ eas_logger.debug('EAS_Stream.__init__')
+ self.handle = handle
+ self.eas = eas
+
+ def SetVolume (self, volume):
+ """Set the stream volume"""
+ eas_logger.debug('Call EAS_SetVolume: volume=%d' % volume)
+ with self.eas.lock:
+ result = eas_dll.EAS_SetVolume(self.eas.handle, self.handle, volume)
+ if result:
+ raise EAS_Exception(result, 'EAS_SetVolume error %d on file %s' % (result, self.path), 'EAS_SetVolume')
+
+ def GetVolume (self):
+ """Get the stream volume."""
+ eas_logger.debug('Call EAS_GetVolume')
+ with self.eas.lock:
+ volume = eas_dll.EAS_GetVolume(self.eas.handle, self.handle)
+ if volume < 0:
+ raise EAS_Exception(volume, 'EAS_GetVolume error %d on file %s' % (volume, self.path), 'EAS_GetVolume')
+ eas_logger.debug('EAS_GetVolume: volume=%d' % volume)
+ return volume
+
+ def SetPriority (self, priority):
+ """Set the stream priority"""
+ eas_logger.debug('Call EAS_SetPriority: priority=%d' % priority)
+ with self.eas.lock:
+ result = eas_dll.EAS_SetPriority(self.eas.handle, self.handle, priority)
+ if result:
+ raise EAS_Exception(result, 'EAS_SetPriority error %d on file %s' % (result, self.path), 'EAS_SetPriority')
+
+ def GetPriority (self):
+ """Get the stream priority."""
+ eas_logger.debug('Call EAS_GetPriority')
+ priority = c_int(0)
+ with self.eas.lock:
+ result = eas_dll.EAS_GetPriority(self.eas.handle, self.handle, byref(priority))
+ if result:
+ raise EAS_Exception(result, 'EAS_GetPriority error %d on file %s' % (result, self.path), 'EAS_GetPriority')
+ eas_logger.debug('EAS_GetPriority: priority=%d' % priority.value)
+ return priority.value
+
+ def SetTransposition (self, transposition):
+ """Set the transposition of a stream."""
+ eas_logger.debug('Call EAS_SetTransposition: transposition=%d' % transposition)
+ with self.eas.lock:
+ result = eas_dll.EAS_SetTransposition(self.eas.handle, self.handle, transposition)
+ if result:
+ raise EAS_Exception(result, 'EAS_SetTransposition error %d on file %s' % (result, self.path), 'EAS_SetTransposition')
+
+ def SetPolyphony (self, polyphony):
+ """Set the polyphony of a stream."""
+ eas_logger.debug('Call EAS_SetPolyphony: polyphony=%d' % polyphony)
+ with self.eas.lock:
+ result = eas_dll.EAS_SetPolyphony(self.eas.handle, self.handle, polyphony)
+ if result:
+ raise EAS_Exception(result, 'EAS_SetPolyphony error %d on file %s' % (result, self.path), 'EAS_SetPolyphony')
+
+ def GetPolyphony (self):
+ """Get the polyphony of a stream."""
+ eas_logger.debug('Call EAS_GetPolyphony')
+ polyphony = c_int(0)
+ with self.eas.lock:
+ result = eas_dll.EAS_GetPolyphony(self.eas.handle, self.handle, byref(polyphony))
+ if result:
+ raise EAS_Exception(result, 'EAS_GetPolyphony error %d on file %s' % (result, self.path), 'EAS_GetPolyphony')
+ eas_logger.debug('EAS_SetPolyphony: polyphony=%d' % polyphony.value)
+ return polyphony.value
+
+ def SelectLib (self, test_lib=False):
+ eas_logger.debug('Call EAS_SelectLib: test_lib=%s' % test_lib)
+ with self.eas.lock:
+ result = eas_dll.EAS_SelectLib(self.eas.handle, self.handle, test_lib)
+ if result:
+ raise EAS_Exception(result, 'EAS_SelectLib error %d on file %s' % (result, self.path), 'EAS_SelectLib')
+
+ def LoadDLSCollection (self, path):
+ eas_logger.debug('Call EAS_LoadDLSCollection: lib_path=%d' % path)
+ with self.eas.lock:
+ result = eas_dll.EAS_LoadDLSCollection(self.eas.handle, self.handle, path)
+ if result:
+ raise EAS_Exception(result, 'EAS_LoadDLSCollection error %d on file %s lib %s' % (result, self.path, path), 'EAS_LoadDLSCollection')
+
+ def RegExtAudioCallback (self, user_data, prog_chg_func, event_func):
+ """Register an external audio callback."""
+ eas_logger.debug('Call EAS_RegExtAudioCallback')
+ if prog_chg_func is not None:
+ prog_chg_func = EAS_EXT_PRG_CHG_FUNC(prog_chg_func)
+ else:
+ prog_chg_func = 0
+ if event_func is not None:
+ event_func = EAS_EXT_EVENT_FUNC(event_func)
+ else:
+ event_func = 0
+ with self.eas.lock:
+ result = eas_dll.EAS_RegExtAudioCallback(self.eas.handle, self.handle, user_data, prog_chg_func, event_func)
+ if result:
+ raise EAS_Exception(result, 'EAS_RegExtAudioCallback error %d on file %s' % (result, self.path), 'EAS_RegExtAudioCallback')
+
+ def SetPlayMode (self, play_mode):
+ """Set play mode on a stream."""
+ eas_logger.debug('Call EAS_SetPlayMode: play_mode=%d' % play_mode)
+ with self.eas.lock:
+ result = eas_dll.EAS_SetPlayMode(self.eas.handle, self.handle, play_mode)
+ if result:
+ raise EAS_Exception(result, 'EAS_SetPlayMode error %d on file %s' % (result, self.path), 'EAS_SetPlayMode')
+
+"""
+EAS_PUBLIC EAS_RESULT EAS_GetMIDIControllers (EAS_DATA_HANDLE pEASData, EAS_HANDLE streamHandle, EAS_U8 channel, S_MIDI_CONTROLLERS *pControl);
+"""
+
+#---------------------------------------------------------------
+# EAS_File
+#---------------------------------------------------------------
+class EAS_File (EAS_Stream):
+ def __init__ (self, path, handle, eas):
+ EAS_Stream.__init__(self, handle, eas)
+ eas_logger.debug('EAS_File.__init__')
+ self.path = path
+ self.prepared = False
+
+ def Prepare (self):
+ """Prepare an audio file for playback"""
+ if self.prepared:
+ eas_logger.warning('Prepare already called on file %s' % self.path)
+ else:
+ with self.eas.lock:
+ eas_logger.debug('Call EAS_Prepare for file: %s' % self.path)
+ result = eas_dll.EAS_Prepare(self.eas.handle, self.handle)
+ if result:
+ raise EAS_Exception(result, 'EAS_Prepare error %d on file %s' % (result, self.path), 'EAS_Prepare')
+ self.prepared = True
+
+ def State (self):
+ """Get stream state."""
+ with self.eas.lock:
+ eas_logger.debug('Call EAS_State for file: %s' % self.path)
+ state = c_long(-1)
+ result = eas_dll.EAS_State(self.eas.handle, self.handle, byref(state))
+ if result:
+ raise EAS_Exception(result, 'EAS_State error %d on file %s' % (result, self.path), 'EAS_State')
+ eas_logger.debug('EAS_State: file=%s, state=%s' % (self.path, stream_states[state.value]))
+ return state.value
+
+ def Close (self):
+ """Close audio file."""
+ if hasattr(self, 'handle'):
+ with self.eas.lock:
+ eas_logger.debug('Call EAS_CloseFile for file: %s' % self.path)
+ result = eas_dll.EAS_CloseFile(self.eas.handle, self.handle)
+ if result:
+ raise EAS_Exception(result, 'EAS_CloseFile error %d on file %s' % (result, self.path), 'EAS_CloseFile')
+
+ # remove file from the EAS object
+ self.eas.audio_streams.remove(self)
+
+ # clean up references
+ del self.handle
+ del self.eas
+ del self.path
+
+ def Pause (self):
+ """Pause a stream."""
+ eas_logger.debug('Call EAS_Pause')
+ with self.eas.lock:
+ result = eas_dll.EAS_Pause(self.eas.handle, self.handle)
+ if result:
+ raise EAS_Exception(result, 'EAS_Pause error %d on file %s' % (result, self.path), 'EAS_Pause')
+
+ def Resume (self):
+ """Resume a stream."""
+ eas_logger.debug('Call EAS_Resume')
+ with self.eas.lock:
+ result = eas_dll.EAS_Resume(self.eas.handle, self.handle)
+ if result:
+ raise EAS_Exception(result, 'EAS_Resume error %d on file %s' % (result, self.path), 'EAS_Resume')
+
+ def Locate (self, secs, offset=False):
+ """Set the playback position of a stream in seconds."""
+ eas_logger.debug('Call EAS_Locate: location=%.3f, relative=%s' % (secs, offset))
+ with self.eas.lock:
+ result = eas_dll.EAS_Locate(self.eas.handle, self.handle, int(secs * 1000 + 0.5), offset)
+ if result:
+ raise EAS_Exception(result, 'EAS_Locate error %d on file %s' % (result, self.path), 'EAS_Locate')
+
+ def GetLocation (self):
+ """Get the stream location in seconds."""
+ eas_logger.debug('Call EAS_GetLocation')
+ msecs = c_int(0)
+ with self.eas.lock:
+ result = eas_dll.EAS_GetLocation(self.eas.handle, self.handle, byref(msecs))
+ if result:
+ raise EAS_Exception(result, 'EAS_GetLocation error %d on file %s' % (result, self.path), 'EAS_GetLocation')
+ msecs = float(msecs.value) / 1000
+ eas_logger.debug('EAS_GetLocation: location=%.3f' % msecs)
+ return msecs
+
+ def GetFileType (self):
+ """Get the file type."""
+ eas_logger.debug('Call EAS_GetFileType')
+ file_type = c_int(0)
+ with self.eas.lock:
+ result = eas_dll.EAS_GetFileType(self.eas.handle, self.handle, byref(file_type))
+ if result:
+ raise EAS_Exception(result, 'EAS_GetFileType error %d on file %s' % (result, self.path), 'EAS_GetFileType')
+ file_type = file_type.value
+ if file_type < len(file_types):
+ file_desc = file_types[file_type]
+ else:
+ file_desc = 'Unrecognized type %d' % file_type
+ eas_logger.debug('EAS_GetFileType: type=%d, desc=%s' % (file_type, file_desc))
+ return (file_type, file_desc)
+
+ def SetRepeat (self, count):
+ """Set the repeat count of a stream."""
+ eas_logger.debug('Call EAS_SetRepeat: count=%d' % count)
+ with self.eas.lock:
+ result = eas_dll.EAS_SetRepeat(self.eas.handle, self.handle, count)
+ if result:
+ raise EAS_Exception(result, 'EAS_SetRepeat error %d on file %s' % (result, self.path), 'EAS_SetRepeat')
+
+ def GetRepeat (self):
+ """Get the repeat count of a stream."""
+ eas_logger.debug('Call EAS_GetRepeat')
+ count = c_int(0)
+ with self.eas.lock:
+ result = eas_dll.EAS_GetRepeat(self.eas.handle, self.handle, byref(count))
+ if result:
+ raise EAS_Exception(result, 'EAS_GetRepeat error %d on file %s' % (result, self.path), 'EAS_GetRepeat')
+ eas_logger.debug('EAS_GetRepeat: count=%d' % count.value)
+ return count.value
+
+ def SetPlaybackRate (self, rate):
+ """Set the playback rate of a stream."""
+ eas_logger.debug('Call EAS_SetPlaybackRate')
+ with self.eas.lock:
+ result = eas_dll.EAS_SetPlaybackRate(self.eas.handle, self.handle, rate)
+ if result:
+ raise EAS_Exception(result, 'EAS_SetPlaybackRate error %d on file %s' % (result, self.path), 'EAS_SetPlaybackRate')
+
+ def ParseMetaData (self):
+ """Parse the metadata in a file."""
+ eas_logger.debug('Call EAS_ParseMetaData')
+ length = c_int(0)
+ with self.eas.lock:
+ result = eas_dll.EAS_ParseMetaData(self.eas.handle, self.handle, byref(length))
+ if result:
+ raise EAS_Exception(result, 'EAS_ParseMetaData error %d on file %s' % (result, self.path), 'EAS_ParseMetaData')
+ return float(length.value) / 1000.0
+
+ def RegisterMetaDataCallback (self, func, buf, buf_size, user_data):
+ """Register a metadata callback."""
+ eas_logger.debug('Call EAS_RegisterMetaDataCallback')
+ with self.eas.lock:
+ if func is not None:
+ callback = EAS_METADATA_CBFUNC(func)
+ else:
+ callback = 0
+ result = eas_dll.EAS_RegisterMetaDataCallback(self.eas.handle, self.handle, callback, buf, buf_size, user_data)
+ if result:
+ raise EAS_Exception(result, 'EAS_RegisterMetaDataCallback error %d on file %s' % (result, self.path), 'EAS_RegisterMetaDataCallback')
+
+ def GetWaveFmtChunk (self):
+ """Get the file type."""
+ eas_logger.debug('Call EAS_GetWaveFmtChunk')
+ wave_fmt_chunk = c_void_p(0)
+ with self.eas.lock:
+ result = eas_dll.EAS_GetWaveFmtChunk(self.eas.handle, self.handle, byref(wave_fmt_chunk))
+ if result:
+ raise EAS_Exception(result, 'EAS_GetWaveFmtChunk error %d on file %s' % (result, self.path), 'EAS_GetWaveFmtChunk')
+ return cast(wave_fmt_chunk, POINTER(WAVEFORMAT)).contents
+
+ def Play (self, max_time=None):
+ """Plays the file to the end or max_time."""
+ eas_logger.debug('EAS_File.Play')
+ if not self.prepared:
+ self.Prepare()
+ if max_time is not None:
+ max_time += self.eas.GetRenderTime()
+ while self.State() not in (EAS_STATE_STOPPED, EAS_STATE_ERROR, EAS_STATE_EMPTY):
+ self.eas.Render()
+ if max_time is not None:
+ if self.eas.GetRenderTime() >= max_time:
+ eas_logger.info('Max render time exceeded - stopping playback')
+ self.Pause()
+ self.eas.Render()
+ break
+
+#---------------------------------------------------------------
+# EAS_MIDIStream
+#---------------------------------------------------------------
+class EAS_MIDIStream (EAS_Stream):
+ def Write(self, data):
+ """Write data to MIDI stream."""
+ with self.eas.lock:
+ result = eas_dll.EAS_WriteMIDIStream(self.eas.handle, self.handle, data, len(data))
+ if result:
+ raise EAS_Exception(result, 'EAS_WriteMIDIStream error %d' % result, 'EAS_WriteMIDIStream')
+
+ def Close (self):
+ """Close MIDI stream."""
+ if hasattr(self, 'handle'):
+ with self.eas.lock:
+ eas_logger.debug('Call EAS_CloseMIDIStream')
+ result = eas_dll.EAS_CloseMIDIStream(self.eas.handle, self.handle)
+ if result:
+ raise EAS_Exception(result, 'EAS_CloseFile error %d' % result, 'EAS_CloseMIDIStream')
+
+ # remove file from the EAS object
+ self.eas.audio_streams.remove(self)
+
+ # clean up references
+ del self.handle
+ del self.eas
+
+#---------------------------------------------------------------
+# EAS_Config
+#---------------------------------------------------------------
+class EAS_Config (Structure):
+ _fields_ = [('libVersion', c_ulong),
+ ('checkedVersion', c_int),
+ ('maxVoices', c_long),
+ ('numChannels', c_long),
+ ('sampleRate', c_long),
+ ('mixBufferSize', c_long),
+ ('filterEnabled', c_int),
+ ('buildTimeStamp', c_ulong),
+ ('buildGUID', c_char_p)]
+
+#---------------------------------------------------------------
+# EAS
+#---------------------------------------------------------------
+class EAS (object):
+ def __init__ (self, handle=None, dll_path=None, log_file=None):
+ if eas_dll is None:
+ InitEASModule(dll_path)
+ if log_file is not None:
+ eas_logger.addHandler(log_file)
+ eas_logger.debug('EAS.__init__')
+ self.Init(handle)
+
+ def __del__ (self):
+ eas_logger.debug('EAS.__del__')
+ self.Shutdown()
+
+ def Init (self, handle=None):
+ """Initializes the EAS Library."""
+ eas_logger.debug('EAS.Init')
+
+ # if we are already initialized, shutdown first
+ if hasattr(self, 'handle'):
+ eas_logger.debug('EAS.Init called with library already initalized')
+ self.ShutDown()
+
+ # setup the logging function
+ eas_dll.SetLogCallback(LogCallback)
+
+ # create some members
+ self.handle = c_void_p(0)
+ self.audio_streams = []
+ self.output_streams = []
+ self.aux_mixer = None
+
+ # create a sync lock
+ self.lock = threading.RLock()
+ with self.lock:
+ # set log callback
+
+ # get library configuration
+ self.Config()
+
+ # initialize library
+ if handle is None:
+ self.do_shutdown = True
+ eas_logger.debug('Call EAS_Init')
+ result = eas_dll.EAS_Init(byref(self.handle))
+ if result:
+ raise EAS_Exception(result, 'EAS_Init error %d' % result, 'EAS_Init')
+ else:
+ self.do_shutdown = False
+ self.handle = handle
+
+ # allocate audio buffer for rendering
+ AudioBufferType = c_ubyte * (2 * self.config.mixBufferSize * self.config.numChannels)
+ self.audio_buffer = AudioBufferType()
+ self.buf_size = self.config.mixBufferSize
+
+ def Config (self):
+ """Retrieves the EAS library configuration"""
+ if not hasattr(self, 'config'):
+ eas_logger.debug('Call EAS_Config')
+ eas_dll.EAS_Config.restype = POINTER(EAS_Config)
+ self.config = eas_dll.EAS_Config()[0]
+ eas_logger.debug("libVersion=%08x, maxVoices=%d, numChannels=%d, sampleRate = %d, mixBufferSize=%d" %
+ (self.config.libVersion, self.config.maxVoices, self.config.numChannels, self.config.sampleRate, self.config.mixBufferSize))
+
+ def Shutdown (self):
+ """Shuts down the EAS library"""
+ eas_logger.debug('EAS.Shutdown')
+ if hasattr(self, 'handle'):
+ with self.lock:
+ # close audio streams
+ audio_streams = self.audio_streams
+ for f in audio_streams:
+ eas_logger.warning('Stream was not closed before EAS_Shutdown')
+ f.Close()
+
+ # close output streams
+ output_streams = self.output_streams
+ for s in output_streams:
+ s.close()
+
+ # shutdown library
+ if self.do_shutdown:
+ eas_logger.debug('Call EAS_Shutdown')
+ result = eas_dll.EAS_Shutdown(self.handle)
+ if result:
+ raise EAS_Exception(result, 'EAS_Shutdown error %d' % result, 'EAS_Shutdown')
+ del self.handle
+
+ def OpenFile (self, path):
+ """Opens an audio file to be played by the EAS library and
+ returns an EAS_File object
+
+ Arguments:
+ path - path to audio file
+
+ Returns:
+ EAS_File
+
+ """
+ with self.lock:
+ eas_logger.debug('Call EAS_OpenFile for file: %s' % path)
+ stream_handle = c_void_p(0)
+ result = eas_dll.EAS_OpenFile(self.handle, path, byref(stream_handle))
+ if result:
+ raise EAS_Exception(result, 'EAS_OpenFile error %d on file %s' % (result, path), 'EAS_OpenFile')
+
+ # create file object and save in list
+ stream = EAS_File(path, stream_handle, self)
+ self.audio_streams.append(stream)
+ return stream
+
+ def OpenMIDIStream (self, stream=None):
+ """Opens a MIDI stream.
+
+ Arguments:
+ stream - open stream object. If None, a new synth
+ is created.
+
+ Returns:
+ EAS_MIDIStream
+
+ """
+ with self.lock:
+ eas_logger.debug('Call EAS_OpenMIDIStream')
+ stream_handle = c_void_p(0)
+ if stream.handle is not None:
+ result = eas_dll.EAS_OpenMIDIStream(self.handle, byref(stream_handle), stream.handle)
+ else:
+ result = eas_dll.EAS_OpenMIDIStream(self.handle, byref(stream_handle), 0)
+ if result:
+ raise EAS_Exception(result, 'EAS_OpenMIDIStream error %d' % result, 'EAS_OpenMIDIStream')
+
+ # create stream object and save in list
+ stream = EAS_MIDIStream(stream_handle, self)
+ self.audio_streams.append(stream)
+ return stream
+
+ def OpenToneControlStream (self, path):
+ """Opens an MMAPI tone control file to be played by the EAS
+ library and returns an EAS_File object
+
+ Arguments:
+ path - path to audio file
+
+ Returns:
+ EAS_File
+
+ """
+ with self.lock:
+ eas_logger.debug('Call EAS_MMAPIToneControl for file: %s' % path)
+ stream_handle = c_void_p(0)
+ result = eas_dll.EAS_MMAPIToneControl(self.handle, path, byref(stream_handle))
+ if result:
+ raise EAS_Exception(result, 'EAS_MMAPIToneControl error %d on file %s' % (result, path), 'EAS_OpenToneControlStream')
+
+ # create file object and save in list
+ stream = EAS_File(path, stream_handle, self)
+ self.audio_streams.append(stream)
+ return stream
+
+ def Attach (self, stream):
+ """Attach a file or output device to the EAS output.
+
+ The stream object must support the following methods as
+ defined in the Python wave module:
+ close()
+ setparams()
+ writeframesraw()
+
+ Arguments:
+ stream - open wave object
+
+ """
+ self.output_streams.append(stream)
+ stream.setparams((self.config.numChannels, 2, self.config.sampleRate, 0, 'NONE', None))
+
+ def Detach (self, stream):
+ """Detach a file or output device from the EAS output. See
+ EAS.Attach for more details. It is the responsibility of
+ the caller to close the wave file or stream.
+
+ Arguments:
+ stream - open and attached wave object
+ """
+ self.output_streams.remove(stream)
+
+ def StartWave (self, dev_num=0, sampleRate=None, maxBufSize=None):
+ """Route the audio output to the indicated wave device. Note
+ that this can cause EASDLL.EAS_RenderWaveOut to return an
+ error code if all the output buffers are full. In this case,
+ the render thread should sleep a bit and try again.
+ Unfortunately, due to the nature of the MMSYSTEM interface,
+ there is no simple way to suspend the render thread.
+
+ """
+ if sampleRate == None:
+ sampleRate = self.config.sampleRate
+ if maxBufSize == None:
+ maxBufSize = self.config.mixBufferSize
+ with self.lock:
+ result = eas_dll.OpenWaveOutDevice(dev_num, sampleRate, maxBufSize)
+ if result:
+ raise EAS_Exception(result, 'OpenWaveOutDevice error %d' % result, 'OpenWaveOutDevice')
+
+ def StopWave (self):
+ """Stop routing audio output to the audio device."""
+ with self.lock:
+ result = eas_dll.CloseWaveOutDevice()
+ if result:
+ raise EAS_Exception(result, 'CloseWaveOutDevice error %d' % result, 'CloseWaveOutDevice')
+
+ def Render (self, count=None, secs=None):
+ """Calls EAS_Render to render audio.
+
+ Arguments
+ count - number of buffers to render
+ secs - number of seconds to render
+
+ If both count and secs are None, render a single buffer.
+
+ """
+
+ # determine number of buffers to render
+ if count is None:
+ if secs is not None:
+ count = int(secs * float(self.config.sampleRate) / float(self.buf_size) + 0.5)
+ else:
+ count = 1
+
+ # render buffers
+ eas_logger.debug('rendering %d buffers' % count)
+ samplesRendered = c_long(0)
+ with self.lock:
+ for c in range(count):
+ # render a buffer of audio
+ eas_logger.debug('rendering buffer')
+ while 1:
+ if self.aux_mixer is None:
+ result = eas_dll.EAS_RenderWaveOut(self.handle, byref(self.audio_buffer), self.buf_size, byref(samplesRendered))
+ else:
+ result = eas_dll.EAS_RenderAuxMixer(self.handle, byref(self.audio_buffer), byref(samplesRendered))
+
+ if result == 0:
+ break;
+ if result == EAS_BUFFER_FULL:
+ time.sleep(0.01)
+ else:
+ raise EAS_Exception(result, 'EAS_Render error %d' % result, 'EAS_Render')
+
+ # output to attached streams
+ for s in self.output_streams:
+ s.writeframesraw(self.audio_buffer)
+
+ def GetRenderTime (self):
+ """Get the render time in seconds."""
+ eas_logger.debug('Call EAS_GetRenderTime')
+ msecs = c_int(0)
+ with self.lock:
+ result = eas_dll.EAS_GetRenderTime(self.handle, byref(msecs))
+ if result:
+ raise EAS_Exception(result, 'EAS_GetRenderTime error %d' % result, 'EAS_GetRenderTime')
+ msecs = float(msecs.value) / 1000
+ eas_logger.debug('EAS_GetRenderTime: time=%.3f' % msecs)
+ return msecs
+
+ def SetVolume (self, volume):
+ """Set the master volume"""
+ eas_logger.debug('Call EAS_SetVolume: volume=%d' % volume)
+ with self.lock:
+ result = eas_dll.EAS_SetVolume(self.handle, 0, volume)
+ if result:
+ raise EAS_Exception(result, 'EAS_SetVolume error %d' % result, 'EAS_SetVolume')
+
+ def GetVolume (self):
+ """Get the stream volume."""
+ eas_logger.debug('Call EAS_GetVolume')
+ volume = c_int(0)
+ with self.lock:
+ result = eas_dll.EAS_GetVolume(self.handle, 0, byref(volume))
+ if result:
+ raise EAS_Exception(result, 'EAS_GetVolume error %d' % result, 'EAS_GetVolume')
+ eas_logger.debug('EAS_GetVolume: volume=%d' % volume.value)
+ return volume.value
+
+ def SetPolyphony (self, polyphony, synth_num=0):
+ """Set the polyphony of a synth."""
+ eas_logger.debug('Call EAS_SetSynthPolyphony: synth_num=%d, polyphony=%d' % (synth_num, polyphony))
+ with self.lock:
+ result = eas_dll.EAS_SetSynthPolyphony(self.handle, synth_num, polyphony)
+ if result:
+ raise EAS_Exception(result, 'EAS_SetSynthPolyphony error %d on synth %d' % (result, synth_num), 'EAS_SetPolyphony')
+
+ def GetPolyphony (self, synth_num=0):
+ """Get the polyphony of a synth."""
+ eas_logger.debug('Call EAS_GetSynthPolyphony: synth_num=%d' % synth_num)
+ polyphony = c_int(0)
+ with self.lock:
+ result = eas_dll.EAS_GetSynthPolyphony(self.handle, synth_num, byref(polyphony))
+ if result:
+ raise EAS_Exception(result, 'EAS_GetSynthPolyphony error %d on synth %d' % (result, synth_num), 'EAS_GetPolyphony')
+ eas_logger.debug('Call EAS_GetSynthPolyphony: synth_num=%d, polyphony=%d' % (synth_num, polyphony.value))
+ return polyphony.value
+
+ def SetMaxLoad (self, max_load):
+ """Set the maximum parser load."""
+ eas_logger.debug('Call EAS_SetMaxLoad: max_load=%d' % max_load)
+ with self.lock:
+ result = eas_dll.EAS_SetMaxLoad(self.handle, max_load)
+ if result:
+ raise EAS_Exception(result, 'EAS_SetMaxLoad error %d' % result, 'EAS_SetMaxLoad')
+
+ def SetParameter (self, module, param, value):
+ """Set a module parameter."""
+ eas_logger.debug('Call EAS_SetParameter: module=%d, param=%d, value=%d' % (module, param, value))
+ with self.lock:
+ result = eas_dll.EAS_SetParameter(self.handle, module, param, value)
+ if result:
+ raise EAS_Exception(result, 'EAS_SetParameter error %d (param=%d, value=%d)' % (result, param, value), 'EAS_SetParameter')
+
+ def GetParameter (self, module, param):
+ """Get the polyphony of a synth."""
+ eas_logger.debug('Call EAS_GetParameter: module=%d, param=%d' % (module, param))
+ value = c_int(0)
+ with self.lock:
+ result = eas_dll.EAS_GetParameter(self.handle, module, param, byref(value))
+ if result:
+ raise EAS_Exception(result, 'EAS_SetParameter error %d (param=%d)' % (result, param), 'EAS_GetParameter')
+ eas_logger.debug('Call EAS_SetParameter: module=%d, param=%d, value=%d' % (module, param, value.value))
+ return value.value
+
+ def SelectLib (self, test_lib=False):
+ eas_logger.debug('Call EAS_SelectLib: test_lib=%s' % test_lib)
+ easdll = cdll.LoadLibrary('EASDLL')
+ with self.lock:
+ result = eas_dll.EAS_SelectLib(self.handle, 0, test_lib)
+ if result:
+ raise EAS_Exception(result, 'EAS_SelectLib error %d' % result, 'EAS_SelectLib')
+
+ def LoadDLSCollection (self, path):
+ eas_logger.debug('Call EAS_LoadDLSCollection: lib_path=%s' % path)
+ with self.lock:
+ result = eas_dll.EAS_LoadDLSCollection(self.handle, 0, path)
+ if result:
+ raise EAS_Exception(result, 'EAS_LoadDLSCollection error %d lib %s' % (result, path), 'EAS_LoadDLSCollection')
+
+ def SetAuxMixerHook (self, aux_mixer):
+
+ # if aux mixer has bigger buffer, re-allocate buffer
+ if (aux_mixer is not None) and (aux_mixer.buf_size > self.config.mixBufferSize):
+ buf_size = aux_mixer.buf_size
+ else:
+ buf_size = self.config.mixBufferSize
+
+ # allocate audio buffer for rendering
+ AudioBufferType = c_ubyte * (2 * buf_size * self.config.numChannels)
+ self.audio_buffer = AudioBufferType()
+ self.buf_size = buf_size
+ self.aux_mixer = aux_mixer
+
+ def SetDebugLevel (self, level=3):
+ """Sets the EAS debug level."""
+ with self.lock:
+ eas_logger.debug('Call EAS_SetDebugLevel')
+ eas_dll.EAS_DLLSetDebugLevel(self.handle, level)
+
+#---------------------------------------------------------------
+# EASAuxMixer
+#---------------------------------------------------------------
+class EASAuxMixer (object):
+ def __init__ (self, eas=None, num_streams=3, sample_rate=44100, max_sample_rate=44100):
+ eas_logger.debug('EASAuxMixer.__init__')
+ self.Init(eas, num_streams, sample_rate, max_sample_rate)
+
+ def __del__ (self):
+ eas_logger.debug('EASAuxMixer.__del__')
+ self.Shutdown()
+
+ def Init (self, eas=None, num_streams=3, sample_rate=44100, max_sample_rate=44100):
+ """Initializes the EAS Auxilliary Mixer."""
+ eas_logger.debug('EASAuxMixer.Init')
+
+ if hasattr(self, 'eas'):
+ raise EAS_Exception(-1, 'EASAuxMixer already initialized', 'EASAuxMixer.Init')
+
+ # initialize EAS, if necessary
+ if eas is None:
+ eas_logger.debug('No EAS handle --- initializing EAS')
+ eas = EAS()
+ self.alloc_eas = True
+ else:
+ self.alloc_eas = False
+ self.eas = eas
+
+ # initialize library
+ eas_logger.debug('Call EAS_InitAuxMixer')
+ buf_size = c_int(0)
+ result = eas_dll.EAS_InitAuxMixer(eas.handle, num_streams, sample_rate, max_sample_rate, byref(buf_size))
+ if result:
+ raise EAS_Exception(result, 'EAS_InitAuxMixer error %d' % result, 'EAS_InitAuxMixer')
+ self.buf_size = buf_size.value
+ self.streams = []
+ eas.SetAuxMixerHook(self)
+
+ def Shutdown (self):
+ """Shuts down the EAS Auxilliary Mixer"""
+ eas_logger.debug('EASAuxMixer.Shutdown')
+ if not hasattr(self, 'eas'):
+ return
+
+ with self.eas.lock:
+ if len(self.streams):
+ eas_logger.warning('Stream was not closed before EAS_ShutdownAuxMixer')
+ for stream in self.streams:
+ self.CloseStream(stream)
+
+ self.eas.SetAuxMixerHook(None)
+
+ # shutdown library
+ eas_logger.debug('Call EAS_ShutdownAuxMixer')
+ result = eas_dll.EAS_ShutdownAuxMixer(self.eas.handle)
+ if result:
+ raise EAS_Exception(result, 'EAS_ShutdownAuxMixer error %d' % result, 'EAS_ShutdownAuxMixer')
+
+ # if we created the EAS reference here, shut it down
+ if self.alloc_eas:
+ self.eas.Shutdown()
+ self.alloc_eas = False
+ del self.eas
+
+ def OpenStream (self, decoder_func, inst_data, sample_rate, num_channels):
+ """Opens an audio file to be played by the JET library and
+ returns a JET_File object
+
+ Arguments:
+ callback - callback function to decode more audio
+
+ """
+ with self.eas.lock:
+ eas_logger.debug('Call EAS_OpenAudioStream')
+ decoder_func = EAS_DECODER_FUNC(decoder_func)
+ stream_handle = c_void_p(0)
+ result = eas_dll.EAS_OpenAudioStream(self.eas.handle, decoder_func, inst_data, sample_rate, num_channels, stream_handle)
+ if result:
+ raise EAS_Exception(result, 'EAS_OpenAudioStream error %d on file %s' % (result, path), 'EAS_OpenAudioStream')
+ self.streams.add(stream_handle)
+ return stream_handle
+
+ def CloseStream (self, stream_handle):
+ """Closes an open audio stream."""
+ with self.eas.lock:
+ eas_logger.debug('Call EAS_CloseAudioStream')
+ result = eas_dll.JET_CloseFile(self.eas.handle, stream_handle)
+ if result:
+ raise EAS_Exception(result, 'EAS_CloseAudioStream error %d' % result, 'EAS_CloseAudioStream')
+
+#---------------------------------------------------------------
+# JET_Status
+#---------------------------------------------------------------
+class JET_Status (Structure):
+ _fields_ = [('currentUserID', c_int),
+ ('segmentRepeatCount', c_int),
+ ('numQueuedSegments', c_int),
+ ('paused', c_int),
+ ('location', c_long),
+ ('currentPlayingSegment', c_int),
+ ('currentQueuedSegment', c_int),
+ ]
+
+#---------------------------------------------------------------
+# JET_File
+#---------------------------------------------------------------
+class JET_File (object):
+ def __init__ (self, handle, jet):
+ eas_logger.debug('JET_File.__init__')
+ self.handle = handle
+ self.jet = jet
+
+#---------------------------------------------------------------
+# JET
+#---------------------------------------------------------------
+class JET (object):
+ def __init__ (self, eas=None):
+ # eas_logger.debug('JET.__init__')
+ self.Init(eas)
+
+ def __del__ (self):
+ eas_logger.debug('JET.__del__')
+ self.Shutdown()
+
+ def Init (self, eas=None, config=None):
+ """Initializes the JET Library."""
+ # eas_logger.debug('JET.Init')
+
+ if hasattr(self, 'eas'):
+ raise EAS_Exception(-1, 'JET library already initialized', 'Jet.Init')
+
+ # create some members
+ if eas is None:
+ # eas_logger.debug('No EAS handle --- initializing EAS')
+ eas = EAS()
+ self.alloc_eas = True
+ else:
+ self.alloc_eas = False
+ self.eas = eas
+ self.fileOpen = False
+
+ # handle configuration
+ if config is None:
+ config_handle = c_void_p(0)
+ config_size = 0
+ else:
+ jet_config = S_JET_CONFIG()
+ jet_config.appLowNote = config.appLowNote
+ config_handle = c_void_p(jet_config)
+ config_size = jet_config.sizeof()
+
+ # initialize library
+ # eas_logger.debug('Call JET_Init')
+ result = eas_dll.JET_Init(eas.handle, config_handle, config_size)
+ if result:
+ raise EAS_Exception(result, 'JET_Init error %d' % result, 'JET_Init')
+
+ def Shutdown (self):
+ """Shuts down the JET library"""
+ eas_logger.debug('JET.Shutdown')
+ if not hasattr(self, 'eas'):
+ return
+
+ with self.eas.lock:
+ if self.fileOpen:
+ eas_logger.warning('Stream was not closed before JET_Shutdown')
+ self.CloseFile()
+
+ # shutdown library
+ eas_logger.debug('Call JET_Shutdown')
+ result = eas_dll.JET_Shutdown(self.eas.handle)
+ if result:
+ raise EAS_Exception(result, 'JET_Shutdown error %d' % result, 'JET_Shutdown')
+
+ # if we created the EAS reference here, shut it down
+ if self.alloc_eas:
+ self.eas.Shutdown()
+ self.alloc_eas = False
+ del self.eas
+
+ def OpenFile (self, path):
+ """Opens an audio file to be played by the JET library and
+ returns a JET_File object
+
+ Arguments:
+ path - path to audio file
+
+ """
+ with self.eas.lock:
+ eas_logger.debug('Call JET_OpenFile for file: %s' % path)
+ result = eas_dll.JET_OpenFile(self.eas.handle, path)
+ if result:
+ raise EAS_Exception(result, 'JET_OpenFile error %d on file %s' % (result, path), 'JET_OpenFile')
+
+ def CloseFile (self):
+ """Closes an open audio file."""
+ with self.eas.lock:
+ eas_logger.debug('Call JET_CloseFile')
+ result = eas_dll.JET_CloseFile(self.eas.handle)
+ if result:
+ raise EAS_Exception(result, 'JET_CloseFile error %d' % result, 'JET_CloseFile')
+
+ def QueueSegment (self, userID, seg_num, dls_num=-1, repeat=0, tranpose=0, mute_flags=0):
+ """Queue a segment for playback.
+
+ Arguments:
+ seg_num - segment number to queue
+ repeat - repeat count (-1=repeat forever, 0=no repeat, 1+ = play n+1 times)
+ tranpose - transpose amount (+/-12)
+
+ """
+ with self.eas.lock:
+ eas_logger.debug('Call JET_QueueSegment')
+ result = eas_dll.JET_QueueSegment(self.eas.handle, seg_num, dls_num, repeat, tranpose, mute_flags, userID)
+ if result:
+ raise EAS_Exception(result, 'JET_QueueSegment error %d' % result, 'JET_QueueSegment')
+
+ def Clear_Queue(self):
+ """Kills the queue."""
+ with self.eas.lock:
+ eas_logger.debug('Call JET_Clear_Queue')
+ result = eas_dll.JET_Clear_Queue(self.eas.handle)
+ if result:
+ raise EAS_Exception(result, 'JET_Clear_Queue error %d' % result, 'JET_Clear_Queue')
+
+ def GetAppEvent(self):
+ """Gets an App event."""
+ with self.eas.lock:
+ eas_logger.debug('Call JET_GetEvent')
+ result = eas_dll.JET_GetEvent(self.eas.handle, 0, 0)
+ return result
+
+ def Play(self):
+ """Starts JET playback."""
+ with self.eas.lock:
+ eas_logger.debug('Call JET_Play')
+ result = eas_dll.JET_Play(self.eas.handle)
+ if result:
+ raise EAS_Exception(result, 'JET_Play error %d' % result, 'JET_Play')
+
+ def Pause(self):
+ """Pauses JET playback."""
+ with self.eas.lock:
+ eas_logger.debug('Call JET_Pause')
+ result = eas_dll.JET_Pause(self.eas.handle)
+ if result:
+ raise EAS_Exception(result, 'JET_Pause error %d' % result, 'JET_Pause')
+
+ def Render (self, count=None, secs=None):
+ """Calls EAS_Render to render audio.
+
+ Arguments
+ count - number of buffers to render
+ secs - number of seconds to render
+
+ If both count and secs are None, render a single buffer.
+
+ """
+ # calls JET.Render
+ with self.eas.lock:
+ self.eas.Render(count, secs)
+
+ def Status (self):
+ """Get JET status."""
+ with self.eas.lock:
+ eas_logger.debug('Call JET_Status')
+ status = JET_Status()
+ result = eas_dll.JET_Status(self.eas.handle, byref(status))
+ if result:
+ raise EAS_Exception(result, 'JET_Status error %d' % result, 'JET_Status')
+ eas_logger.debug("currentUserID=%d, repeatCount=%d, numQueuedSegments=%d, paused=%d" %
+ (status.currentUserID, status.segmentRepeatCount, status.numQueuedSegments, status.paused))
+ return status
+
+ def SetVolume (self, volume):
+ """Set the JET volume"""
+ eas_logger.debug('Call JET_SetVolume')
+ with self.eas.lock:
+ result = eas_dll.JET_SetVolume(self.eas.handle, volume)
+ if result:
+ raise EAS_Exception(result, 'JET_SetVolume error %d' % result, 'JET_SetVolume')
+
+ def SetTransposition (self, transposition):
+ """Set the transposition of a stream."""
+ eas_logger.debug('Call JET_SetTransposition')
+ with self.eas.lock:
+ result = eas_dll.JET_SetTransposition(self.eas.handle, transposition)
+ if result:
+ raise EAS_Exception(result, 'JET_SetTransposition error %d' % result, 'JET_SetTransposition')
+
+ def TriggerClip (self, clipID):
+ """Trigger a clip in the current segment."""
+ eas_logger.debug('Call JET_TriggerClip')
+ with self.eas.lock:
+ result = eas_dll.JET_TriggerClip(self.eas.handle, clipID)
+ if result:
+ raise EAS_Exception(result, 'JET_SetTransposition error %d' % result, 'JET_TriggerClip')
+
+ def SetMuteFlag (self, track_num, mute, sync=True):
+ """Trigger a clip in the current segment."""
+ eas_logger.debug('Call JET_SetMuteFlag')
+ with self.eas.lock:
+ result = eas_dll.JET_SetMuteFlag(self.eas.handle, track_num, mute, sync)
+ if result:
+ raise EAS_Exception(result, 'JET_SetMuteFlag error %d' % result, 'JET_SetMuteFlag')
+
+ def SetMuteFlags (self, mute_flags, sync=True):
+ """Trigger a clip in the current segment."""
+ eas_logger.debug('Call JET_SetMuteFlags')
+ with self.eas.lock:
+ result = eas_dll.JET_SetMuteFlags(self.eas.handle, mute_flags, sync)
+ if result:
+ raise EAS_Exception(result, 'JET_SetMuteFlag error %d' % result, 'JET_SetMuteFlags')
+
+