/*
 * Emunation Plugin for MD-API 
 *
 * This code 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 code 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.
 * Or, point your browser to http://www.gnu.org/copyleft/gpl.html
 */
 
#include <process.h>
#include "../main.h"
#include "DVBCoreWrapper.h"
#include "MDExtern82.h"

HMODULE DVBCOREDLL;
static DWORD CommandFilter = 0;
DWORD DVBCORE_PMT_FILTER=0;
DWORD DVBCORE_ECM_FILTER=0;
DWORD DVBCORE_EMM_FILTER=0;
//DVBCore Engine Functions
BOOL (__stdcall *_DVBAddFilter)(DWORD PID, LPCB_STREAMHOOK StreamHook, DWORD FilterType , BYTE* pbFilterData , BYTE* pbFilterMask , BYTE bLength);
BOOL (__stdcall *_DVBDelFilter) (DWORD hFilter);
void (__stdcall *_DVBSendSAACmd) (WORD CmdBuf[32], int CmdLen);
BOOL (__stdcall *_DVBParams)(TP_INFO* TP_Info, DWORD Options);


bool TPINFO_TO_TProgramm82()
{
    struct TP_INFO TPinfo;
    TProgramm82* TPMD = &m_DLLInstance.m_curprg;
	_DVBParams(&TPinfo,GET_ALLINFO | GET_TRYFROMCACHE /*GET_ONLYFROMCACHE*/);	//vahid fix 01/24/2007
    if (TPinfo.HdrVer!=DVB_HDRVER_TP_INFO)
    {   
        m_DLLInstance.Log("DVBCore:ERROR: Current DVBCore API is different\n");
        m_DLLInstance.Log("DVBCore:Current TP_INFO ver: 0x%X Emunation TP_INFO ver: 0x%X\n",TPinfo.HdrVer,DVB_HDRVER_TP_INFO);
        return false;
    }
    if ((TPinfo.wDataValid & (PAT_VALID|PMT_VALID))!=0)
    {

        if (TPinfo.wChCurrent == CURRENT_NONE) return false;

        struct CH_INFO* ch = &TPinfo.Channel[TPinfo.wChCurrent];
        memcpy(TPMD->Name,&ch->Ch_Name[2],29);
        if (ch->Ch_Name[0]>sizeof(TPMD->Name)-1)
            TPMD->Name[sizeof(TPMD->Name)+1] = '\0';
        else
            TPMD->Name[ch->Ch_Name[0]+1] = '\0';
		TPMD->CA_Anzahl = ch->ECM.wCount % MAX_CA_SYSTEMS;
		TPMD->Video_pid=ch->wVideo;
// Ritz Causes a general fault and crashes with following line of code
//		TPMD->Audio_pid = ch->Audio.wPID[ch->Audio.wCurrent];
		TPMD->PMT_pid=ch->wPMT;
		TPMD->SID_pid=ch->wSID;
		TPMD->PCR_pid=ch->wPCR;
		TPMD->freq = TPinfo.dwFreq;
        if(ch->ECM.wCurrent!=0xFFFF)
            TPMD->ECM_PID = ch->ECM.wPID[ch->ECM.wCurrent];
        else
            TPMD->ECM_PID = 0x1FFF;
        
        for (int i=0;i< ch->ECM.wCount%MAX_CA_SYSTEMS;i++)
        {
            TPMD->CA_System[i].CA_Typ=ch->ECM.wCA_Type[i];
            TPMD->CA_System[i].ECM=ch->ECM.wPID[i];            
        }
        
        for (int i=0;i< TPinfo.EMM.wCount%MAX_CA_SYSTEMS;i++)
        {
            TPMD->CA_System[i].Provider_Id=0;
            TPMD->CA_System[i].EMM=TPinfo.EMM.wPID[i];            
        }
        
    }//    if (TPInfo.wDataValid &(PAT_VALID|PMT_VALID)!=0)
    else
    {
        m_DLLInstance.Log("DVBCore:TPInfo not valid\n");        
        return false;
    }
    return true;
  
}
//DVBCore Functions
extern "C" BOOL __stdcall DVBPLGInit(DWORD CardType, HWND Handle, void *ExtraInfo = NULL)
{
    if(!m_DLLInstance.IsInitialized)
    {
        DVBCOREDLL = LoadLibrary("DVBCore.dll");
        
        if(DVBCOREDLL!=INVALID_HANDLE_VALUE)
        {   
            (FARPROC&)_DVBAddFilter= GetProcAddress(DVBCOREDLL,"DVBAddFilter");
            (FARPROC&)_DVBDelFilter= GetProcAddress(DVBCOREDLL,"DVBDelFilter");
            (FARPROC&)_DVBSendSAACmd= GetProcAddress(DVBCOREDLL,"DVBSendSAACmd");
            (FARPROC&)_DVBParams = GetProcAddress(DVBCOREDLL,"DVBParams");

        }
        if(_DVBAddFilter && _DVBDelFilter && _DVBSendSAACmd &&_DVBParams)
        {
            m_DLLInstance.OnDVBCoreInit(Handle);  
            CommandFilter = _DVBAddFilter(HOOK_COMMANDS,(LPCB_STREAMHOOK)CMD_FILTER,FT_STREAMING_FILTER,NULL,NULL,0);  
        }
    }
    return TRUE;
}
extern "C" BOOL __stdcall DVBPLGCall(DWORD Code =0, void *ExtraInfo = NULL)
{
    m_DLLInstance.On_Menu_Select(IDM_SHOW);
    return TRUE;
}

extern "C" BOOL __stdcall DVBPLGGetInfo(PLG_INFO* PLG_Info)
{
    PLG_Info->HdrVer=100;
    PLG_Info->dwShortCut=0;
    PLG_Info->dwTTL= 0;
    strcpy(PLG_Info->Name,"EmuNation");
    return TRUE;
}
extern "C" BOOL __stdcall DVBPLGClose(DWORD Reason =0)
{
    m_DLLInstance.ThreadState=false;
    if(CommandFilter!=0)_DVBDelFilter(CommandFilter);
    if(DVBCORE_PMT_FILTER!=0)_DVBDelFilter(DVBCORE_PMT_FILTER);
    if(DVBCORE_ECM_FILTER!=0)_DVBDelFilter(DVBCORE_ECM_FILTER);
    if(DVBCORE_EMM_FILTER!=0)_DVBDelFilter(DVBCORE_EMM_FILTER);
    FreeLibrary(DVBCOREDLL);
    CloseHandle(DVBCOREDLL);
    Sleep(10);
    return TRUE;
}
BOOL __stdcall CMD_FILTER(BYTE* buf, ULONG Len, DWORD hFilter)
{
    CH_INFO* chinfo =  (CH_INFO*) buf;
    switch(Len)
    {
        case FT_CMD_CHANNEL_WILLBE_CHANGED:
        break;
        case FT_CMD_CHANNEL_CHANGED:
            TPINFO_TO_TProgramm82();
            m_DLLInstance.On_Channel_Change_TH((const struct TProgramm82)m_DLLInstance.m_curprg);
        break;

    };
    return TRUE;
}

BOOL __stdcall STREAM_FILTER(BYTE* Buf, ULONG Len, DWORD hFilter)
{
    //Call On_Filter_Data_Arrival(int MyFilter, int DataLen, unsigned char *_Data);
    if(hFilter==DVBCORE_PMT_FILTER)
        m_DLLInstance.On_Filter_Data_Arrival(DATA_FILTER_ID,Len,Buf);
    else
    if(hFilter==DVBCORE_ECM_FILTER)
        m_DLLInstance.On_Filter_Data_Arrival(ECM_FILTER_ID,Len,Buf);
    else
    if(hFilter==DVBCORE_EMM_FILTER)
        m_DLLInstance.On_Filter_Data_Arrival(EMM_FILTER_ID,Len,Buf);

    return TRUE;
}
