|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
"""Multi-library, cross-platform audio decoding.""" |
|
|
|
from . import ffdec |
|
from .exceptions import DecodeError, NoBackendError |
|
from .version import version as __version__ |
|
from .base import AudioFile |
|
|
|
|
|
def _gst_available(): |
|
"""Determine whether Gstreamer and the Python GObject bindings are |
|
installed. |
|
""" |
|
try: |
|
import gi |
|
except ImportError: |
|
return False |
|
|
|
try: |
|
gi.require_version('Gst', '1.0') |
|
except (ValueError, AttributeError): |
|
return False |
|
|
|
try: |
|
from gi.repository import Gst |
|
except ImportError: |
|
return False |
|
|
|
return True |
|
|
|
|
|
def _ca_available(): |
|
"""Determines whether CoreAudio is available (i.e., we're running on |
|
Mac OS X). |
|
""" |
|
import ctypes.util |
|
lib = ctypes.util.find_library('AudioToolbox') |
|
return lib is not None |
|
|
|
|
|
def _mad_available(): |
|
"""Determines whether the pymad bindings are available.""" |
|
try: |
|
import mad |
|
except ImportError: |
|
return False |
|
else: |
|
return True |
|
|
|
|
|
|
|
BACKENDS = [] |
|
|
|
|
|
def available_backends(flush_cache=False): |
|
"""Returns a list of backends that are available on this system. |
|
|
|
The list of backends is cached after the first call. |
|
If the parameter `flush_cache` is set to `True`, then the cache |
|
will be flushed and the backend list will be reconstructed. |
|
""" |
|
|
|
if BACKENDS and not flush_cache: |
|
return BACKENDS |
|
|
|
|
|
from . import rawread |
|
result = [rawread.RawAudioFile] |
|
|
|
|
|
if _ca_available(): |
|
from . import macca |
|
result.append(macca.ExtAudioFile) |
|
|
|
|
|
if _gst_available(): |
|
from . import gstdec |
|
result.append(gstdec.GstAudioFile) |
|
|
|
|
|
if _mad_available(): |
|
from . import maddec |
|
result.append(maddec.MadAudioFile) |
|
|
|
|
|
if ffdec.available(): |
|
result.append(ffdec.FFmpegAudioFile) |
|
|
|
|
|
BACKENDS[:] = result |
|
|
|
return BACKENDS |
|
|
|
|
|
def audio_open(path, backends=None): |
|
"""Open an audio file using a library that is available on this |
|
system. |
|
|
|
The optional `backends` parameter can be a list of audio file |
|
classes to try opening the file with. If it is not provided, |
|
`audio_open` tries all available backends. If you call this function |
|
many times, you can avoid the cost of checking for available |
|
backends every time by calling `available_backends` once and passing |
|
the result to each `audio_open` call. |
|
|
|
If all backends fail to read the file, a NoBackendError exception is |
|
raised. |
|
""" |
|
if backends is None: |
|
backends = available_backends() |
|
|
|
for BackendClass in backends: |
|
try: |
|
return BackendClass(path) |
|
except DecodeError: |
|
pass |
|
|
|
|
|
raise NoBackendError() |
|
|