#include "StdAfx.h"
#include "EventHandler.h"

CEcmDat* m_pEcm;		// とりあえず。。

CEventHandler::CEventHandler(void)
{
	m_pTsPacketParser = NULL;
	m_pTsDescrambler = NULL;
	m_pTsServiceSelect = NULL;
	m_pFileWriter = NULL;
	m_pNetworkSend = NULL;
	m_pHttpSend = NULL;
	m_pEcm = NULL;
	m_pKeepRate = NULL;
	m_pProgManager = NULL;
	m_pTsDemuxer = NULL;
	m_pVideoFile = NULL;
	m_pAudioFile = NULL;
	m_pFFmpgVideoBand = NULL;
	m_pFFmpgVideo = NULL;
	m_pFFmpgAudioBand = NULL;
	m_pFFmpgAudio = NULL;
	m_pWaveWriter = NULL;
	m_pAacConverter = NULL;

	m_emergency = FALSE;

	m_server_port = 1234;

	m_AudHoseiFromVid = FALSE;

	m_Useffmpg = FALSE;

	m_SoundMethod = 0;
	m_AudioEsNum = 0;

	m_wNowEventID = 0;
	m_wRecordingNowEventID = 0;
}

CEventHandler::~CEventHandler(void)
{
	Exit();
}

extern bool OpenFFmpeg(LPSTR vlc);

static BYTE WaveHead[] =		// from CWaveWriter@BonTsDemux
{
	'R', 'I', 'F', 'F',				// +0	RIFF
	0x00U, 0x00U, 0x00U, 0x00U,		// +4	これ以降のファイルサイズ(ファイルサイズ - 8)
	'W', 'A', 'V', 'E',				// +8	WAVE
	'f', 'm', 't', ' ',				// +12	fmt
	0x10U, 0x00U, 0x00U, 0x00U,		// +16	fmt チャンクのバイト数
	0x01U, 0x00U,					// +18	フォーマットID
	0x02U, 0x00U,					// +20	ステレオ
	0x80U, 0xBBU, 0x00U, 0x00U,		// +24	48KHz
	0x00U, 0xEEU, 0x02U, 0x00U,		// +28	192000Byte/s
	0x04U, 0x00U,					// +30	ブロックサイズ
	0x10U, 0x00U,					// +32	サンプルあたりのビット数
	'd', 'a', 't', 'a',				// +36	data
	0x00U, 0xffU, 0xffU, 0xffU		// +40	波形データのバイト数
};


BOOL CEventHandler::Init(
	DWORD opt,				// オプションビット
	LPCTSTR tsfname,		// 保存するtsのファイル名
	LPCTSTR tsfname_org,	// tsのデフォルトファイル名(EPGの番組一致に使用)
	DWORD PacketSize,		// 全体的なパケットサイズ
	DWORD buf_margin,		// TSバッファマージン
	DWORD buf_size,			// TSバッファMAX
	DWORD ffmpg_bufsize,	// ffmpeg用バッファサイズ
	DWORD service,			// サービスセレクト
	DWORD outer_reader,		// BCASリーダーメソッド (0=内蔵のみ 1=内蔵 or 外付け 2=BCasProxy)
	LPCTSTR CasProxyAdr,	// CasProxyサーバーアドレス
	DWORD CasProxyPort		// CasProxyサーバーポート
)
{

	CMediaDecoder* connect;

	m_opt = opt;
	m_RecordingMode = FALSE;
	
	strcpy(m_tsfname,tsfname);
	_splitpath(tsfname_org,NULL,NULL,m_tstitle,NULL);
	m_achannel = 2 * 2;


	ZeroMemory(&m_RecordingEpg,sizeof(TSEPG_PROGRAM));

	m_pEcm = new CEcmDat();
	m_pEcm->SetDiag(OPT_BDIAG & opt ? TRUE : FALSE);
	m_Useffmpg = FALSE;

	m_ServiceNum = (WORD)service;
	m_NowServiceNum = m_ServiceNum;	
	
	m_pKeepRate = new CKeepRate(PacketSize							// パケット長
							,buf_margin								// 何バイトためてからデコード開始するか
							,buf_size 								// バッファのMAXサイズ
							,( (opt&(OPT_UDP|OPT_FFMPEG)) ? 100*1024*1024 : 0)		// 最大瞬間風速を、100Mbpsに抑える
							,FALSE									// copy data
							,"TS"									// name
							,this
							);		

	m_pTsPacketParser = new CTsPacketParser(this);
	m_pKeepRate->SetOutputDecoder(m_pTsPacketParser);			// m_pKeepRate->m_pTsPacketParser
	connect = m_pTsPacketParser;

	if(opt&OPT_SEL) {
		m_pTsServiceSelect = new CTsServiceSelect(this);
		m_pTsServiceSelect->SetServiceId(service);
		m_pTsServiceSelect->StartTrans(TRUE);
		
		connect->SetOutputDecoder(m_pTsServiceSelect);			// ->m_pTsServiceSelect
		connect = m_pTsServiceSelect;
	}

	if(opt&OPT_B25) {
		m_pTsDescrambler = new CTsDescrambler(this);
		m_pTsDescrambler->SetBcasStatus(outer_reader,CasProxyAdr,CasProxyPort);
		if(m_pTsDescrambler->OpenBcasCard()){
			connect->SetOutputDecoder(m_pTsDescrambler);		// ->m_pTsDescrambler
			connect = m_pTsDescrambler;
		}
	}

	if(opt&OPT_UDP) {			// UDP出力選択
		m_pNetworkSend = new CNetworkSend(32767);
		m_pNetworkSend->Open("localhost",m_server_port);
		connect->SetOutputDecoder(m_pNetworkSend);				// ->m_pNetworkSend
		connect = m_pNetworkSend;

	} else if(opt&OPT_HTTP) {			// HTTP出力選択
		m_pHttpSend = new CHttpSend(this,m_server_port,8*1024);
		connect->SetOutputDecoder(m_pHttpSend);					// ->m_pHttpSend
//		m_pHttpSend->RawTcp(TRUE);
		connect = m_pHttpSend;

	} else if (opt&(OPT_DEMUX|OPT_FFMPEG)) {	// demux | ffmpeg出力選択(TEST)
		if(opt&OPT_FFMPEG) 	m_Useffmpg = TRUE;

		m_pProgManager = new CProgManager(this);
		connect->SetOutputDecoder(m_pProgManager);				// ->m_pProgManager

		m_pTsDemuxer = new CTsDemuxer(this);
		m_pTsDemuxer->EnableLipSync(TRUE);
		m_pProgManager->SetOutputDecoder(m_pTsDemuxer);			// ->m_pTsDemuxer


		if (opt&OPT_DEMUX){						// demux出力
			m_RecordingMode = TRUE;

			char file_name[_MAX_PATH];
			
			sprintf_s(file_name,"%s.m2v",tsfname);
			m_pVideoFile = new CFileWriter(this);
			if(m_pVideoFile->OpenFile(file_name)){
				m_pTsDemuxer->SetOutputDecoder(m_pVideoFile,	// 		->m_pVideoFile
								CTsDemuxer::OUTPUT_VIDEO);
			} else {
				log_out("ファイル:%sが開けません。",file_name);
			}
/*
				if(!m_WaveWriter.OpenFile(lpszAudioFile))throw 2UL;
				m_TsDemuxer.SetOutputDecoder(&m_AacConverter, CTsDemuxer::OUTPUT_AUDIO);
				m_AacConverter.SetOutputDecoder(&m_WaveWriter);
*/

/*
			// aac出力
			sprintf_s(file_name,"%s.aac",tsfname);
			m_pAudioFile = new CFileWriter(this);
			if(m_pAudioFile->OpenFile(file_name)){
				m_pTsDemuxer->SetOutputDecoder(m_pAudioFile,	// 		->m_pAudioFile
								CTsDemuxer::OUTPUT_AUDIO);
			} else {
				log_out("ファイル:%sが開けません。",file_name);
			}
*/
			// wav出力
			sprintf_s(file_name,"%s.wav",tsfname);
			m_pAacConverter = new CAacConverter(this);
			m_pTsDemuxer->SetOutputDecoder(m_pAacConverter,	// 		->m_pAudioFile
							CTsDemuxer::OUTPUT_AUDIO);
			
			m_pWaveWriter = new CWaveWriter(this);
			if(m_pWaveWriter->OpenFile(file_name, 16, m_SoundMethod==3 ? 6 : 2 , 48000)){
				m_pAacConverter->SetOutputDecoder(m_pWaveWriter);
			} else {
				log_out("ファイル:%sが開けません。",file_name);
			}

		} else {								// FFmpeg出力

			m_RecordingMode = TRUE;

			m_pFFmpgVideo = new CHttpSend(this,m_server_port,64*1024);
			m_pFFmpgVideoBand = new CKeepRate(64*1024,			//packet
												0,				//margin
												ffmpg_bufsize,	//max
												0,	//max_bps
												TRUE,			//copydata
												"M2V",			//name
												this);	//VIDEO用クッションバッファ作る
			m_pTsDemuxer->SetOutputDecoder(m_pFFmpgVideoBand,		//		->m_pFFmpgVideo
							CTsDemuxer::OUTPUT_VIDEO);
			m_pFFmpgVideoBand->SetOutputDecoder(m_pFFmpgVideo);
			m_pFFmpgVideoBand->m_debugmsg = FALSE;

/*
			// aac出力
			m_pFFmpgAudioBand = new CKeepRate(1024,	//packet
												0,				//margin
												2*1024*1024,	//max
												256*1024,		//max_bps
												TRUE,			//copydata
												"AAC",			//name
												this);	//Audio用クッションバッファ作る
			m_pFFmpgAudioBand->m_debugmsg = FALSE;
			m_pTsDemuxer->SetOutputDecoder(m_pFFmpgAudioBand,	// 		->m_pFFmpgAudio
							CTsDemuxer::OUTPUT_AUDIO);
			m_pFFmpgAudio = new CHttpSend(this,1234,8*1024);
			m_pFFmpgAudioBand->SetOutputDecoder(m_pFFmpgAudio);
*/


			// wav出力

			m_pAacConverter = new CAacConverter(this);

			m_pAacConverter->SetOutputChannel(2);
			m_pAacConverter->SetStereoMethod(0);		// Stereo To Mono

			if(m_SoundMethod == 3){
				m_pAacConverter->SetOutputChannel(6);
				WaveHead[22] = 0x06;
				m_achannel = 6*2;
			} else if (m_SoundMethod == 1 || m_SoundMethod == 2){
				m_pAacConverter->SetStereoMethod(m_SoundMethod);
			}

			m_pTsDemuxer->SetOutputDecoder(m_pAacConverter,	// 		->m_pFFmpgAudio
							CTsDemuxer::OUTPUT_AUDIO);

			m_pFFmpgAudioBand = new CKeepRate(1024*64,		//packet
												0,		//margin
												ffmpg_bufsize,		//max
												0,		//max_bps
												TRUE,	//copydata
												"WAV",	//name
												this);	//Audio用クッションバッファ作る
			m_pFFmpgAudioBand->m_debugmsg = FALSE;
			m_pAacConverter->SetOutputDecoder(m_pFFmpgAudioBand);


			m_pFFmpgAudio = new CHttpSend(this,m_server_port,64*1024);

			CMediaData *m = new CMediaData(WaveHead, (DWORD)sizeof(WaveHead));
			m_pFFmpgAudio->InputMedia(m);
			delete m;

//			m_pFFmpgAudio->SetHeader(WaveHead,sizeof(WaveHead));

			m_pFFmpgAudioBand->SetOutputDecoder(m_pFFmpgAudio);

#if 0
/*
			FILE* f;
			size_t len;
			BYTE inbuf33[512*1024];
			Sleep(300);

			OpenFFmpeg("C:\\Program Files\\適当プログラム\\cap_sts\\ffmpeg.exe -i http://localhost:1234/ -acodec libmp3lame  -ar 48000 -ab 192k -y out.mpg");


			f = fopen("C:\\Program Files\\適当プログラム\\cap_sts\\test.m2v","rb");
*/
			FILE* f;
			size_t len;
			BYTE inbuf33[8*1024];

			Sleep(1000);

			OpenFFmpeg("C:\\Program Files\\適当プログラム\\cap_sts\\ffmpeg.exe -i \"http://localhost:1234/test.wav\" -acodec libmp3lame  -ar 48000 -ab 192k -y out.mpg");

			f = fopen("C:\\Program Files\\適当プログラム\\cap_sts\\test.wav","rb");
			while(len=fread(inbuf33,sizeof(BYTE),sizeof(inbuf33),f)){

				CMediaData *m = new CMediaData(inbuf33, (DWORD)len);
				m_pFFmpgAudio->InputMedia(m);
				delete m;
//				m = new CMediaData(inbuf33, (DWORD)len);
//				m_pFFmpgAudioBand->InputMedia(m);
			}
			fclose(f);
			m_pFFmpgAudio->Close();
			delete m_pFFmpgAudio;
#endif
		}
	} else {				//ファイル出力選択
		m_RecordingMode = TRUE;
		m_pFileWriter = new CFileWriter(this);
		if(m_pFileWriter->OpenFile(tsfname)){
			connect->SetOutputDecoder(m_pFileWriter);			// ->m_pFileWriter
			connect = m_pFileWriter;
		} else {
			log_out("ファイル:%sが開けません。",tsfname);
		}
	}
	if(m_RecordingMode && m_pTsServiceSelect){
		if(opt&OPT_SYNCEIT){
			m_pTsServiceSelect->StartTrans(FALSE);
		} else {
			m_pTsServiceSelect->StartTrans(TRUE);
		}
	}
	return TRUE;
}

BOOL CEventHandler::CheckServerConnection(void)
{
	BOOL ret = TRUE;
	
	if ( m_pFFmpgVideo && m_pFFmpgVideo->IsOpen() == FALSE){
		ret = FALSE;
	}
	if ( m_pHttpSend && m_pHttpSend->IsOpen() == FALSE){
		ret = FALSE;
	}

	return ret;
}

void CEventHandler::Exit(void)
{
	if(m_pEcm)	m_pEcm->exit();

	if(m_pKeepRate)				m_pKeepRate->StopTrans();
	if(m_pFFmpgAudioBand)		m_pFFmpgAudioBand->StopTrans();
	if(m_pFFmpgVideoBand)		m_pFFmpgVideoBand->StopTrans();
	if(m_pFFmpgVideo)			m_pFFmpgVideo->Close();
	if(m_pFFmpgAudio)			m_pFFmpgAudio->Close();


	if(m_pKeepRate)				delete m_pKeepRate;
	if(m_pFFmpgVideoBand)		delete m_pFFmpgVideoBand;
	if(m_pFFmpgAudioBand)		delete m_pFFmpgAudioBand;


	if(m_pTsPacketParser)		delete m_pTsPacketParser;
	if(m_pTsServiceSelect)		delete m_pTsServiceSelect;
	if(m_pTsDescrambler)		delete m_pTsDescrambler;
	if(m_pNetworkSend)			delete m_pNetworkSend;
	if(m_pHttpSend)				delete m_pHttpSend;
	if(m_pFileWriter)			delete m_pFileWriter;
	if(m_pEcm)					delete m_pEcm;
	if(m_pProgManager)			delete m_pProgManager;
	if(m_pTsDemuxer)			delete m_pTsDemuxer;
	if(m_pVideoFile)			delete m_pVideoFile;
	if(m_pAudioFile)			delete m_pAudioFile;
	if(m_pFFmpgVideo)			delete m_pFFmpgVideo;
	if(m_pFFmpgAudio)			delete m_pFFmpgAudio;
	if(m_pWaveWriter)			delete m_pWaveWriter;
	if(m_pAacConverter)			delete m_pAacConverter;

	m_pTsPacketParser = NULL;
	m_pTsDescrambler = NULL;
	m_pTsServiceSelect = NULL;
	m_pFileWriter = NULL;
	m_pNetworkSend = NULL;
	m_pHttpSend = NULL;
	m_pEcm = NULL;
	m_pKeepRate = NULL;
	m_pProgManager = NULL;
	m_pTsDemuxer = NULL;
	m_pVideoFile = NULL;
	m_pAudioFile = NULL;
	m_pFFmpgVideoBand = NULL;
	m_pFFmpgVideo = NULL;
	m_pFFmpgAudioBand = NULL;
	m_pFFmpgAudio = NULL;
	m_pWaveWriter = NULL;
	m_pAacConverter = NULL;
}

BOOL CEventHandler::OnTsData(BYTE* data,DWORD len)
{
	if(m_emergency) return FALSE;
	return m_pKeepRate->InputMedia(new CMediaData(data, len));
}

BOOL CEventHandler::OnBcasData(BYTE* data,DWORD len)
{
	if(m_emergency) return FALSE;
	m_pEcm->set(data,len);
	return TRUE;
}

void CEventHandler::Reset(void)
{
}

const DWORD CEventHandler::OnDecoderEvent(CMediaDecoder *pDecoder, const DWORD dwEventID, PVOID pParam)
{
	// デコーダからのイベントを受け取る(暫定)
	if(pDecoder == m_pProgManager){
		
		// プログラムマネージャからのイベント
		switch(dwEventID){
			case CProgManager::EID_SERVICE_LIST_UPDATED : {
				// サービスの構成が変化した
				WORD wVideoPID = 0xFFFF;
				WORD wAudioPID = 0xFFFF;
				m_pProgManager->GetServiceEsPID(&wVideoPID, &wAudioPID);
				if(m_AudioEsNum){
					m_pTsServiceSelect->GetAudioEs(m_AudioEsNum,NULL,&wAudioPID);
				}
				m_pTsDemuxer->SetVideoPID(wVideoPID);
				m_pTsDemuxer->SetAudioPID(wAudioPID);
				return 0UL;
			}
			
			case CProgManager::EID_SERVICE_INFO_UPDATED : {
				// サービス情報が更新された
				TCHAR szServiceName[1024] = {TEXT("不明")};
				m_pProgManager->GetServiceName(szServiceName);
				return 0UL;
			}
		}
	} else if(pDecoder == m_pTsDemuxer){
	
		switch(dwEventID){
		
			case CTsDemuxer::EID_SERVICE_FIRST_AAC:					// しょっぱな補完。基点をVIDEOのPTSにあわせるため、差分を埋める
				{
					LONGLONG diff;
					LONG hokan;
					diff = m_pTsDemuxer->GetM2VAACDif();
					diff = diff * 48 * m_achannel / 90;
					hokan = (LONG)diff;
					hokan -= (hokan % m_achannel);
					if(hokan > 1920000 || hokan < -1920000){
						log_out("初回音声補正 : 初回で10秒以上ずれています。\n");
						break;
					}
					if(hokan > 0){							// Videoが遅れている場合
						TRACE1("初回補正 : %d\n",hokan);

						BYTE* dummy = new BYTE[hokan];
						ZeroMemory(dummy,hokan);

						CMediaData *m = new CMediaData(dummy, hokan);
						delete [] dummy;

						if(m_Useffmpg) m_pFFmpgAudioBand->InputMedia(m);
						else m_pWaveWriter->InputMedia(m);

						m_pAacConverter->m_total_frame += hokan / m_achannel;
						delete m;
					} else if (hokan < 0){					// Videoが進んでいる場合
						m_pAacConverter->SetCutFrame((DWORD)(m_pTsDemuxer->GetM2VAACDif() *-1* 48 / 90));	// Video先頭にあわせるために、削除するAudioフレーム数を設定
						m_pTsDemuxer->m_FirstAudioPts = m_pTsDemuxer->m_FirstVideoPts;			// 先頭がVIDEOと同期するので、Audioの先頭PTSをVIDEOと同じにする
					}
				}

				break;
			case CTsDemuxer::EID_SERVICE_M2V_COMMIT:
				if(m_pAacConverter->GetTotalSample() < 100000) break;

//				log_out("M2V	%I64d	%I64d	%d\n",m_pTsDemuxer->m_NowVideoPts,m_pTsDemuxer->m_NowAudioPts,m_pAacConverter->GetTotalSample());
				{
#if 0
					LONGLONG pts_ms = m_pTsDemuxer->GetTotalVideoPts();
					LONGLONG frame_ms = (LONGLONG)m_pTsDemuxer->GetVideoTotalFrame() * 3003;		// * 1000 / 29.97(fps)  → ms
					LONGLONG diff;

					diff = (pts_ms - frame_ms);

//					TRACE2("frame_ms:%I64d   , pts_ms:%I64d\n",frame_ms,pts_ms);

					if(diff >= 70 || diff <= -70){
						m_pTsDemuxer->m_FirstAudioPts += (LONGLONG)diff;		// 何らかの原因で、Videoが欠落している。
						m_pTsDemuxer->m_FirstVideoPts += (LONGLONG)diff;		// 補正する。
						TRACE2("frame_ms:%I64d   , pts_ms:%I64d\n",frame_ms,pts_ms);
					}
#endif
				}
				break;
			case CTsDemuxer::EID_SERVICE_AAC_COMMIT:
				{

				if(m_pAacConverter->GetTotalSample() < 100000) break;

//				log_out("AAC	%I64d	%I64d	%d\n",m_pTsDemuxer->m_NowVideoPts,m_pTsDemuxer->m_NowAudioPts,m_pAacConverter->GetTotalSample());

				LONGLONG diff;
				diff = (m_pTsDemuxer->GetTotalAudioPts() / 90 - m_pAacConverter->GetTotalSample() / 48);	// PTS 90kHz Audio 48kHz らしいので、単位をmsにあわせて差分をとる。

				if(m_pTsDemuxer->m_NowAudioPts == -1) break;

				if (diff > 5000 || diff < -5000){		// ±2sec以上は、やりすぎなので恐らくエラーが発生している
					m_pAacConverter->ResetTotalFrame();
					m_pTsDemuxer->ResetTotalAudioPts();
					m_pTsDemuxer->EnableLipSync(TRUE);
				} else {
					if (diff == 0){
						m_pAacConverter->SetHoseiPol(0);
						m_AudHoseiFromVid = 0;
					} else if(diff >= 70){					// 2 frame 以上ずれていたら
						TRACE1("diff : %dms\n",(LONG)diff);
						if(diff >= 200){												// 200ms以上ずれていたら、NULLで一気に補完
							BYTE* dummy = new BYTE[(int)diff*48* m_achannel];			// 音声フレームが足りていない場合は、NULLで一気に補完するように変更
							ZeroMemory(dummy,(int)diff*48* m_achannel);

							CMediaData *m = new CMediaData(dummy, (int)diff*48* m_achannel);
							delete [] dummy;

							if(m_Useffmpg) m_pFFmpgAudioBand->InputMedia(m);
							else m_pWaveWriter->InputMedia(m);

							delete m;

							m_pAacConverter->m_total_frame += diff*48;
						} else {
							m_pAacConverter->SetHoseiPol((LONG)4);				
							m_AudHoseiFromVid = 1;
						}
					} else if (diff <= -70){			// -2 frame以上ずれていたら
						TRACE1("diff : %dms\n",(LONG)diff);
						m_pAacConverter->SetHoseiPol((LONG)-4);				
						m_AudHoseiFromVid = -1;
					} else if (m_AudHoseiFromVid < 0){	// 
						TRACE1("diff : %dms\n",(LONG)diff);
						m_pAacConverter->SetHoseiPol((LONG)-4);				
						m_AudHoseiFromVid = -1;
					} else if (m_AudHoseiFromVid > 0){
						TRACE1("diff : %dms\n",(LONG)diff);
						m_pAacConverter->SetHoseiPol((LONG)4);				
						m_AudHoseiFromVid = 1;
					}
				}

				m_pAacConverter->ResetPesPerFrame();

				}
				break;
		}
	} else if(pDecoder == m_pTsServiceSelect){
		switch(dwEventID){
			case CTsServiceSelect::EID_PAT_UPDATE :
				if(m_ServiceNum == 0){				// サービス未指定の場合は
					m_pTsServiceSelect->GetServiceID(&m_NowServiceNum);	// 初回のサービス番号を取得する
					CTsEPGMgr* EpgMgr;			
					EpgMgr =  m_pTsServiceSelect->GetEpgMgr();
					EpgMgr->Clear();
					m_wNowEventID=0;
				}				
				break;
			case CTsServiceSelect::EID_EPG_UPDATE :
				CTsEPGMgr* EpgMgr;
				TSEPG_PROGRAM* Prg;
				
				EpgMgr =  m_pTsServiceSelect->GetEpgMgr();

//				Prg = EpgMgr->FindEpgDataByTime(m_NowServiceNum,CDateTime::GetCurrentDateTime(),FALSE);
//				Prg = EpgMgr->FindEpgDataLatest(m_NowServiceNum);
				Prg = m_pTsServiceSelect->GetLatestPrg();
				if(Prg){
#ifdef _DEBUG
					if((m_wNowEventID == Prg->wEventID) && (m_NowVersion < Prg->byVersion)){
						m_wNowEventID=0;
					}
#endif
					if(m_wNowEventID != Prg->wEventID){
						m_wNowEventID = Prg->wEventID;
						m_NowVersion = Prg->byVersion;
						if(m_opt & OPT_SHOWTITLE){
							printf("\n");
							log_out(TEXT("現在の番組 :"));
							{
								TSEPG_PROGRAM &stItem=*Prg;
								long year,month,day,hour,min,sec,e_hour,e_min,e_sec;

								CDateTime::ConvertFrom_MJD(/*stItem.stStart.Date*/CDateTime::GetCurrentDateTime().Date,year,month,day);
								CDateTime::ConvertFrom_TimeSec(/*stItem.stStart.Time*/CDateTime::GetCurrentDateTime().Time,hour,min,sec);
								CDateTime::ConvertFrom_TimeSec(stItem.stEnd.Time,e_hour,e_min,e_sec);
								log_out("[%s]\n[%s]\n",stItem.szTitle,stItem.szText);
#ifdef _DEBUG
								log_out("放送時間 :%04d/%02d/%02d(%s) %02d:%02d:%02d-%02d:%02d:%02d[%04X:%04X]\n",
									year,month,day,CDateTime::GetWeekDayString(stItem.stStart.Date),
									hour,min,sec,e_hour,e_min,e_sec,
									stItem.wServiceID,stItem.wEventID
									);
#endif
							}						}
					}
				//	EpgMgr->FreeEpgDataMemory(Prg,1);
				}

				Prg = NULL;
				if(m_RecordingMode){
					if(m_wRecordingNowEventID==0){
						Prg = EpgMgr->FindEpgDataByTitle(m_tstitle,6,m_NowServiceNum);
						if(Prg){
							m_wRecordingNowEventID = Prg->wEventID;
							if(m_opt & OPT_SHOWTITLE){
								log_out(TEXT("録画番組HIT : %s\n"),Prg->szTitle);
							}
						}
					} else {
						Prg = EpgMgr->FindEpgDataByEventID(0,0,m_NowServiceNum,m_wRecordingNowEventID);
					}
					if(Prg){
						m_RecordingEpg = *Prg;
						EpgMgr->FreeEpgDataMemory(Prg,1);
					}
				}
				if(m_RecordingMode && m_opt&OPT_SYNCEIT){
					if(m_wRecordingNowEventID && m_wNowEventID && (m_wNowEventID==m_wRecordingNowEventID)){
						if(!m_pTsServiceSelect->IsStartTrans()){
							m_pTsServiceSelect->StartTrans(TRUE);
							log_out(TEXT("録画スタート。\n"));
						}
					} else {
						if(m_pTsServiceSelect->IsStartTrans()){
							m_pTsServiceSelect->StartTrans(FALSE);
							log_out(TEXT("録画ストップ。\n"));
						}
					}
				}
				break;
		}
	} else {
		switch(dwEventID){
			case CHttpSend::EID_ERROR_SOCKET:
				m_emergency = TRUE;
				break;
		}
	}
		
	return 0UL;
}
