/*
  Simple DirectMedia Layer
  Copyright (C) 1997-2016 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_WINMM

/* Allow access to a raw mixing buffer */

#include "../../core/windows/SDL_windows.h"
#include <mmsystem.h>

#include "SDL_assert.h"
#include "SDL_timer.h"
#include "SDL_audio.h"
#include "../SDL_audio_c.h"
#include "SDL_winmm.h"

#ifndef WAVE_FORMAT_IEEE_FLOAT
#define WAVE_FORMAT_IEEE_FLOAT 0x0003
#endif

#define DETECT_DEV_IMPL(iscap, typ, capstyp) \
static void DetectWave##typ##Devs(void) { \
    const UINT iscapture = iscap ? 1 : 0; \
    const UINT devcount = wave##typ##GetNumDevs(); \
    capstyp##2W caps; \
    UINT i; \
    for (i = 0; i < devcount; i++) { \
	if (wave##typ##GetDevCaps(i,(LP##capstyp##W)&caps,sizeof(caps))==MMSYSERR_NOERROR) { \
            char *name = WIN_LookupAudioDeviceName(caps.szPname,&caps.NameGuid); \
            if (name != NULL) { \
                SDL_AddAudioDevice((int) iscapture, name, (void *) ((size_t) i+1)); \
                SDL_free(name); \
            } \
        } \
    } \
}

DETECT_DEV_IMPL(SDL_FALSE, Out, WAVEOUTCAPS)
DETECT_DEV_IMPL(SDL_TRUE, In, WAVEINCAPS)

static void
WINMM_DetectDevices(void)
{
    DetectWaveInDevs();
    DetectWaveOutDevs();
}

static void CALLBACK
CaptureSound(HWAVEIN hwi, UINT uMsg, DWORD_PTR dwInstance,
          DWORD_PTR dwParam1, DWORD_PTR dwParam2)
{
    SDL_AudioDevice *this = (SDL_AudioDevice *) dwInstance;

    /* Only service "buffer is filled" messages */
    if (uMsg != WIM_DATA)
        return;

    /* Signal that we have a new buffer of data */
    ReleaseSemaphore(this->hidden->audio_sem, 1, NULL);
}


/* The Win32 callback for filling the WAVE device */
static void CALLBACK
FillSound(HWAVEOUT hwo, UINT uMsg, DWORD_PTR dwInstance,
          DWORD_PTR dwParam1, DWORD_PTR dwParam2)
{
    SDL_AudioDevice *this = (SDL_AudioDevice *) dwInstance;

    /* Only service "buffer done playing" messages */
    if (uMsg != WOM_DONE)
        return;

    /* Signal that we are done playing a buffer */
    ReleaseSemaphore(this->hidden->audio_sem, 1, NULL);
}

static int
SetMMerror(char *function, MMRESULT code)
{
    int len;
    char errbuf[MAXERRORLENGTH];
    wchar_t werrbuf[MAXERRORLENGTH];

    SDL_snprintf(errbuf, SDL_arraysize(errbuf), "%s: ", function);
    len = SDL_static_cast(int, SDL_strlen(errbuf));

    waveOutGetErrorText(code, werrbuf, MAXERRORLENGTH - len);
    WideCharToMultiByte(CP_ACP, 0, werrbuf, -1, errbuf + len,
                        MAXERRORLENGTH - len, NULL, NULL);

    return SDL_SetError("%s", errbuf);
}

static void
WINMM_WaitDevice(_THIS)
{
    /* Wait for an audio chunk to finish */
    WaitForSingleObject(this->hidden->audio_sem, INFINITE);
}

static Uint8 *
WINMM_GetDeviceBuf(_THIS)
{
    return (Uint8 *) (this->hidden->
                      wavebuf[this->hidden->next_buffer].lpData);
}

static void
WINMM_PlayDevice(_THIS)
{
    /* Queue it up */
    waveOutWrite(this->hidden->hout,
                 &this->hidden->wavebuf[this->hidden->next_buffer],
                 sizeof(this->hidden->wavebuf[0]));
    this->hidden->next_buffer = (this->hidden->next_buffer + 1) % NUM_BUFFERS;
}

static int
WINMM_CaptureFromDevice(_THIS, void *buffer, int buflen)
{
    const int nextbuf = this->hidden->next_buffer;
    MMRESULT result;

    SDL_assert(buflen == this->spec.size);

    /* Wait for an audio chunk to finish */
    WaitForSingleObject(this->hidden->audio_sem, INFINITE);

    /* Copy it to caller's buffer... */
    SDL_memcpy(buffer, this->hidden->wavebuf[nextbuf].lpData, this->spec.size);

    /* requeue the buffer that just finished. */
    result = waveInAddBuffer(this->hidden->hin,
                             &this->hidden->wavebuf[nextbuf],
                             sizeof (this->hidden->wavebuf[nextbuf]));
    if (result != MMSYSERR_NOERROR) {
        return -1;  /* uhoh! Disable the device. */
    }

    /* queue the next buffer in sequence, next time. */
    this->hidden->next_buffer = (nextbuf + 1) % NUM_BUFFERS;
    return this->spec.size;
}

static void
WINMM_FlushCapture(_THIS)
{
    /* Wait for an audio chunk to finish */
    if (WaitForSingleObject(this->hidden->audio_sem, 0) == WAIT_OBJECT_0) {
        const int nextbuf = this->hidden->next_buffer;
        /* requeue the buffer that just finished without reading from it. */
        waveInAddBuffer(this->hidden->hin,
                        &this->hidden->wavebuf[nextbuf],
                        sizeof (this->hidden->wavebuf[nextbuf]));
        this->hidden->next_buffer = (nextbuf + 1) % NUM_BUFFERS;
    }
}

static void
WINMM_CloseDevice(_THIS)
{
    int i;

    if (this->hidden->hout) {
        waveOutReset(this->hidden->hout);

        /* Clean up mixing buffers */
        for (i = 0; i < NUM_BUFFERS; ++i) {
            if (this->hidden->wavebuf[i].dwUser != 0xFFFF) {
                waveOutUnprepareHeader(this->hidden->hout,
                                       &this->hidden->wavebuf[i],
                                       sizeof (this->hidden->wavebuf[i]));
            }
        }

        waveOutClose(this->hidden->hout);
    }

    if (this->hidden->hin) {
        waveInReset(this->hidden->hin);

        /* Clean up mixing buffers */
        for (i = 0; i < NUM_BUFFERS; ++i) {
            if (this->hidden->wavebuf[i].dwUser != 0xFFFF) {
                waveInUnprepareHeader(this->hidden->hin,
                                       &this->hidden->wavebuf[i],
                                       sizeof (this->hidden->wavebuf[i]));
            }
        }
        waveInClose(this->hidden->hin);
    }

    if (this->hidden->audio_sem) {
        CloseHandle(this->hidden->audio_sem);
    }

    SDL_free(this->hidden->mixbuf);
    SDL_free(this->hidden);
}

static SDL_bool
PrepWaveFormat(_THIS, UINT devId, WAVEFORMATEX *pfmt, const int iscapture)
{
    SDL_zerop(pfmt);

    if (SDL_AUDIO_ISFLOAT(this->spec.format)) {
        pfmt->wFormatTag = WAVE_FORMAT_IEEE_FLOAT;
    } else {
        pfmt->wFormatTag = WAVE_FORMAT_PCM;
    }
    pfmt->wBitsPerSample = SDL_AUDIO_BITSIZE(this->spec.format);

    pfmt->nChannels = this->spec.channels;
    pfmt->nSamplesPerSec = this->spec.freq;
    pfmt->nBlockAlign = pfmt->nChannels * (pfmt->wBitsPerSample / 8);
    pfmt->nAvgBytesPerSec = pfmt->nSamplesPerSec * pfmt->nBlockAlign;

    if (iscapture) {
        return (waveInOpen(0, devId, pfmt, 0, 0, WAVE_FORMAT_QUERY) == 0);
    } else {
        return (waveOutOpen(0, devId, pfmt, 0, 0, WAVE_FORMAT_QUERY) == 0);
    }
}

static int
WINMM_OpenDevice(_THIS, void *handle, const char *devname, int iscapture)
{
    SDL_AudioFormat test_format = SDL_FirstAudioFormat(this->spec.format);
    int valid_datatype = 0;
    MMRESULT result;
    WAVEFORMATEX waveformat;
    UINT devId = WAVE_MAPPER;  /* WAVE_MAPPER == choose system's default */
    UINT i;

    if (handle != NULL) {  /* specific device requested? */
        /* -1 because we increment the original value to avoid NULL. */
        const size_t val = ((size_t) handle) - 1;
        devId = (UINT) val;
    }

    /* 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);

    /* Initialize the wavebuf structures for closing */
    for (i = 0; i < NUM_BUFFERS; ++i)
        this->hidden->wavebuf[i].dwUser = 0xFFFF;

    if (this->spec.channels > 2)
        this->spec.channels = 2;        /* !!! FIXME: is this right? */

    while ((!valid_datatype) && (test_format)) {
        switch (test_format) {
        case AUDIO_U8:
        case AUDIO_S16:
        case AUDIO_S32:
        case AUDIO_F32:
            this->spec.format = test_format;
            if (PrepWaveFormat(this, devId, &waveformat, iscapture)) {
                valid_datatype = 1;
            } else {
                test_format = SDL_NextAudioFormat();
            }
            break;

        default:
            test_format = SDL_NextAudioFormat();
            break;
        }
    }

    if (!valid_datatype) {
        return SDL_SetError("Unsupported audio format");
    }

    /* Update the fragment size as size in bytes */
    SDL_CalculateAudioSpec(&this->spec);

    /* Open the audio device */
    if (iscapture) {
        result = waveInOpen(&this->hidden->hin, devId, &waveformat,
                             (DWORD_PTR) CaptureSound, (DWORD_PTR) this,
                             CALLBACK_FUNCTION);
        if (result != MMSYSERR_NOERROR) {
            return SetMMerror("waveInOpen()", result);
        }
    } else {
        result = waveOutOpen(&this->hidden->hout, devId, &waveformat,
                             (DWORD_PTR) FillSound, (DWORD_PTR) this,
                             CALLBACK_FUNCTION);
        if (result != MMSYSERR_NOERROR) {
            return SetMMerror("waveOutOpen()", result);
        }
    }

#ifdef SOUND_DEBUG
    /* Check the sound device we retrieved */
    {
        if (iscapture) {
            WAVEINCAPS caps;
            result = waveInGetDevCaps((UINT) this->hidden->hout,
                                      &caps, sizeof (caps));
            if (result != MMSYSERR_NOERROR) {
                return SetMMerror("waveInGetDevCaps()", result);
            }
            printf("Audio device: %s\n", caps.szPname);
        } else {
            WAVEOUTCAPS caps;
            result = waveOutGetDevCaps((UINT) this->hidden->hout,
                                       &caps, sizeof(caps));
            if (result != MMSYSERR_NOERROR) {
                return SetMMerror("waveOutGetDevCaps()", result);
            }
            printf("Audio device: %s\n", caps.szPname);
        }
    }
#endif

    /* Create the audio buffer semaphore */
    this->hidden->audio_sem =
		CreateSemaphore(NULL, iscapture ? 0 : NUM_BUFFERS - 1, NUM_BUFFERS, NULL);
    if (this->hidden->audio_sem == NULL) {
        return SDL_SetError("Couldn't create semaphore");
    }

    /* Create the sound buffers */
    this->hidden->mixbuf =
        (Uint8 *) SDL_malloc(NUM_BUFFERS * this->spec.size);
    if (this->hidden->mixbuf == NULL) {
        return SDL_OutOfMemory();
    }

    SDL_zero(this->hidden->wavebuf);
    for (i = 0; i < NUM_BUFFERS; ++i) {
        this->hidden->wavebuf[i].dwBufferLength = this->spec.size;
        this->hidden->wavebuf[i].dwFlags = WHDR_DONE;
        this->hidden->wavebuf[i].lpData =
            (LPSTR) & this->hidden->mixbuf[i * this->spec.size];

        if (iscapture) {
            result = waveInPrepareHeader(this->hidden->hin,
                                          &this->hidden->wavebuf[i],
                                          sizeof(this->hidden->wavebuf[i]));
            if (result != MMSYSERR_NOERROR) {
                return SetMMerror("waveInPrepareHeader()", result);
            }

            result = waveInAddBuffer(this->hidden->hin,
                                     &this->hidden->wavebuf[i],
                                     sizeof(this->hidden->wavebuf[i]));
            if (result != MMSYSERR_NOERROR) {
                return SetMMerror("waveInAddBuffer()", result);
            }
        } else {
            result = waveOutPrepareHeader(this->hidden->hout,
                                          &this->hidden->wavebuf[i],
                                          sizeof(this->hidden->wavebuf[i]));
            if (result != MMSYSERR_NOERROR) {
                return SetMMerror("waveOutPrepareHeader()", result);
            }
        }
    }

    if (iscapture) {
        result = waveInStart(this->hidden->hin);
        if (result != MMSYSERR_NOERROR) {
            return SetMMerror("waveInStart()", result);
        }
    }

    return 0;                   /* Ready to go! */
}


static int
WINMM_Init(SDL_AudioDriverImpl * impl)
{
    /* Set the function pointers */
    impl->DetectDevices = WINMM_DetectDevices;
    impl->OpenDevice = WINMM_OpenDevice;
    impl->PlayDevice = WINMM_PlayDevice;
    impl->WaitDevice = WINMM_WaitDevice;
    impl->GetDeviceBuf = WINMM_GetDeviceBuf;
    impl->CaptureFromDevice = WINMM_CaptureFromDevice;
    impl->FlushCapture = WINMM_FlushCapture;
    impl->CloseDevice = WINMM_CloseDevice;

    impl->HasCaptureSupport = SDL_TRUE;

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

AudioBootStrap WINMM_bootstrap = {
    "winmm", "Windows Waveform Audio", WINMM_Init, 0
};

#endif /* SDL_AUDIO_DRIVER_WINMM */

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