/*
  Simple DirectMedia Layer
  Copyright (C) 1997-2022 Sam Lantinga <slouken@libsdl.org>

  This software is provided 'as-is', without any express or implied
  warranty.  In no event will the authors be held liable for any damages
  arising from the use of this software.

  Permission is granted to anyone to use this software for any purpose,
  including commercial applications, and to alter it and redistribute it
  freely, subject to the following restrictions:

  1. The origin of this software must not be misrepresented; you must not
     claim that you wrote the original software. If you use this software
     in a product, an acknowledgment in the product documentation would be
     appreciated but is not required.
  2. Altered source versions must be plainly marked as such, and must not be
     misrepresented as being the original software.
  3. This notice may not be removed or altered from any source distribution.
*/
#include "../../SDL_internal.h"

#if SDL_AUDIO_DRIVER_NAS

/* Allow access to a raw mixing buffer */

#include <signal.h>
#include <unistd.h>

#include "SDL_timer.h"
#include "SDL_audio.h"
#include "SDL_loadso.h"
#include "../SDL_audio_c.h"
#include "SDL_nasaudio.h"

static void (*NAS_AuCloseServer) (AuServer *);
static void (*NAS_AuNextEvent) (AuServer *, AuBool, AuEvent *);
static AuBool(*NAS_AuDispatchEvent) (AuServer *, AuEvent *);
static void (*NAS_AuHandleEvents) (AuServer *);
static AuFlowID(*NAS_AuCreateFlow) (AuServer *, AuStatus *);
static void (*NAS_AuStartFlow) (AuServer *, AuFlowID, AuStatus *);
static void (*NAS_AuSetElements)
  (AuServer *, AuFlowID, AuBool, int, AuElement *, AuStatus *);
static void (*NAS_AuWriteElement)
  (AuServer *, AuFlowID, int, AuUint32, AuPointer, AuBool, AuStatus *);
static AuUint32 (*NAS_AuReadElement)
  (AuServer *, AuFlowID, int, AuUint32, AuPointer, AuStatus *);
static AuServer *(*NAS_AuOpenServer)
  (_AuConst char *, int, _AuConst char *, int, _AuConst char *, char **);
static AuEventHandlerRec *(*NAS_AuRegisterEventHandler)
  (AuServer *, AuMask, int, AuID, AuEventHandlerCallback, AuPointer);


#ifdef SDL_AUDIO_DRIVER_NAS_DYNAMIC

static const char *nas_library = SDL_AUDIO_DRIVER_NAS_DYNAMIC;
static void *nas_handle = NULL;

static int
load_nas_sym(const char *fn, void **addr)
{
    *addr = SDL_LoadFunction(nas_handle, fn);
    if (*addr == NULL) {
        return 0;
    }
    return 1;
}

/* cast funcs to char* first, to please GCC's strict aliasing rules. */
#define SDL_NAS_SYM(x) \
    if (!load_nas_sym(#x, (void **) (char *) &NAS_##x)) return -1
#else
#define SDL_NAS_SYM(x) NAS_##x = x
#endif

static int
load_nas_syms(void)
{
    SDL_NAS_SYM(AuCloseServer);
    SDL_NAS_SYM(AuNextEvent);
    SDL_NAS_SYM(AuDispatchEvent);
    SDL_NAS_SYM(AuHandleEvents);
    SDL_NAS_SYM(AuCreateFlow);
    SDL_NAS_SYM(AuStartFlow);
    SDL_NAS_SYM(AuSetElements);
    SDL_NAS_SYM(AuWriteElement);
    SDL_NAS_SYM(AuReadElement);
    SDL_NAS_SYM(AuOpenServer);
    SDL_NAS_SYM(AuRegisterEventHandler);
    return 0;
}

#undef SDL_NAS_SYM

#ifdef SDL_AUDIO_DRIVER_NAS_DYNAMIC

static void
UnloadNASLibrary(void)
{
    if (nas_handle != NULL) {
        SDL_UnloadObject(nas_handle);
        nas_handle = NULL;
    }
}

static int
LoadNASLibrary(void)
{
    int retval = 0;
    if (nas_handle == NULL) {
        nas_handle = SDL_LoadObject(nas_library);
        if (nas_handle == NULL) {
            /* Copy error string so we can use it in a new SDL_SetError(). */
            const char *origerr = SDL_GetError();
            const size_t len = SDL_strlen(origerr) + 1;
            char *err = SDL_stack_alloc(char, len);
            SDL_strlcpy(err, origerr, len);
            SDL_SetError("NAS: SDL_LoadObject('%s') failed: %s", nas_library, err);
            SDL_stack_free(err);
            retval = -1;
        } else {
            retval = load_nas_syms();
            if (retval < 0) {
                UnloadNASLibrary();
            }
        }
    }
    return retval;
}

#else

static void
UnloadNASLibrary(void)
{
}

static int
LoadNASLibrary(void)
{
    load_nas_syms();
    return 0;
}

#endif /* SDL_AUDIO_DRIVER_NAS_DYNAMIC */

/* This function waits until it is possible to write a full sound buffer */
static void
NAS_WaitDevice(_THIS)
{
    while (this->hidden->buf_free < this->hidden->mixlen) {
        AuEvent ev;
        NAS_AuNextEvent(this->hidden->aud, AuTrue, &ev);
        NAS_AuDispatchEvent(this->hidden->aud, &ev);
    }
}

static void
NAS_PlayDevice(_THIS)
{
    while (this->hidden->mixlen > this->hidden->buf_free) {
        /*
         * We think the buffer is full? Yikes! Ask the server for events,
         *  in the hope that some of them is LowWater events telling us more
         *  of the buffer is free now than what we think.
         */
        AuEvent ev;
        NAS_AuNextEvent(this->hidden->aud, AuTrue, &ev);
        NAS_AuDispatchEvent(this->hidden->aud, &ev);
    }
    this->hidden->buf_free -= this->hidden->mixlen;

    /* Write the audio data */
    NAS_AuWriteElement(this->hidden->aud, this->hidden->flow, 0,
                       this->hidden->mixlen, this->hidden->mixbuf, AuFalse,
                       NULL);

    this->hidden->written += this->hidden->mixlen;

#ifdef DEBUG_AUDIO
    fprintf(stderr, "Wrote %d bytes of audio data\n", this->hidden->mixlen);
#endif
}

static Uint8 *
NAS_GetDeviceBuf(_THIS)
{
    return (this->hidden->mixbuf);
}

static int
NAS_CaptureFromDevice(_THIS, void *buffer, int buflen)
{
    struct SDL_PrivateAudioData *h = this->hidden;
    int retval;

    while (SDL_TRUE) {
        /* just keep the event queue moving and the server chattering. */
        NAS_AuHandleEvents(h->aud);
    
        retval = (int) NAS_AuReadElement(h->aud, h->flow, 1, buflen, buffer, NULL);
        /*printf("read %d capture bytes\n", (int) retval);*/
        if (retval == 0) {
            SDL_Delay(10);  /* don't burn the CPU if we're waiting for data. */
        } else {
            break;
        }
    }

    return retval;
}

static void
NAS_FlushCapture(_THIS)
{
    struct SDL_PrivateAudioData *h = this->hidden;
    AuUint32 total = 0;
    AuUint32 br;
    Uint8 buf[512];

    do {
        /* just keep the event queue moving and the server chattering. */
        NAS_AuHandleEvents(h->aud);
        br = NAS_AuReadElement(h->aud, h->flow, 1, sizeof (buf), buf, NULL);
        /*printf("flushed %d capture bytes\n", (int) br);*/
        total += br;
    } while ((br == sizeof (buf)) && (total < this->spec.size));
}

static void
NAS_CloseDevice(_THIS)
{
    if (this->hidden->aud) {
        NAS_AuCloseServer(this->hidden->aud);
    }
    SDL_free(this->hidden->mixbuf);
    SDL_free(this->hidden);
}

static AuBool
event_handler(AuServer * aud, AuEvent * ev, AuEventHandlerRec * hnd)
{
    SDL_AudioDevice *this = (SDL_AudioDevice *) hnd->data;
    struct SDL_PrivateAudioData *h = this->hidden;
    if (this->iscapture) {
        return AuTrue;  /* we don't (currently) care about any of this for capture devices */
    }

    switch (ev->type) {
    case AuEventTypeElementNotify:
        {
            AuElementNotifyEvent *event = (AuElementNotifyEvent *) ev;

            switch (event->kind) {
            case AuElementNotifyKindLowWater:
                if (h->buf_free >= 0) {
                    h->really += event->num_bytes;
                    gettimeofday(&h->last_tv, 0);
                    h->buf_free += event->num_bytes;
                } else {
                    h->buf_free = event->num_bytes;
                }
                break;
            case AuElementNotifyKindState:
                switch (event->cur_state) {
                case AuStatePause:
                    if (event->reason != AuReasonUser) {
                        if (h->buf_free >= 0) {
                            h->really += event->num_bytes;
                            gettimeofday(&h->last_tv, 0);
                            h->buf_free += event->num_bytes;
                        } else {
                            h->buf_free = event->num_bytes;
                        }
                    }
                    break;
                }
            }
        }
    }
    return AuTrue;
}

static AuDeviceID
find_device(_THIS)
{
    /* These "Au" things are all macros, not functions... */
    struct SDL_PrivateAudioData *h = this->hidden;
    const unsigned int devicekind = this->iscapture ? AuComponentKindPhysicalInput : AuComponentKindPhysicalOutput;
    const int numdevs = AuServerNumDevices(h->aud);
    const int nch = this->spec.channels;
    int i;

    /* Try to find exact match on channels first... */
    for (i = 0; i < numdevs; i++) {
        const AuDeviceAttributes *dev = AuServerDevice(h->aud, i);
        if ((AuDeviceKind(dev) == devicekind) && (AuDeviceNumTracks(dev) == nch)) {
            return AuDeviceIdentifier(dev);
        }
    }

    /* Take anything, then... */
    for (i = 0; i < numdevs; i++) {
        const AuDeviceAttributes *dev = AuServerDevice(h->aud, i);
        if (AuDeviceKind(dev) == devicekind) {
            this->spec.channels = AuDeviceNumTracks(dev);
            return AuDeviceIdentifier(dev);
        }
    }
    return AuNone;
}

static int
NAS_OpenDevice(_THIS, const char *devname)
{
    AuElement elms[3];
    int buffer_size;
    SDL_bool iscapture = this->iscapture;
    SDL_AudioFormat test_format, format = 0;

    /* Initialize all variables that we clean on shutdown */
    this->hidden = (struct SDL_PrivateAudioData *)
        SDL_malloc((sizeof *this->hidden));
    if (this->hidden == NULL) {
        return SDL_OutOfMemory();
    }
    SDL_zerop(this->hidden);

    /* Try for a closest match on audio format */
    for (test_format = SDL_FirstAudioFormat(this->spec.format); test_format; test_format = SDL_NextAudioFormat()) {
        switch (test_format) {
        case AUDIO_U8:
            format = AuFormatLinearUnsigned8;
            break;
        case AUDIO_S8:
            format = AuFormatLinearSigned8;
            break;
        case AUDIO_U16LSB:
            format = AuFormatLinearUnsigned16LSB;
            break;
        case AUDIO_U16MSB:
            format = AuFormatLinearUnsigned16MSB;
            break;
        case AUDIO_S16LSB:
            format = AuFormatLinearSigned16LSB;
            break;
        case AUDIO_S16MSB:
            format = AuFormatLinearSigned16MSB;
            break;
        default:
            continue;
        }
        break;
    }
    if (!test_format) {
        return SDL_SetError("%s: Unsupported audio format", "nas");
    }
    this->spec.format = test_format;

    this->hidden->aud = NAS_AuOpenServer("", 0, NULL, 0, NULL, NULL);
    if (this->hidden->aud == 0) {
        return SDL_SetError("NAS: Couldn't open connection to NAS server");
    }

    this->hidden->dev = find_device(this);
    if ((this->hidden->dev == AuNone)
        || (!(this->hidden->flow = NAS_AuCreateFlow(this->hidden->aud, 0)))) {
        return SDL_SetError("NAS: Couldn't find a fitting device on NAS server");
    }

    buffer_size = this->spec.freq;
    if (buffer_size < 4096)
        buffer_size = 4096;

    if (buffer_size > 32768)
        buffer_size = 32768;    /* So that the buffer won't get unmanageably big. */

    /* Calculate the final parameters for this audio specification */
    SDL_CalculateAudioSpec(&this->spec);

    if (iscapture) {
        AuMakeElementImportDevice(elms, this->spec.freq, this->hidden->dev,
                                  AuUnlimitedSamples, 0, NULL);
        AuMakeElementExportClient(elms + 1, 0, this->spec.freq, format,
                                  this->spec.channels, AuTrue, buffer_size,
                                  buffer_size, 0, NULL);
    } else {
        AuMakeElementImportClient(elms, this->spec.freq, format,
                                  this->spec.channels, AuTrue, buffer_size,
                                  buffer_size / 4, 0, NULL);
        AuMakeElementExportDevice(elms + 1, 0, this->hidden->dev, this->spec.freq,
                                  AuUnlimitedSamples, 0, NULL);
    }

    NAS_AuSetElements(this->hidden->aud, this->hidden->flow, AuTrue,
                      2, elms, NULL);

    NAS_AuRegisterEventHandler(this->hidden->aud, AuEventHandlerIDMask, 0,
                               this->hidden->flow, event_handler,
                               (AuPointer) this);

    NAS_AuStartFlow(this->hidden->aud, this->hidden->flow, NULL);

    /* Allocate mixing buffer */
    if (!iscapture) {
        this->hidden->mixlen = this->spec.size;
        this->hidden->mixbuf = (Uint8 *) SDL_malloc(this->hidden->mixlen);
        if (this->hidden->mixbuf == NULL) {
            return SDL_OutOfMemory();
        }
        SDL_memset(this->hidden->mixbuf, this->spec.silence, this->spec.size);
    }

    /* We're ready to rock and roll. :-) */
    return 0;
}

static void
NAS_Deinitialize(void)
{
    UnloadNASLibrary();
}

static SDL_bool
NAS_Init(SDL_AudioDriverImpl * impl)
{
    if (LoadNASLibrary() < 0) {
        return SDL_FALSE;
    } else {
        AuServer *aud = NAS_AuOpenServer("", 0, NULL, 0, NULL, NULL);
        if (aud == NULL) {
            SDL_SetError("NAS: AuOpenServer() failed (no audio server?)");
            return SDL_FALSE;
        }
        NAS_AuCloseServer(aud);
    }

    /* Set the function pointers */
    impl->OpenDevice = NAS_OpenDevice;
    impl->PlayDevice = NAS_PlayDevice;
    impl->WaitDevice = NAS_WaitDevice;
    impl->GetDeviceBuf = NAS_GetDeviceBuf;
    impl->CaptureFromDevice = NAS_CaptureFromDevice;
    impl->FlushCapture = NAS_FlushCapture;
    impl->CloseDevice = NAS_CloseDevice;
    impl->Deinitialize = NAS_Deinitialize;

    impl->OnlyHasDefaultOutputDevice = SDL_TRUE;
    impl->OnlyHasDefaultCaptureDevice = SDL_TRUE;
    impl->HasCaptureSupport = SDL_TRUE;

    return SDL_TRUE;   /* this audio target is available. */
}

AudioBootStrap NAS_bootstrap = {
    "nas", "Network Audio System", NAS_Init, SDL_FALSE
};

#endif /* SDL_AUDIO_DRIVER_NAS */

/* vi: set ts=4 sw=4 expandtab: */
