# platform-dependent audio module using BASS

import platform, ctypes, os
from pybass_constants import *
import ini

dll = None
dllf = ""
opus = ""
flac = ""
midi = ""
use_ctypes = False
if platform.system() == "Windows":
    dllf = "bass.dll"
    opus = "bassopus.dll"
    flac = "bassflac.dll"
    midi = "bassmidi.dll"
elif platform.system() == "Darwin":
    dllf = "libbass.dylib"
    opus = "libbassopus.dylib"
    flac = "libbassflac.dylib"
    midi = "libbassmidi.dylib"
else:
    dllf = "libbass.so"
    opus = "libbassopus.so"
    flac = "libbassflac.so"
    midi = "libbassmidi.so"

def checkAvailable():
    """
Check if the DLLs exist
Returns string with dll name if it's missing, empty if all DLLs are in place
    """
    one = os.path.exists(os.path.abspath(dllf))
    two = os.path.exists(os.path.abspath(opus))
    three = os.path.exists(os.path.abspath(flac))
    four = os.path.exists(os.path.abspath(midi))
    if not one: return dllf
    if not two: return two
    if not three: return three
    if not four: return four
    return ""



def init(freq=48000):
    """
Initialize BASS and the opus plugin
    """
    global dll, bassmidi, use_ctypes
    if not dll:
        if platform.system() == "Darwin":
            dll = ctypes.CDLL(dllf)
            use_ctypes = True
        else:
            import pybass as dll
            import pybass.pybassmidi as bassmidi
            
    if not dll.BASS_Init(ini.read_ini_int("AO2XP.ini", "Audio", "device", -1), freq, 0, 0, 0):
        print "[audio] Audio library could not be initialized. Error", getbasserror()
    if not dll.BASS_PluginLoad(os.path.abspath(opus), 0):
        print "[audio] Opus plugin failed to load. Error", getbasserror()
    if not dll.BASS_PluginLoad(os.path.abspath(flac), 0):
        print "[audio] FLAC plugin failed to load. Error", getbasserror()
    if not dll.BASS_PluginLoad(os.path.abspath(midi), 0):
        print "[audio] MIDI plugin failed to load. Error", getbasserror()
        
    if os.path.exists(os.path.abspath("gm.sf2")):
        dll.BASS_SetConfigPtr(bassmidi.BASS_CONFIG_MIDI_DEFFONT, "gm.sf2");
    else:
        print "[audio] Soundfont not fount. MIDI files will not play."

def free():
    """
Free BASS
    """
    dll.BASS_Free()

def getcurrdevice():
    return dll.BASS_GetDevice()

def getdevices():
    """
Get BASS devices
    """
    info = BASS_DEVICEINFO() if use_ctypes else dll.BASS_DEVICEINFO()
    ind = 0
    devices = []
    while dll.BASS_GetDeviceInfo(ind, ctypes.c_voidp(ctypes.addressof(info)) if use_ctypes else info):
        devices.append(info.name)
        ind += 1
    return devices

def loadhandle(mem, file, offset=0, length=0, flags=0):
    """
Load a BASS stream handle
    """
    return dll.BASS_StreamCreateFile(mem, file, QWORD(offset), QWORD(length), flags)

def loadURLhandle(url, offset, flags, proc=DOWNLOADPROC(), user=0):
    """
Load a BASS stream handle from an URL
    """
    return dll.BASS_StreamCreateURL(url, offset, flags, proc, user)
    
def loadMOD(mem, file, offset=0, length=0, flags=0):
    """
Load a BASS module file
    """
    return dll.BASS_MusicLoad(mem, file, QWORD(offset), length, flags, 0)
    
def loadMIDI(mem, file, offset=0, length=0, flags=0):
    """
Load a BASS stream handle
    """
    return bassmidi.BASS_MIDI_StreamCreateFile(mem, file, QWORD(offset), QWORD(length), flags, 0)

def freehandle(handle):
    """
Free a handle
    """
    return dll.BASS_StreamFree(handle)
    
def freeMOD(handle):
    """
Free a module handle
    """
    return dll.BASS_MusicFree(handle)

def playhandle(handle, restart):
    """
Play a handle
    """
    return dll.BASS_ChannelPlay(handle, restart)
    
def pausehandle(handle):
    """
Play a handle
    """
    return dll.BASS_ChannelPause(handle)

def stophandle(handle):
    """
Stop handle playback
    """
    return dll.BASS_ChannelStop(handle)

def handleisactive(handle):
    """
Get handle playback status
    """
    return dll.BASS_ChannelIsActive(handle)

def sethandleattr(handle, attr, value):
    """
Set handle attribute
    """
    if use_ctypes and type(value) == float: value = ctypes.c_float(value)
    return dll.BASS_ChannelSetAttribute(handle, attr, value)
    
def getbasserror():
    return dll.BASS_ErrorGetCode()