////////////////////////////////////////////////////////////////////////////////
// Sound.cpp
//
//  Sound-handling code

#include "stdhdr.h"

#include "Sound.h"
#include "Debug.h"

// Force the inclusion of the libraries we need
#pragma comment(lib, "kernel32.lib")
#pragma comment(lib, "user32.lib")
#pragma comment(lib, "gdi32.lib")
#pragma comment(lib, "ole32.lib")
#pragma comment(lib, "dxguid.lib")
#pragma comment(lib, "ddraw.lib")
#pragma comment(lib, "dinput8.lib")

////////////////////////////////////////////////////////////////////////////////
// Sound and music support

IDirectMusicPerformance8    *g_pMusicPerformance;
IDirectMusicLoader8         *g_pMusicLoader;

BOOL InitDirectMusic()
{
    HRESULT h;

    // Initialise COM, so that we can use CoCreateInstance.
    ::CoInitialize(NULL);
    
    // Create an IDirectMusicPerformance8 object, through which 
    //  we will access all audio functions.
    h = ::CoCreateInstance(CLSID_DirectMusicPerformance, NULL, 
                     CLSCTX_INPROC, IID_IDirectMusicPerformance8,
                     (void **)&g_pMusicPerformance);
    if (FAILED(h))
    {
        DISPLAYERRORCODE(h, "DirectMusic could not be initialised. DirectX 8 may not be installed.");
        return FALSE;
    }
    
    // Set up the audio: a normal stereo and reverb system.
    h = g_pMusicPerformance->InitAudio(NULL, NULL, NULL, 
        DMUS_APATH_SHARED_STEREOPLUSREVERB, 
        64, DMUS_AUDIOF_ALL, NULL);
    if (FAILED(h))
    {
        DISPLAYERRORCODE(h, "DirectX Audio could not be initialised. Check for low memory or low system resources.");
        return FALSE;
    }

    // Create an IDirectMusicLoader8 object. which will load
    //  audio files for us.
    h = ::CoCreateInstance(CLSID_DirectMusicLoader, NULL, 
                     CLSCTX_INPROC, IID_IDirectMusicLoader8,
                     (void **)&g_pMusicLoader);
    if (FAILED(h))
    {
        DISPLAYERRORCODE(h, "DirectX Audio could not be initialised. Check for low memory or low system resources.");
        return FALSE;
    }

    return TRUE;
}

IDirectMusicSegment8 *LoadSound(LPCWSTR wszFilename)
{
    IDirectMusicSegment8 *pSegment;
    
    HRESULT h;

    // Load the background music MIDI file
    // Note that we cast away the const here; this is okay, since LoadObjectFromFile is not
    //  going to alter it.
    h = g_pMusicLoader->LoadObjectFromFile(CLSID_DirectMusicSegment, 
        IID_IDirectMusicSegment8, (LPWSTR)wszFilename, (void **) &pSegment);
    if (FAILED(h))
    {
        DISPLAYERRORCODE(h, "Sound file could not be loaded.");
        return NULL;
    }
    return pSegment;
}

void DownloadSound(IDirectMusicSegment8 *pSegment)
{
    // Download this to the sound card (if necessary)
    if ((g_pMusicPerformance != NULL) && (pSegment != NULL))
        pSegment->Download(g_pMusicPerformance);
}

void PlaySound(IDirectMusicSegment8 *pSegment, DWORD dwFlags)
{
    // Play the segment immediately
    if ((g_pMusicPerformance != NULL) && (pSegment != NULL))
        g_pMusicPerformance->PlaySegment(pSegment, dwFlags, 0, NULL);
}

void StopSound(IDirectMusicSegment8 *pSegment)
{
    if ((g_pMusicPerformance != NULL) && (pSegment != NULL))
        g_pMusicPerformance->StopEx(pSegment, 0, 0);
}

void UnloadSound(IDirectMusicSegment8 *pSegment)
{
    if ((g_pMusicPerformance != NULL) && (pSegment != NULL))
        pSegment->Unload(g_pMusicPerformance);
}

void StopAllSound()
{
    if (g_pMusicPerformance != NULL)
        g_pMusicPerformance->Stop(NULL, NULL, 0, 0);
}

void ExitDirectMusic()
{
    if (g_pMusicPerformance != NULL)
    {
        g_pMusicPerformance->CloseDown();
        g_pMusicPerformance->Release();
        g_pMusicPerformance = NULL;
    }
    if (g_pMusicLoader != NULL)
    {
        g_pMusicLoader->Release();
        g_pMusicLoader = NULL;
    }
}