///////////////////////////////////////////////////////////////////////////////////////////
// Sound.cpp
//
//  Implementation of the Sound class, which serves to contain a sound effect or music 
// file, played back using DirectMusic.

#include "StdAfx.h"
#include "Sound.h"
#include "DirectXException.h"

using namespace System::Runtime::InteropServices;

namespace Sunlight
{
    namespace DirectX
    {
        namespace SoundMusic
        {
            Sound::Sound() :
                m_pSegment(NULL),
                DirectMusicObject(NULL),
                m_pFilename(NULL),
                m_bIsLoaded(false)
            {
            }

            Sound::~Sound()
            {
                Unload();
            }

            // Load this sound object into memory.
            void Sound::Load()
            {
                IDirectMusicSegment8 __nogc *pSegment;

                LPWSTR wszFilename = (LPWSTR)(void *)Marshal::StringToCoTaskMemUni(m_pFilename);
                HRESULT h = DirectMusicObject->GetLoader()->LoadObjectFromFile(CLSID_DirectMusicSegment,
                    IID_IDirectMusicSegment8, wszFilename, (void **)&pSegment);
                CoTaskMemFree(wszFilename);

                if (FAILED(h))
                {
                    if ((h == HRESULT_FROM_WIN32(ERROR_FILE_NOT_FOUND)) || (h == DMUS_E_LOADER_FAILEDOPEN) || (h == DMUS_E_UNSUPPORTED_STREAM))
                        throw new IO::FileNotFoundException(String::Format(S"Unable to load music file {0}", m_pFilename), m_pFilename);
                    throw new Sunlight::DirectX::DirectXException(S"IDirectMusicLoader8::LoadObjectFromFile", h);
                }

                m_pSegment = pSegment;

                String *LowercaseFilename = m_pFilename->ToLower();
                if (LowercaseFilename->EndsWith(S".mid") || LowercaseFilename->EndsWith(S".rmi"))
                {
                    // Standard MIDI file
                    m_pSegment->SetParam(GUID_StandardMIDIFile, 
                        0xFFFFFFFF, DMUS_SEG_ALLTRACKS, 0, NULL);       
                }

                m_pSegment->Download(DirectMusicObject->GetPerformance());
            }

            // Unload this object from memory.
            void Sound::Unload()
            {
                if (m_pSegment != NULL)
                {
                    m_pSegment->Unload(DirectMusicObject->GetPerformance());
                    m_pSegment->Release();
                    m_pSegment = NULL;
                }
                m_bIsLoaded = false;
            }

            // Prepare this object for playback later.
            void Sound::Prepare()
            {
                if (m_pFilename == NULL)
                    throw new ArgumentNullException(S"Filename");

                if (m_bIsLoaded)
                    return;

                Unload();
                Load();

                m_bIsLoaded = true;
            }

            // Play this object from the beginning.
            void Sound::Play()
            {
                Prepare();
    
                if (m_pSegment != NULL)
                    DirectMusicObject->GetPerformance()->PlaySegment(m_pSegment, DMUS_SEGF_SECONDARY, 0, NULL);
            }

            // Stop the playback of this object.
            void Sound::Stop()
            {
                if (m_pSegment != NULL)
                    DirectMusicObject->GetPerformance()->StopEx(m_pSegment, 0, 0);
            }

            String *Sound::get_Filename()
            {
                return m_pFilename;
            }
            void Sound::set_Filename(String *pFilename)
            {
                m_pFilename = pFilename;
                m_bIsLoaded = false;
            }
        }
    }
}