/*	
	HotKey plugin for Sonique 2.0
    Copyright (C) 2004  Jerome Kuptz

    This program is free software; you can redistribute it and/or modify
    it under the terms of the GNU General Public License as published by
    the Free Software Foundation; either version 2 of the License, or
    (at your option) any later version.

    This program is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    GNU General Public License for more details.

    You should have received a copy of the GNU General Public License
    along with this program; if not, write to the Free Software
    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
*/
#include "MediaFilterHotKey.h"
#include "sq2_hotkey.h"

//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////// HotKeyFilter /////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

MError MediaErrors[ERR_MEDIA__NUM];

HotKeyFilter::HotKeyFilter(SQ2_Audio_HotKey_dll *parMainDLL) 
{
	MGENERIC_CONSTRUCTOR();
	m_bEnabled     = true;
	m_pPrefs       = NULL;
	m_State        = MediaState_Stopped;
	m_pChain       = NULL;
	m_pMyDest      = NULL;
	m_pAudioFormat = NULL;

	m_MainDLL = parMainDLL;

	m_ErrorSys->RegisterErrors(GetMediaErrors(MediaErrors), lenof(MediaErrors), ERR_MEDIA__MODULE);

}

HotKeyFilter::~HotKeyFilter()
{
	ChangeState(MediaState_Stopped);

	if (m_pAudioFormat)
		m_pAudioFormat = NULL;

}

MRESULT HotKeyFilter::QueryModule(const MID& mid, void** ppv, bool bAddReference , const MGeneric* pPrev  )
{
	if( mid == MID_MEDIAFILTER || mid == MID_MEDIAFILTER_HOT) {
		*ppv = (MMediaFilter*)this;
	} else if( mid == MID_MEDIAINFORMATION ) {
		*ppv = (MMediaInformation*)this;
	} else if( mid == MID_MEDIASETTINGS ) {
		*ppv = (MMediaSettings*)this;
	} else {
		*ppv = NULL;
		return GetBasicError(ERR_BASIC_UNKNOWNOBJECT);
	}
	if( *ppv )
	{
		if( bAddReference )
			((MGeneric*)*ppv)->AddRef();
		return M_OK;
	}

	return GetBasicError(ERR_BASIC_OUTOFMEMORY);
}

///////////////////////////////////////////////////////// MMediaFilter /////////////////////////////////////////////////////////
MRESULT HotKeyFilter::GetNumInputs( ) const
{
	return 1;
}
MRESULT HotKeyFilter::GetInput( MMediaInput** ppToHere, int32 nWhich ) const
{
	if( nWhich == 0 )
	{
		*ppToHere = (HotKeyFilter*)this;
		return M_OK;
	} else {
		return GetBasicError(ERR_BASIC_NOTFOUND);
	}
}
MRESULT HotKeyFilter::GetInput( MMediaInput** ppToHere, const wchar_t* wsWhich ) const
{
	if( !GetInputName().CompareTo(wsWhich) )
	{
		*ppToHere = (HotKeyFilter*)this;
		return M_OK;
	} else {
		return GetBasicError(ERR_BASIC_NOTFOUND);
	}
}
MRESULT HotKeyFilter::GetNumOutputs( ) const
{
	return 1;
}
MRESULT HotKeyFilter::GetOutput( MMediaOutput** ppToHere, int32 nWhich ) const
{
	if( nWhich == 0 )
	{
		*ppToHere = (HotKeyFilter*)this;
		return M_OK;
	} else {
		return GetBasicError(ERR_BASIC_NOTFOUND);
	}

}
MRESULT HotKeyFilter::AddedToChain( MMediaChain* pChain )
{
	m_pChain = pChain;
	return M_OK;
}

MRESULT HotKeyFilter::GetOutput( MMediaOutput** ppToHere, const wchar_t* wsWhich ) const
{
	if( !GetOutputName().CompareTo(wsWhich) )
	{
		*ppToHere = (HotKeyFilter*)this;
		return M_OK;
	} else {
		return GetBasicError(ERR_BASIC_NOTFOUND);
	}
}


///////////////////////////////////////////////////////// MMediaInput /////////////////////////////////////////////////////////
WString HotKeyFilter::GetInputName( ) const
{
	return L"input";
}

MRESULT HotKeyFilter::CanHandle( MMediaOutput* pOutput, uint32 *plConfidence, uint32 *plMerit )
{
	// Hopefully this will keep us out the audio chain.
	if( m_State != MediaState_Stopped && m_State != MediaState_FormatDetection )
		return GetError(MediaErrors, ERR_MEDIA_NOTVALIDINTHISSTATE);

	AutoCriticalSection acs(&m_HotCs);

	Array< RefPtr<MMediaFormat> > CompatibleFormats;

	MRESULT res = GetCompatibleFormats(pOutput, CompatibleFormats);
	if( FAILED(res) )
		return res;
	
	*plConfidence = 0;
	*plMerit = 0;

	return M_OK;
}

MRESULT HotKeyFilter::AttachInput( MMediaOutput* pOutput )
{
	m_pMySource = pOutput;
	return M_OK;
}

MRESULT HotKeyFilter::GetFilter( MMediaFilter** ppToHere )
{
	*ppToHere = this;
	return M_OK;
}

MRESULT HotKeyFilter::ChangeState( MediaState State )
{
	m_State = State;
    return M_OK;
}

MRESULT HotKeyFilter::SeekFilter( double tTime, bool bAccurately, bool bFlush )
{
    return M_OK;
}
MRESULT HotKeyFilter::FlushFilter( )
{
    return M_OK;
}

MRESULT HotKeyFilter::GatherFilterInformation( InformationHint Hint )
{
    return M_OK;
}


///////////////////////////////////////////////////////// MMediaOutput /////////////////////////////////////////////////////////
MRESULT HotKeyFilter::GetCompatibleFormats( MMediaOutput* pOutput, Array<RefPtr<MMediaFormat> >& CompatibleFormats )
{
	Array<RefPtr<MMediaFormat> > Formats;
	MMediaFormat* pFormat;
	MRESULT res;
	uint32 i;

	res = pOutput->GetFormats(Formats);
	if( FAILED(res) )
		return res;

	for( i = 0; i < Formats.GetCount(); i++ )
	{
		pFormat = Formats[i];
		if( pFormat->MediaType == MID_MEDIATYPE_PCM)
		{
			continue;
		}
		Formats.RemoveAt(i);
		i--;
	}
	CompatibleFormats = Formats;

	return M_OK;
}

WString HotKeyFilter::GetOutputName( ) const
{
	return L"output";
}
MRESULT HotKeyFilter::GetPacket( RefPtr<MPacket>& pToHere )
{
	MRESULT res = m_pMySource->GetPacket(pToHere);

	if( FAILED(res) )
		return res;

	return M_OK;
}

MRESULT HotKeyFilter::GetFormats( Array<RefPtr<MMediaFormat> >& Formats )
{
	MRESULT res = GetCompatibleFormats(m_pMySource, Formats);
	if( FAILED(res) )
		return res;
	return M_OK;
}

MRESULT HotKeyFilter::SelectFormat( MMediaFormat* pFormat )
{
	return m_pMySource->SelectFormat(pFormat);
}

MRESULT HotKeyFilter::AttachOutput( MMediaInput* pInput )
{
	m_pMyDest = pInput;
	return M_OK;
}


///////////////////////////////////////////////////////// MMediaInformation /////////////////////////////////////////////////////////

MRESULT HotKeyFilter::GetStringInfo( const wchar_t* wsWhich, WString& wsToHere )
{
	if( !WString::Compare(wsWhich, L"modulename") )
	{
		wsToHere = "HotKey";
		return M_OK;
	} else if( !WString::Compare(wsWhich, L"moduledescription") ) {
		wsToHere = "Sonique 2 Global Hot Key Watcher";
		return M_OK;
	} else if( !WString::Compare(wsWhich, L"modulecopyright") ) {
		wsToHere = "2004 Jerome Kuptz";
		return M_OK;
	}
	return GetBasicError(ERR_BASIC_NOTFOUND);
}
MRESULT HotKeyFilter::GetIntegerInfo( const wchar_t* wsWhich, int32& lToHere )
{
	if( !WString::Compare(wsWhich, L"enabled") )
    {
		lToHere = m_bEnabled;
		return M_OK;
	} else if( !WString::Compare(wsWhich, L"playmod") ) {
		lToHere = m_lPlayMod;
		return M_OK;
	} else if( !WString::Compare(wsWhich, L"stopmod") ) {
		lToHere = m_lStopMod;
		return M_OK;
	} else if( !WString::Compare(wsWhich, L"nextmod") ) {
		lToHere = m_lNextMod;
		return M_OK;
	} else if( !WString::Compare(wsWhich, L"prevmod") ) {
		lToHere = m_lPrevMod;
		return M_OK;
	} else if( !WString::Compare(wsWhich, L"mutemod") ) {
		lToHere = m_lMuteMod;
		return M_OK;
	} else if( !WString::Compare(wsWhich, L"volumod") ) {
		lToHere = m_lVolUMod;
		return M_OK;
	} else if( !WString::Compare(wsWhich, L"voldmod") ) {
		lToHere = m_lVolDMod;
		return M_OK;
	} else if( !WString::Compare(wsWhich, L"playkey") ) {
		lToHere = m_lPlayKey;
		return M_OK;
	} else if( !WString::Compare(wsWhich, L"stopkey") ) {
		lToHere = m_lStopKey;
		return M_OK;
	} else if( !WString::Compare(wsWhich, L"nextkey") ) {
		lToHere = m_lNextKey;
		return M_OK;
	} else if( !WString::Compare(wsWhich, L"prevkey") ) {
		lToHere = m_lPrevKey;
		return M_OK;
	} else if( !WString::Compare(wsWhich, L"mutekey") ) {
		lToHere = m_lMuteKey;
		return M_OK;
	} else if( !WString::Compare(wsWhich, L"voldkey") ) {
		lToHere = m_lVolDKey;
		return M_OK;
	} else if( !WString::Compare(wsWhich, L"volukey") ) {
		lToHere = m_lVolUKey;
		return M_OK;
	}
	
	return GetBasicError(ERR_BASIC_NOTFOUND);
}
MRESULT HotKeyFilter::GetRealInfo( const wchar_t* wsWhich, double& lfToHere )
{
	if( !WString::Compare(wsWhich, L"moduleversion") ) {
		lfToHere = 1.0;
		return M_OK;
	}
	return GetBasicError(ERR_BASIC_NOTFOUND);
}
MRESULT HotKeyFilter::EnumerateInformation( Array<MediaInfo>& Info )
{

	MediaInfo* i;

	i = &Info.AddTail();
	i->Name = L"modulename";
	i->Desc = L"the name of this audio component";
	i->Type = (MediaInfoType)(MediaInfo_String|MediaInfo_ModuleSpecific);
	i = &Info.AddTail();
	i->Name = L"moduledescription";
	i->Desc = L"the human readable name of this audio component";
	i->Type = (MediaInfoType)(MediaInfo_String|MediaInfo_ModuleSpecific);
	i = &Info.AddTail();
	i->Name = L"modulecopyright";
	i->Desc = L"the owner of the copyright of this audio component";
	i->Type = (MediaInfoType)(MediaInfo_String|MediaInfo_ModuleSpecific);
	i = &Info.AddTail();
	i->Name = L"moduleversion";
	i->Desc = L"the revision number of this audio component";
	i->Type = (MediaInfoType)(MediaInfo_Real|MediaInfo_ModuleSpecific);
	i = &Info.AddTail();
	return M_OK;
}


///////////////////////////////////////////////////////// MMediaSettings /////////////////////////////////////////////////////////

MRESULT HotKeyFilter::SetStringInfo( const wchar_t* wsWhich, const WString& Info )
{
	return GetBasicError(ERR_BASIC_NOTFOUND);
}
MRESULT HotKeyFilter::SetIntegerInfo( const wchar_t* wsWhich, int32 Info )
{
	AutoCriticalSection acs(&m_HotCs);
	if( !WString::Compare(wsWhich, L"enabled") ) {
		m_bEnabled = (Info != 0);
		return M_OK;
	} else if( !WString::Compare(wsWhich, L"playmod") ) {
		m_lPlayMod = Info;
		return M_OK;
	} else if( !WString::Compare(wsWhich, L"stopmod") ) {
		m_lStopMod = Info;
		return M_OK;
	} else if( !WString::Compare(wsWhich, L"nextmod") ) {
		m_lNextMod = Info;
		return M_OK;
	} else if( !WString::Compare(wsWhich, L"prevmod") ) {
		m_lPrevMod = Info;
		return M_OK;
	} else if( !WString::Compare(wsWhich, L"mutemod") ) {
		m_lMuteMod = Info;
		return M_OK;
	} else if( !WString::Compare(wsWhich, L"volumod") ) {
		m_lVolUMod = Info;
		return M_OK;
	} else if( !WString::Compare(wsWhich, L"voldmod") ) {
		m_lVolDMod = Info;
		return M_OK;
	} else if( !WString::Compare(wsWhich, L"playkey") ) {
		m_lPlayKey = Info;
		return M_OK;
	} else if( !WString::Compare(wsWhich, L"stopkey") ) {
		m_lStopKey = Info;
		return M_OK;
	} else if( !WString::Compare(wsWhich, L"nextkey") ) {
		m_lNextKey = Info;
		return M_OK;
	} else if( !WString::Compare(wsWhich, L"prevkey") ) {
		m_lPrevKey = Info;
		return M_OK;
	} else if( !WString::Compare(wsWhich, L"mutekey") ) {
		m_lMuteKey = Info;		
		return M_OK;
	} else if( !WString::Compare(wsWhich, L"voldkey") ) {
		m_lVolDKey = Info;		
		return M_OK;
	} else if( !WString::Compare(wsWhich, L"volukey") ) {
		m_lVolUKey = Info;		
		return M_OK;
	} else if( !WString::Compare(wsWhich, L"reloadSettings") ) {
		m_MainDLL->m_bReloadSettings = true;
		return M_OK;
	}
	
	return GetBasicError(ERR_BASIC_NOTFOUND);
}
MRESULT HotKeyFilter::SetRealInfo( const wchar_t* wsWhich, double Info )
{
	return GetBasicError(ERR_BASIC_NOTFOUND);
}
MRESULT HotKeyFilter::LoadSettings( MPreferences* pPrefs )
{
	int32 lVal;
	WString wsVal;

	if( SUCCEEDED(pPrefs->GetInt( L"enabled", lVal)) )
		SetIntegerInfo(L"enabled", lVal);
	else 
	{
		if( SUCCEEDED(GetIntegerInfo(L"enabled", lVal)) )
			pPrefs->SetInt( L"enabled", lVal);
	}
	

	/** Baalrukh - 03-03-2004 : Changed mod keys from WString to int **/
	// MODS
	if( SUCCEEDED(pPrefs->GetInt( L"playmod", lVal)) )
		SetIntegerInfo(L"playmod", lVal);
	else 
	{
		if( SUCCEEDED(GetIntegerInfo(L"playmod", lVal)) )
			pPrefs->SetInt( L"playmod", lVal);
	}

	if( SUCCEEDED(pPrefs->GetInt( L"stopmod", lVal)) )
		SetIntegerInfo(L"stopmod", lVal);
	else 
	{
		if( SUCCEEDED(GetIntegerInfo(L"stopmod", lVal)) )
			pPrefs->SetInt( L"stopmod", lVal);
	}

	if( SUCCEEDED(pPrefs->GetInt( L"nextmod", lVal)) )
		SetIntegerInfo(L"nextmod", lVal);
	else 
	{
		if( SUCCEEDED(GetIntegerInfo(L"nextmod", lVal)) )
			pPrefs->SetInt( L"nextmod", lVal);
	}

	if( SUCCEEDED(pPrefs->GetInt( L"prevmod", lVal)) )
		SetIntegerInfo(L"prevmod", lVal);
	else 
	{
		if( SUCCEEDED(GetIntegerInfo(L"prevmod", lVal)) )
			pPrefs->SetInt( L"prevmod", lVal);
	}

	if( SUCCEEDED(pPrefs->GetInt( L"mutemod", lVal)) )
		SetIntegerInfo(L"mutemod", lVal);
	else 
	{
		if( SUCCEEDED(GetIntegerInfo(L"mutemod", lVal)) )
			pPrefs->SetInt( L"mutemod", lVal);
	}

	if( SUCCEEDED(pPrefs->GetInt( L"voldmod", lVal)) )
		SetIntegerInfo(L"voldmod", lVal);
	else 
	{
		if( SUCCEEDED(GetIntegerInfo(L"voldmod", lVal)) )
			pPrefs->SetInt( L"voldmod", lVal);
	}

	if( SUCCEEDED(pPrefs->GetInt( L"volumod", lVal)) )
		SetIntegerInfo(L"volumod", lVal);
	else 
	{
		if( SUCCEEDED(GetIntegerInfo(L"volumod", lVal)) )
			pPrefs->SetInt( L"volumod", lVal);
	}



	// Keys
	if( SUCCEEDED(pPrefs->GetInt( L"playkey", lVal)) )
		SetIntegerInfo(L"playkey", lVal);
	else 
	{
		if( SUCCEEDED(GetIntegerInfo(L"playkey", lVal)) )
			pPrefs->SetInt( L"playkey", lVal);
	}

	if( SUCCEEDED(pPrefs->GetInt( L"stopkey", lVal)) )
		SetIntegerInfo(L"stopkey", lVal);
	else 
	{
		if( SUCCEEDED(GetIntegerInfo(L"stopkey", lVal)) )
			pPrefs->SetInt( L"stopkey", lVal);
	}

	if( SUCCEEDED(pPrefs->GetInt( L"nextkey", lVal)) )
		SetIntegerInfo(L"nextkey", lVal);
	else 
	{
		if( SUCCEEDED(GetIntegerInfo(L"nextkey", lVal)) )
			pPrefs->SetInt( L"nextkey", lVal);
	}

	if( SUCCEEDED(pPrefs->GetInt( L"prevkey", lVal)) )
		SetIntegerInfo(L"prevkey", lVal);
	else 
	{
		if( SUCCEEDED(GetIntegerInfo(L"prevkey", lVal)) )
			pPrefs->SetInt( L"prevkey", lVal);
	}

	if( SUCCEEDED(pPrefs->GetInt( L"mutekey", lVal)) )
		SetIntegerInfo(L"mutekey", lVal);
	else 
	{
		if( SUCCEEDED(GetIntegerInfo(L"mutekey", lVal)) )
			pPrefs->SetInt( L"mutekey", lVal);
	}

	if( SUCCEEDED(pPrefs->GetInt( L"voldkey", lVal)) )
		SetIntegerInfo(L"voldkey", lVal);
	else 
	{
		if( SUCCEEDED(GetIntegerInfo(L"voldkey", lVal)) )
			pPrefs->SetInt( L"voldkey", lVal);
	}

	if( SUCCEEDED(pPrefs->GetInt( L"volukey", lVal)) )
		SetIntegerInfo(L"volukey", lVal);
	else 
	{
		if( SUCCEEDED(GetIntegerInfo(L"volukey", lVal)) )
			pPrefs->SetInt( L"volukey", lVal);
	}

	m_pPrefs = pPrefs;
	return M_OK;
}
MRESULT HotKeyFilter::SaveSettings( MPreferences* pPrefs )
{
	AutoCriticalSection acs(&m_HotCs);
	int32 lVal;
	WString wsVal;

	if( SUCCEEDED(GetIntegerInfo(L"enabled", lVal)) )
		pPrefs->SetInt( L"enabled", lVal);

	if( SUCCEEDED(GetIntegerInfo(L"playmod", lVal)) )
		pPrefs->SetInt( L"playmod", lVal);

	if( SUCCEEDED(GetIntegerInfo(L"stopmod", lVal)) )
		pPrefs->SetInt( L"stopmod", lVal);

	if( SUCCEEDED(GetIntegerInfo(L"nextmod", lVal)) )
		pPrefs->SetInt( L"nextmod", lVal);

	if( SUCCEEDED(GetIntegerInfo(L"prevmod", lVal)) )
		pPrefs->SetInt( L"prevmod", lVal);

	if( SUCCEEDED(GetIntegerInfo(L"mutemod", lVal)) )
		pPrefs->SetInt( L"mutemod", lVal);

	if( SUCCEEDED(GetIntegerInfo(L"voldmod", lVal)) )
		pPrefs->SetInt( L"voldmod", lVal);

	if( SUCCEEDED(GetIntegerInfo(L"volumod", lVal)) )
		pPrefs->SetInt( L"volumod", lVal);


	if( SUCCEEDED(GetIntegerInfo(L"playkey", lVal)) )
		pPrefs->SetInt( L"playkey", lVal);

	if( SUCCEEDED(GetIntegerInfo(L"stopkey", lVal)) )
		pPrefs->SetInt( L"stopkey", lVal);

	if( SUCCEEDED(GetIntegerInfo(L"nextkey", lVal)) )
		pPrefs->SetInt( L"nextkey", lVal);

	if( SUCCEEDED(GetIntegerInfo(L"prevkey", lVal)) )
		pPrefs->SetInt( L"prevkey", lVal);

	if( SUCCEEDED(GetIntegerInfo(L"mutekey", lVal)) )
		pPrefs->SetInt( L"mutekey", lVal);

	if( SUCCEEDED(GetIntegerInfo(L"volukey", lVal)) )
		pPrefs->SetInt( L"volukey", lVal);

	if( SUCCEEDED(GetIntegerInfo(L"voldkey", lVal)) )
		pPrefs->SetInt( L"voldkey", lVal);

	
	
	return M_OK;
}

MRESULT	HotKeyFilter::FilterMessage( const wchar_t* wsMessageName, void* pData )
{
	if( !WString::Compare(wsMessageName, L"HotKeyPluginReloadSettings") )
	{
		LoadSettings(m_pPrefs);
	}

	return M_OK;
}
