
#include "ErG_DirectShow.h"
#pragma warning(disable:4995)
#pragma warning(disable:4996)


//#include <tchar.h>
//#include <strsafe.h>

// Convert from Decibel Level to Logarithmic Scale.

#define DECTOLOG(vol)      (-15 * (100 - vol))

// Convert to scale of (-10,000, 10,000).

#define CONVPAN(pan)        (pan * 100)



ErG_DirectShow ErG_DirectShow::m_pInstance;

ErG_DirectShow::ErG_DirectShow()
{
	pBasicAudio =0;

	pMediaSeeking=0;

	pGraphBuilder=0;

	pMediaControl=0;

	pVideoWindow=0; 

	pMediaEvent=0;  

}


ErG_DirectShow* ErG_DirectShow::GetInstance()
{
	return &m_pInstance;
}

void ErG_DirectShow::Init(HWND hWnd)
{
	// Create the filter graph manager and render the file.

	this->hWnd = hWnd;
	CoCreateInstance(CLSID_FilterGraph, NULL, CLSCTX_INPROC,

	IID_IGraphBuilder, (void **)&pGraphBuilder);

	//pGraphBuilder->QueryInterface(IID_IVideoWindow,(void**)&pVideoWindow);

	//pVideoWindow->put_Owner((OAHWND)hWnd);

	//pVideoWindow->put_WindowStyle( WS_CHILD | WS_CLIPSIBLINGS);

 

	// Make the Movie Take up the Entire Window.
	//POSSIBLY COMMENTING OUT FOR FUTURE USE

     //RECT rect;

     //GetClientRect(hWnd, &rect);

     //pVideoWindow->SetWindowPosition(0, 0, rect.right, rect.bottom);

 

	// Set the owner window to receive event notifications.

	pGraphBuilder->QueryInterface(IID_IMediaEventEx, (void **)&pMediaEvent);

	pMediaEvent->SetNotifyWindow((OAHWND)hWnd, WM_GRAPHNOTIFY, 0);
}

int ErG_DirectShow::Load(char* szFilename)
{
	if (!szFilename)	return -1;

	// Make sure the texture isn't already loaded.
	for (unsigned int i = 0; i < m_vFiles.size(); i++)
	{
		// compare strings without caring about upper or lowercase.
		if (stricmp((char*)szFilename, (char*)m_vFiles[i].szName) == 0)	// 0 means they are equal.
		{
			m_vFiles[i].ref++; // add a reference to this texture.
			return i;	// return the index.
		}
	}

	// Look for an open spot.
	int id = -1;
	for (unsigned int i = 0; i < m_vFiles.size(); i++)
	{
		if (m_vFiles[i].ref == 0)
		{
			id = i;
			break;
		}
	}

	// if we didn't find an open spot, load it in a new one
	if (id == -1)
	{
		// A temp texture object.
		tFile loaded;

		// Copy the filename of the loaded texture.
		strcpy((char*)loaded.szName, (char*)szFilename);
		loaded.ref = 1;

		m_vFiles.push_back(loaded);

		// Return the id of the texture.
		return (int)m_vFiles.size() - 1;
	}
	else
	{
		strcpy((char*)m_vFiles[id].szName, (char*)szFilename);


		// AddRef
		m_vFiles[id].ref = 1;

		// Return the id of the texture.
		return id;
	}

}
	
void ErG_DirectShow::Play(int nID, DWORD dwFlags)
{
	//);_T(m_vFiles[nID].szName)
	pGraphBuilder->RenderFile(L"08-hans_zimmer-parlay.mp3", NULL);

	// Specify the owner window.
	pGraphBuilder->QueryInterface(IID_IBasicAudio, (void **)&pBasicAudio);

	pGraphBuilder->QueryInterface(IID_IMediaSeeking, (void **)&pMediaSeeking); 

	// Set the volume.

	pBasicAudio->put_Volume(DECTOLOG(200));

	// Set the pan.

	pBasicAudio->put_Balance(CONVPAN(0));

	pGraphBuilder->QueryInterface(IID_IMediaEventEx, (void **)&pMediaEvent);

	pMediaEvent->SetNotifyWindow((OAHWND)hWnd, WM_GRAPHNOTIFY, 0);

 

	// Run the graph.

	pGraphBuilder->QueryInterface(IID_IMediaControl, (void **)&pMediaControl);

	pMediaControl->Run();

}

void ErG_DirectShow::Restart()
{

	if (pMediaSeeking)

       {
         LONGLONG llPos = 0;

         pMediaSeeking->SetPositions(&llPos, AM_SEEKING_AbsolutePositioning, &llPos, AM_SEEKING_NoPositioning);

       }
}

void ErG_DirectShow::SetVolume(int volume)
{
	pBasicAudio->put_Volume(DECTOLOG(volume));
}

void ErG_DirectShow::SetPan(int pan)
{
	pBasicAudio->put_Balance(CONVPAN(pan));
}

void ErG_DirectShow::HandleEvent()
{
	long evCode, param1, param2;         // Parameters to be set on certain Messages.

     HRESULT result;                      // For Error Tracking.

 

     // Call GetEvent until it returns a failure code, indicating that the queue is empty.

     //while (result = pMediaEvent->GetEvent(&evCode, &param1, &param2, 0), SUCCEEDED(result))

     //{

     //      result = pMediaEvent->FreeEventParams(evCode, param1, param2);

     //      // If the Sample stops playing or is stopped by the User then call CleanUp.

     //      if ((evCode == EC_COMPLETE) || (evCode == EC_USERABORT))

     //      {

     //           CleanUp();

     //           break;

     //      }

     //}

	 // Call GetEvent until it returns a failure code, indicating that the queue is empty.

       while (result =pMediaEvent->GetEvent(&evCode, &param1, &param2, 0),

				SUCCEEDED(result))

       {

              result = pMediaEvent->FreeEventParams(evCode, param1, param2);

              // If the Sample stops playing or is stopped by the User then call CleanUp.

              if ((evCode == EC_COMPLETE) || (evCode == EC_USERABORT))

              {

                    Restart();

                    break;

              }

       }
}

void ErG_DirectShow::Shutdown()
{
	if (pMediaSeeking)

	{

		   pMediaSeeking->Release();

		   pMediaSeeking = NULL;

	}

 

	if (pBasicAudio)

	{

		   pBasicAudio->Release();

		   pBasicAudio = NULL;

	}

     if (pMediaControl)                        // Does pMediaControl exist.

     {

           pMediaControl->Stop();               // Stop the graph.

           pMediaControl->Release();            // Release the Movie Controls

           pMediaControl = NULL;                 // Set to NULL for safety.

     }

 

     if (pVideoWindow)                          // Does pVideoWindow exist.

     {

           pVideoWindow->put_Visible(OAFALSE);  // Show no longer.

           pVideoWindow->put_Owner(NULL);       // Have no Owner.

           pVideoWindow->Release();             // Release the Video Window.

           pVideoWindow = NULL;                 // Set to NULL for safety.

     }



 

	if (pMediaEvent)                           // Does pMediaEvent exist.

	{

     pMediaEvent->Release();              // Release the event manager.

     pMediaEvent = NULL;                  // Set to NULL for safety.

     }

 

     if (pGraphBuilder)                         // Does pGraphBuilder exist.

     {

		pGraphBuilder->Release();            // Release the filter graph manager.

		pGraphBuilder = NULL;                // Set to NULL for safety.

	}

}