/*
    Copyright (c) 2007 SIEGE Development Team
    All rights reserved.
    
    This file is part of libSIEGE.
    
    This software is copyrighted work licensed under the terms of the
    2-clause BSD license. Please consult the file "license.txt" for
    details.
    
    If you did not recieve the file with this program, please email
    Tim Chas <darkuranium@gmail.com>.
*/

#include "source.h"

static void pysSourceDealloc(PysSource* self)
{
    Py_XDECREF(self->buffer);

    sgAudioSourceDestroy(self->source);
    self->ob_type->tp_free(self);
}
static PyObject* pysSourceNew(PyTypeObject *type, PyObject *args, PyObject *kwargs)
{
    PysSource* self = (PysSource*)type->tp_alloc(type, 0);
    if(self != NULL)
    {
        self->buffer = NULL;
        self->source = NULL;
    }
    return (PyObject*)self;
}
static int pysSourceInit(PysSource* self, PyObject* args, PyObject* kwargs)
{
    PyObject* obj;
    float priority = 0.0;
    float volume = 1.0;
    float pitch = 1.0;
    SGbool looping = SG_FALSE;
    if(!PyArg_ParseTuple(args, "O|fffb", &obj, &priority, &volume, &pitch, &looping));
        return -1;
    if(!pysBufferCheck(obj))
        return -1;

    Py_INCREF(obj);
    PysBuffer* buffer = (PysBuffer*)obj;
    self->buffer = buffer;
    self->source = sgAudioSourceCreate(buffer->buffer, priority, volume, pitch, looping);

    return 0;
}

static PyObject* pysSourcePlay(PysSource* self)
{
    sgAudioSourcePlay(self->source);
    Py_RETURN_NONE;
}
static PyObject* pysSourceIsPlaying(PysSource* self)
{
    if(sgAudioSourceIsPlaying(self->source))
        Py_RETURN_TRUE;
    Py_RETURN_FALSE;
}
static PyObject* pysSourcePause(PysSource* self)
{
    sgAudioSourcePause(self->source);
    Py_RETURN_NONE;
}
static PyObject* pysSourceIsPaused(PysSource* self)
{
    if(sgAudioSourceIsPaused(self->source))
        Py_RETURN_TRUE;
    Py_RETURN_FALSE;
}
static PyObject* pysSourceRewind(PysSource* self)
{
    sgAudioSourceRewind(self->source);
    Py_RETURN_NONE;
}
/*static PyObject* pysSourceIsRewinded(PysSource* self)
{
    if(sgAudioSourceIsRewinded(self->source))
        Py_RETURN_TRUE;
    Py_RETURN_FALSE;
}*/
static PyObject* pysSourceStop(PysSource* self)
{
    sgAudioSourceStop(self->source);
    Py_RETURN_NONE;
}
static PyObject* pysSourceIsStopped(PysSource* self)
{
    if(sgAudioSourceIsStopped(self->source))
        Py_RETURN_TRUE;
    Py_RETURN_FALSE;
}
static PyObject* pysSourceIsActive(PysSource* self)
{
    if(sgAudioSourceIsActive(self->source))
        Py_RETURN_TRUE;
    Py_RETURN_FALSE;
}
static PyObject* pysSourceQueueBuffers(PysSource* self, PyObject* args)
{
    size_t size = PyTuple_GET_SIZE(args);
    size_t i;

    SGAudioBuffer** buffers = malloc(size * sizeof(SGAudioBuffer*));

    for(i = 0; i < size; i++)
    {
        PyObject* obj = PyTuple_GET_ITEM(args, i);
        if(!pysBufferCheck(obj))
        {
            free(buffers);
            return NULL;
        }
        PysBuffer* buffer = (PysBuffer*)obj;
        buffers[i] = buffer->buffer;
    }

    sgAudioSourceQueueBuffers(self->source, buffers, size);

    free(buffers);
    Py_RETURN_NONE;
}
static PyObject* pysSourceQueueBuffer(PysSource* self, PyObject* args)
{
    PyObject* obj;
    if(!PyArg_ParseTuple(args, "O", &obj))
        return NULL;
    if(!pysBufferCheck(obj))
        return NULL;

    PysBuffer* buffer = (PysBuffer*)obj;
    sgAudioSourceQueueBuffer(self->source, buffer->buffer);

    Py_RETURN_NONE;
}

static PyObject* pysSourceSetPosition(PysSource* self, PyObject* args)
{
    float x, y, z;
    size_t size = PyTuple_GET_SIZE(args);

    if(size == 3)
    {
        if(!PyArg_ParseTuple(args, "fff", &x, &y, &z))
            return NULL;
        sgAudioSourceSetPosition3f(self->source, x, y, z);
    }
    else if(size == 2)
    {
        if(!PyArg_ParseTuple(args, "ff", &x, &y))
            return NULL;
        sgAudioSourceSetPosition2f(self->source, x, y);
    }
    else
        return NULL;

    Py_RETURN_NONE;
}
static PyObject* pysSourceGetPosition(PysSource* self)
{
    float x, y, z;
    sgAudioSourceGetPosition3f(self->source, &x, &y, &z);
    return Py_BuildValue("(fff)", x, y, z);
}

static PyObject* pysSourceSetVelocity(PysSource* self, PyObject* args)
{
    float x, y, z;
    size_t size = PyTuple_GET_SIZE(args);

    if(size == 3)
    {
        if(!PyArg_ParseTuple(args, "fff", &x, &y, &z))
            return NULL;
        sgAudioSourceSetVelocity3f(self->source, x, y, z);
    }
    else if(size == 2)
    {
        if(!PyArg_ParseTuple(args, "ff", &x, &y))
            return NULL;
        sgAudioSourceSetVelocity2f(self->source, x, y);
    }
    else
        return NULL;

    Py_RETURN_NONE;
}
static PyObject* pysSourceGetVelocity(PysSource* self)
{
    float x, y, z;
    sgAudioSourceGetVelocity3f(self->source, &x, &y, &z);
    return Py_BuildValue("(fff)", x, y, z);
}

/*static PyObject* pysSourceSetFalloff(PysSource* self, PyObject* args)
{
    float falloff;
    if(!PyArg_ParseTuple(args, "f", &falloff))
        return NULL;
    sgAudioSourceSetFalloff(self->source, falloff);
    Py_RETURN_NONE;
}
static PyObject* pysSourceGetFalloff(PysSource* self)
{
    return Py_BuildValue("f", sgAudioSourceGetFalloff(self->source));
}*/

static PyObject* pysSourceSetPitch(PysSource* self, PyObject* args)
{
    float pitch;
    if(!PyArg_ParseTuple(args, "f", &pitch))
        return NULL;
    sgAudioSourceSetPitch(self->source, pitch);
    Py_RETURN_NONE;
}
static PyObject* pysSourceGetPitch(PysSource* self)
{
    return Py_BuildValue("f", sgAudioSourceGetPitch(self->source));
}

static PyObject* pysSourceSetVolume(PysSource* self, PyObject* args)
{
    float volume;
    if(!PyArg_ParseTuple(args, "f", &volume))
        return NULL;
    sgAudioSourceSetVolume(self->source, volume);
    Py_RETURN_NONE;
}
static PyObject* pysSourceGetVolume(PysSource* self)
{
    return Py_BuildValue("f", sgAudioSourceGetVolume(self->source));
}

static PyObject* pysSourceSetLooping(PysSource* self, PyObject* args)
{
    SGbool looping;
    if(!PyArg_ParseTuple(args, "b", &looping))
        return NULL;
    sgAudioSourceSetLooping(self->source, looping);
    Py_RETURN_NONE;
}
static PyObject* pysSourceGetLooping(PysSource* self)
{
    if(sgAudioSourceGetLooping(self->source))
        Py_RETURN_TRUE;
    Py_RETURN_FALSE;
}

static PyMethodDef PysSourceMethods[] = {
    {"play", (PyCFunction)pysSourcePlay, METH_NOARGS, ""},
    {"isPlaying", (PyCFunction)pysSourceIsPlaying, METH_NOARGS, ""},
    {"pause", (PyCFunction)pysSourcePause, METH_NOARGS, ""},
    {"isPaused", (PyCFunction)pysSourceIsPaused, METH_NOARGS, ""},
    {"rewind", (PyCFunction)pysSourceRewind, METH_NOARGS, ""},
    //{"isRewinded", (PyCFunction)pysSourceIsRewinded, METH_NOARGS, ""},
    {"stop", (PyCFunction)pysSourceStop, METH_NOARGS, ""},
    {"isStopped", (PyCFunction)pysSourceIsStopped, METH_NOARGS, ""},
    {"isActive", (PyCFunction)pysSourceIsActive, METH_NOARGS, ""},
    {"queueBuffers", (PyCFunction)pysSourceQueueBuffers, METH_VARARGS, ""},
    {"queueBuffer", (PyCFunction)pysSourceQueueBuffer, METH_VARARGS, ""},

    {"setPosition", (PyCFunction)pysSourceSetPosition, METH_VARARGS, ""},
    {"getPosition", (PyCFunction)pysSourceGetPosition, METH_NOARGS, ""},

    {"setVelocity", (PyCFunction)pysSourceSetVelocity, METH_VARARGS, ""},
    {"getVelocity", (PyCFunction)pysSourceGetVelocity, METH_NOARGS, ""},

    //{"setFalloff", (PyCFunction)pysSourceSetFalloff, METH_VARARGS, ""},
    //{"getFalloff", (PyCFunction)pysSourceGetFalloff, METH_NOARGS, ""},

    {"setPitch", (PyCFunction)pysSourceSetPitch, METH_VARARGS, ""},
    {"getPitch", (PyCFunction)pysSourceGetPitch, METH_NOARGS, ""},

    {"setVolume", (PyCFunction)pysSourceSetVolume, METH_VARARGS, ""},
    {"getVolume", (PyCFunction)pysSourceGetVolume, METH_NOARGS, ""},

    {"setLooping", (PyCFunction)pysSourceSetLooping, METH_VARARGS, ""},
    {"getLooping", (PyCFunction)pysSourceGetLooping, METH_NOARGS, ""},
    {NULL, NULL, 0, NULL}
};

static PyMemberDef PysSourceMembers[] = {
    {NULL, 0, 0, 0, NULL}
};

static PyTypeObject PysSourceType = {
    PyObject_HEAD_INIT(NULL)
    0,                         /*ob_size*/
    "siege.audio.Source",      /*tp_name*/
    sizeof(PysSource),         /*tp_basicsize*/
    0,                         /*tp_itemsize*/
    (destructor)pysSourceDealloc, /*tp_dealloc*/
    0,                         /*tp_print*/
    0,                         /*tp_getattr*/
    0,                         /*tp_setattr*/
    0,                         /*tp_compare*/
    0,                         /*tp_repr*/
    0,                         /*tp_as_number*/
    0,                         /*tp_as_sequence*/
    0,                         /*tp_as_mapping*/
    0,                         /*tp_hash */
    0,                         /*tp_call*/
    0,                         /*tp_str*/
    0,                         /*tp_getattro*/
    0,                         /*tp_setattro*/
    0,                         /*tp_as_buffer*/
    Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, /*tp_flags*/
    "",                        /* tp_doc */
    0,		                   /* tp_traverse */
    0,		                   /* tp_clear */
    0,		                   /* tp_richcompare */
    0,		                   /* tp_weaklistoffset */
    0,		                   /* tp_iter */
    0,		                   /* tp_iternext */
    PysSourceMethods,          /* tp_methods */
    PysSourceMembers,          /* tp_members */
    0,                         /* tp_getset */
    0,                         /* tp_base */
    0,                         /* tp_dict */
    0,                         /* tp_descr_get */
    0,                         /* tp_descr_set */
    0,                         /* tp_dictoffset */
    (initproc)pysSourceInit,   /* tp_init */
    0,                         /* tp_alloc */
    pysSourceNew,                 /* tp_new */
};

int pysSourceCheck(PyObject* o)
{
    return PyObject_TypeCheck(o, &PysSourceType);
}
void sgpyInitAudioSource(PyObject* parent)
{
    PysSourceType.tp_new = PyType_GenericNew;
    if(PyType_Ready(&PysSourceType) < 0)
        return;

    Py_INCREF(&PysSourceType);
    PyModule_AddObject(parent, "Source", (PyObject*)&PysSourceType);
}
