//////////////////////////////////////////
// DirectShowProc.h
// Copyright (c) 01/31/2022 by BCCSkelton
//////////////////////////////////////////

/////////////////////////////////
//主ウィンドウCMyWndの関数の定義
//ウィンドウメッセージ関数
/////////////////////////////////
bool CMyWnd::OnCreate(WPARAM wParam, LPARAM lParam) {

	//コモンコントロールの初期化
	InitCommonControls();

	//ツールバー登録−Init(hWnd, hIinstance, ID, (以下省略可）Style)
	TBar.Init(m_hWnd, m_hInstance, TOOLBAR);
	//ツールバーボタン用カスタムビットマップ追加
	TBar.AddBmp(m_hInstance, MAKEINTRESOURCE(IDI_TOOLBAR), 9);
	//ツールバーボタン追加
	TBBUTTON tbb[13];
	ZeroMemory(tbb, sizeof(tbb));
	tbb[0].iBitmap = TBar.m_id + 0;
	tbb[0].fsState = TBSTATE_ENABLED;
	tbb[0].fsStyle = TBSTYLE_BUTTON;
	tbb[0].idCommand = IDM_OPEN;
	tbb[1].fsStyle = TBSTYLE_SEP;	//セパレーター
	tbb[2].iBitmap = TBar.m_id + 1;
	tbb[2].fsState = TBSTATE_ENABLED;
	tbb[2].fsStyle = TBSTYLE_BUTTON;
	tbb[2].idCommand = IDM_EXIT;
	tbb[3].fsStyle = TBSTYLE_SEP;	//セパレーター
	tbb[4].iBitmap = TBar.m_id + 2;
	tbb[4].fsStyle = TBSTYLE_BUTTON;
	tbb[4].idCommand = IDM_SHOW;
	tbb[5].iBitmap = TBar.m_id + 3;
	tbb[5].fsStyle = TBSTYLE_BUTTON;
	tbb[5].idCommand = IDM_PAUSE;
	tbb[6].iBitmap = TBar.m_id + 4;
	tbb[6].fsStyle = TBSTYLE_BUTTON;
	tbb[6].idCommand = IDM_STOP;
	tbb[7].fsStyle = TBSTYLE_SEP;	//セパレーター
	tbb[8].iBitmap = TBar.m_id + 5;
	tbb[8].fsState = TBSTATE_ENABLED;
	tbb[8].fsStyle = TBSTYLE_BUTTON;
	tbb[8].idCommand = IDM_MAKELIST;
	tbb[9].iBitmap = TBar.m_id + 6;
	tbb[9].fsStyle = TBSTYLE_BUTTON;
	tbb[9].idCommand = IDM_AUTOPLAY;
	tbb[10].fsStyle = TBSTYLE_SEP;	//セパレーター
	tbb[11].iBitmap = TBar.m_id + 7;
	tbb[11].fsState = TBSTATE_ENABLED;
	tbb[11].fsStyle = TBSTYLE_BUTTON;
	tbb[11].idCommand = IDM_ABOUT;
	tbb[12].iBitmap = TBar.m_id + 8;
	tbb[12].fsState = TBSTATE_ENABLED;
	tbb[12].fsStyle = TBSTYLE_BUTTON;
	tbb[12].idCommand = IDM_VERSION;
	TBar.AddButtons(13, tbb);

	//ステータスバー登録−Init(hWnd, hIinstance, ID, (以下省略可）Style)
	SBar.Init(m_hWnd, m_hInstance, STATUSBAR);
	//ステータスバー区画設定
	int sec[3] = {120, 240, -1};
	SBar.SetSection(3, sec);
	//ステータスバー文字列設定
	SBar.SetText(0, "DirectShow Ver 1.1");
	SBar.SetText(1, "再生時間");
	SBar.SetText(2, "ファイル名");

	//メニュー、ツールバーボタン等初期化
	ChangeMenuStatus(0);	//「再生」、「一時停止」、「中止」
	AllowtoOpen(TRUE);		//「動画ファイルを開く」、「URLから開く」
	AutoPlay(TRUE, FALSE);	//「プレイリストの作成・選択」、「プレイリストの再生」

	//ヘルプファイル登録
	g_HelpFile = arg.Path();
	g_HelpFile = g_HelpFile + "\\DirectShowHelp.chm";

	//ファイルリストディレクトリーの作成
	g_FileListDir = arg.Path();
	g_FileListDir = g_FileListDir + "\\FileList";
	if(!PathFileExists(g_FileListDir.ToChar()))
		CreateDirectory(g_FileListDir.ToChar(), NULL);

	//再生用スライダーコントロールの作成
	g_Slider.Create(TBar.GetHandle(), IDC_SLIDER, 340, 0, 300, 24);
	ShowWindow(g_Slider.GetHandle(), SW_HIDE);	//スライダーコントロールを隠す
	//スライダーの親であるツールバーのWM_HSCROLL処理を行う為のサブクラス化
	g_TBProc = (WNDPROC)GetWindowLongPtr(GetDlgItem(m_hWnd, TOOLBAR), GWLP_WNDPROC);
	SetWindowLongPtr(GetDlgItem(m_hWnd, TOOLBAR), GWLP_WNDPROC, (LONG_PTR)TOOLBARProc);

	//ドラッグアンドドロップの受付開始
	DragAcceptFiles(m_hWnd, TRUE);

	//ファイル起動時の処理
	if(arg.c() > 1) {
		if(g_ExtChk.CheckExt(arg.v(1), FILTER)) {
			g_ByFile = TRUE;
			g_dshow.SetFileName(arg.v(1));
			OnOpen();
		}
		else
			MessageBox(m_hWnd, "再生対象外のファイルです", "エラー", MB_OK | MB_ICONERROR);
	}

	return TRUE;
}

bool CMyWnd::OnTimer(WPARAM wParam, LPARAM lParam) {

	int cp = (int)g_dshow.GetCurrentPos();
	char* tm = GetTimeStr(g_Mtm - cp);
	//スライダーコントロールの表示
	g_Slider.SetPosition(cp);
	//ステータスバー文字列設定
	SBar.SetText(1, tm);
	return TRUE;
}

bool CMyWnd::OnLButtonDown(WPARAM wParam, LPARAM lParam) {

	//一時停止（1）または再生中（2）（タイムラグ10/1000秒）
	if(g_dshow.GetState(10) == 1 || g_dshow.GetState(10) == 2) {
		OnPause();
		return TRUE;
	}
	return FALSE;
}

bool CMyWnd::OnRButtonDown(WPARAM wParam, LPARAM lParam) {

	//ポップアップメニューを読みこむ
	HMENU hPopupMenu = GetSubMenu(GetMenu(m_hWnd), 1);
	//ポップアップメニューの表示
	POINT pt;
	GetCursorPos(&pt);
	TrackPopupMenu(hPopupMenu, TPM_LEFTALIGN | TPM_LEFTBUTTON,
				  pt.x, pt.y, 0, m_hWnd, NULL);
	return TRUE;
}

bool CMyWnd::OnNotify(WPARAM wParam, LPARAM lParam) {

	//ツールバーからのツールチップ情報取得
	if(((LPNMHDR)lParam)->code == TTN_NEEDTEXT) {
		static LPTOOLTIPTEXT lptip;
		lptip = (LPTOOLTIPTEXT)lParam;
		switch (lptip->hdr.idFrom) {
			case IDM_OPEN:
				lptip->lpszText = "動画ファイルを開く";
				break;
			case IDM_EXIT:
				lptip->lpszText = "終了";
				break;
			case IDM_SHOW:
				lptip->lpszText = "再生";
				break;
			case IDM_PAUSE:
				lptip->lpszText = "一時停止";
				break;
			case IDM_STOP:
				lptip->lpszText = "中止";
				break;
			case IDM_MAKELIST:
				lptip->lpszText = "プレイリストの作成・選択";
				break;
			case IDM_AUTOPLAY:
				lptip->lpszText = "プレイリストの再生";
				break;
			case IDM_ABOUT:
				lptip->lpszText = "DirectShowについて";
				break;
			case IDM_VERSION:
				lptip->lpszText = "バージョン情報";
				break;
		}
		return TRUE;
	}
	return FALSE;
}

bool CMyWnd::OnSize(WPARAM wParam, LPARAM lParam) {

	TBar.AutoSize();
	SBar.AutoSize();
	//スライダーコントロールの自動位置調整
	g_Slider.AutoSize(1);		//右上隅にmarginxは0、marginyは2で表示
	//クライアントエリアサイズ
	int w = LOWORD(lParam);		//ウインドウ幅
	int h = HIWORD(lParam);		//ウインドウ高さ
	//TBarとSBarの高さを控除
	RECT rec;
	GetWindowRect(SBar.GetHandle(), &rec);
	h -= rec.bottom - rec.top;
	GetWindowRect(TBar.GetHandle(), &rec);
	int barh = rec.bottom - rec.top;
	h -= barh;
	g_dshow.Move(0, barh, w, h);
	return TRUE;
}

bool CMyWnd::OnClose(WPARAM wParam, LPARAM lParam) {

	if(MessageBox(m_hWnd, "終了しますか", "終了確認",
					MB_YESNO | MB_ICONINFORMATION) == IDYES)
		//処理をするとDestroyWindow、PostQuitMessageが呼ばれる
		return TRUE;
	else
		//そうでなければウィンドウではDefWindowProc関数をreturn、ダイアログではreturn FALSEとなる。
		return FALSE;
}

bool CMyWnd::OnMinMax(WPARAM wParam, LPARAM lParam) {

	//典型的なウィンドウのサイズ制限処理
	MINMAXINFO *pmmi;
	pmmi = (MINMAXINFO*)lParam;
	pmmi->ptMinTrackSize.x = 656;	//クライアントエリア640 + 16
	pmmi->ptMinTrackSize.y = 541;	//クライアントエリア480 + 61
	return FALSE;					//処理はDefWndProcに任す
}

bool CMyWnd::OnGraphNotify(WPARAM wParam, LPARAM lParam) {

	long evnt;					//EC_COMPLETE - 再生終了、EC_USERABORT - 再生中止、EC_ERRORABORT - エラー
	if(!g_dshow.IsOver(evnt))	//再生開始前や再生中は何もしない
		return FALSE;
	//終了処理
	WhenComplete();
	//プレイリスト再生中
	if(g_AutoPlay) {
		if(*m_FileList.ToChar())	//まだ完了していない場合
			OnAutoPlay();
		else {						//完了した場合
			g_AutoPlay = FALSE;
			AutoPlay(TRUE, FALSE);	//プレイリストの作成・選択、再生
		}
	}	
	return TRUE;
}

bool CMyWnd::OnDropFiles(WPARAM wParam) {

	//ドラッグアンドドロップされたファイル名取得と処理
	char FileName[MAX_PATH];
	DragQueryFile((HDROP)wParam, 0, FileName, MAX_PATH);
	if(g_ExtChk.CheckExt(FileName, FILTER)) {
		g_ByFile = TRUE;
		g_dshow.SetFileName(FileName);
		OnOpen();
		DragFinish((HDROP)wParam);
		return TRUE;
	}
	MessageBox(m_hWnd, "再生対象外のファイルです", "エラー", MB_OK | MB_ICONERROR);
	return FALSE;
}

/////////////////////////////////
//主ウィンドウCMyWndの関数の定義
//メニュー項目、コントロール関数
/////////////////////////////////
bool CMyWnd::OnOpen() {

	if(g_ByFile)
		g_ByFile = FALSE;
	else {
		//動画ファイルを読む
		if(!g_dshow.SetFileName(""))
			return FALSE;
	}
	//メニュー、ボタンの状態変更
	ChangeMenuStatus(1);
	//ステータスバー文字列設定
	SBar.SetText(2, g_dshow.m_FileName);
	SBar.SendMsg(SB_SETTIPTEXT, 2, (LPARAM)g_dshow.m_FileName);	//ToolTipをつける
	return TRUE;
}

bool CMyWnd::OnUrl() {

	urldlg.DoModal(m_hWnd, "IDD_URL", urldlgProc, m_hInstance);
	//メニュー、ボタンの状態変更
	ChangeMenuStatus(1);
	//ステータスバー文字列設定
	SBar.SetText(2, g_dshow.m_FileName);
	SBar.SendMsg(SB_SETTIPTEXT, 2, (LPARAM)g_dshow.m_FileName);	//ToolTipをつける
	return TRUE;
}

bool CMyWnd::OnExit() {

	SendMsg(WM_CLOSE, 0, 0);
	return TRUE;
}

bool CMyWnd::OnShow() {

	//再生開始
	if(g_dshow.Show(m_hWnd)) {
		g_Mtm = (int)g_dshow.GetDuration();
		char* tm = GetTimeStr(g_Mtm);
		//ステータスバー文字列設定
		SBar.SetText(1, tm);
		SBar.SendMsg(SB_SETTIPTEXT, 1, (LPARAM)tm);	//ToolTipをつける
		//メニュー、ボタンの状態変更
		ChangeMenuStatus(2);
		AllowtoOpen(FALSE);		//ファイル読み込みを不能にする
		//再生用スライダーコントロールの設定
		g_Slider.SetRange(0, g_Mtm);
		g_Slider.SetPosition(0);
		//スライダーコントロールを表示する
		ShowWindow(g_Slider.GetHandle(), SW_SHOW);
		//タイマー開始（毎1秒）
		g_tmr.Begin(m_hWnd, 1, 1000);
		return TRUE;
	}
	else
		return FALSE;
}

bool CMyWnd::OnPause() {

	static bool toggle = FALSE;
	if(toggle) {
		//再生再開（Run()メソッド）
		g_dshow.Continue();
		//メニュー、ボタンの状態変更
		ChangeMenuStatus(2);
		g_tmr.Begin(m_hWnd, 1, 1000);	//タイマー開始（毎1秒）
	}
	else {
		//再生一時停止
		g_dshow.Pause();
		//メニュー、ボタンの状態変更
		ChangeMenuStatus(3);
		g_tmr.Stop();					//タイマー中止
	}
	toggle = !toggle;
	return TRUE;
}

bool CMyWnd::OnStop() {

	//再生中止
	g_dshow.Stop();
	//終了処理
	WhenComplete();
	//プレイリスト再生中
	if(g_AutoPlay) {
		if(*m_FileList.ToChar()) {		//まだ完了していない場合
			if(MessageBox(m_hWnd, "プレイリスト再生を続けますか？", "プレイリスト再生確認",
						MB_YESNO | MB_ICONQUESTION) == IDYES)
				OnAutoPlay();
			else {						//プレイリスト再生の中止
				m_FileList = "";
				g_AutoPlay = FALSE;
				AutoPlay(TRUE, FALSE);	//プレイリストの作成・選択、再生
			}
		}
		else {							//完了した場合
			g_AutoPlay = FALSE;
			AutoPlay(TRUE, FALSE);		//プレイリストの作成・選択、再生
		}
	}	
	return TRUE;
}

bool CMyWnd::OnMakelist() {

	//FileList.dllからダイアログを呼ぶ
	char* fn = GetFileList("プレイリストファイル(*.plf)\0*.plf\0\0", FILTER, g_FileListDir.ToChar(), "plf");
	if(!*fn) {
		MessageBox(m_hWnd, "plfファイルが選択されませんでした", "エラー", MB_OK | MB_ICONERROR);
		return FALSE;
	}
	m_FileList.FromFile(fn);
	//プレイリストの再生メニューとツールボタンを有効化する
	AutoPlay(FALSE, TRUE);
	return TRUE;
}

bool CMyWnd::OnAutoPlay() {

	CSTR fn, comment;
	if(!m_FileList.Next(fn)) {		//ファイルリストから再生ファイルのフルパス名を切り出す
		g_AutoPlay = FALSE;
		AutoPlay(TRUE, FALSE);
		MessageBox(m_hWnd, "プレイリスト再生が完了しました", "プレイリスト再生完了", MB_OK | MB_ICONINFORMATION);
	}
	else {							//ファイルリストに再生ファイルがあったならば
		m_FileList.Next(comment);	//ファイルリストから不要な「備考」を切り出す
		//DirectShowに再生ファイルを登録
		g_dshow.SetFileName(fn.ToChar());
		//ステータスバー文字列設定
		SBar.SetText(2, g_dshow.m_FileName);
		SBar.SendMsg(SB_SETTIPTEXT, 2, (LPARAM)g_dshow.m_FileName);	//ToolTipをつける
		//プレイリストの作成・選択、再生メニューを無効化する
		AutoPlay(FALSE, FALSE);
		//プレイリスト再生状態
		g_AutoPlay = TRUE;
		//再生
		if(!OnShow())					//プレイリストの再生に失敗した場合
			OnStop();
	}
	return TRUE;
}

bool CMyWnd::OnPlayList() {

	CSTR List, FileList, FileName;
	CARG arg;
	FileList = m_FileList;
	while(FileList.Next(FileName)) {
		arg = FileName.ToChar();
		List = List + arg.FileName();
		List = List + "\r\n";
		FileList.Next(FileName);		//備考をスキップする
	}
	MessageBox(m_hWnd, List.ToChar(), "プレイリスト", MB_OK | MB_ICONINFORMATION);
	return TRUE;
}

bool CMyWnd::OnAbout() {

	CSTR cmd = "hh ";
	cmd = cmd + g_HelpFile;
	WinExec(cmd.ToChar(), SW_SHOWNORMAL);
	return TRUE;
}

bool CMyWnd::OnVersion() {

	versiondlg.DoModal(m_hWnd, "IDD_VERSION", versiondlgProc, m_hInstance);
	return TRUE;
}

////////////////////////////////////////////////////////
//ユーザー定義関数
//スライダー非表示とタイマー、再生時間メニュー等の初期化
////////////////////////////////////////////////////////
void CMyWnd::WhenComplete() {

	//タイマー中止
	g_tmr.Stop();
	//再生時間の初期化
	g_Mtm = 0;
	//スライダーコントロールを隠す
	ShowWindow(g_Slider.GetHandle(), SW_HIDE);
	//再生終了後、ファイル読み込み後状態にする（再生可）
	ChangeMenuStatus(1);
	//ファイル読み込みを可能にする
	AllowtoOpen(TRUE);
}

///////////////////////////////////////////////////
//ユーザー定義関数
//初期状態・終了時0
//ファイル読込み時1、再生時2、一時停止時3（トグル）
///////////////////////////////////////////////////
void CMyWnd::ChangeMenuStatus(int flag) {

	HMENU hMenu = GetSubMenu(GetMenu(m_hWnd), 1);	//メニューハンドルの取得
	switch(flag) {
	case 0:		//全て無効化する
		//メニューアイテム
		EnableMenuItem(hMenu, 0, MF_BYPOSITION | MF_GRAYED);
		EnableMenuItem(hMenu, 1, MF_BYPOSITION | MF_GRAYED);
		EnableMenuItem(hMenu, 2, MF_BYPOSITION | MF_GRAYED);
		//ツールバーボタン
		SendMessage(TBar.GetHandle(), TB_ENABLEBUTTON, IDM_SHOW, MAKELONG(FALSE, 0));
		SendMessage(TBar.GetHandle(), TB_ENABLEBUTTON, IDM_PAUSE, MAKELONG(FALSE, 0));
		SendMessage(TBar.GetHandle(), TB_ENABLEBUTTON, IDM_STOP, MAKELONG(FALSE, 0));
		break;
	case 1:		//再生のみ有効化する
		//メニューアイテム
		EnableMenuItem(hMenu, 0, MF_BYPOSITION | MF_ENABLED);
		EnableMenuItem(hMenu, 1, MF_BYPOSITION | MF_GRAYED);
		EnableMenuItem(hMenu, 2, MF_BYPOSITION | MF_GRAYED);
		//ツールバーボタン
		SendMessage(TBar.GetHandle(), TB_ENABLEBUTTON, IDM_SHOW, MAKELONG(TRUE, 0));
		SendMessage(TBar.GetHandle(), TB_ENABLEBUTTON, IDM_PAUSE, MAKELONG(FALSE, 0));
		SendMessage(TBar.GetHandle(), TB_ENABLEBUTTON, IDM_STOP, MAKELONG(FALSE, 0));
		break;
	case 2:		//再生を無効化し、一時停止、中止を有効化する
		//メニューアイテム
		EnableMenuItem(hMenu, 0, MF_BYPOSITION | MF_GRAYED);
		EnableMenuItem(hMenu, 1, MF_BYPOSITION | MF_ENABLED);
		EnableMenuItem(hMenu, 2, MF_BYPOSITION | MF_ENABLED);
		//ツールバーボタン
		SendMessage(TBar.GetHandle(), TB_ENABLEBUTTON, IDM_SHOW, MAKELONG(FALSE, 0));
		SendMessage(TBar.GetHandle(), TB_ENABLEBUTTON, IDM_PAUSE, MAKELONG(TRUE, 0));
		SendMessage(TBar.GetHandle(), TB_ENABLEBUTTON, IDM_STOP, MAKELONG(TRUE, 0));
		break;
	case 3:		//再生、中止を共に無効化する
		//メニューアイテム
		EnableMenuItem(hMenu, 0, MF_BYPOSITION | MF_GRAYED);
		EnableMenuItem(hMenu, 2, MF_BYPOSITION | MF_GRAYED);
		//ツールバーボタン
		SendMessage(TBar.GetHandle(), TB_ENABLEBUTTON, IDM_SHOW, MAKELONG(FALSE, 0));
		SendMessage(TBar.GetHandle(), TB_ENABLEBUTTON, IDM_STOP, MAKELONG(FALSE, 0));
		break;
	default:
		return;
	}
	DrawMenuBar(m_hWnd);	//Re-draw
}

/////////////////////////////////////////////////////
//ユーザー定義関数
//「ファイルを開く」と「URLから開く」の状態を変更する
/////////////////////////////////////////////////////
void CMyWnd::AllowtoOpen(bool flag) {

	HMENU hMenu = GetSubMenu(GetMenu(m_hWnd), 0);	//メニューハンドルの取得
	//メニューアイテム
	EnableMenuItem(hMenu, 0, MF_BYPOSITION | (flag ? MF_ENABLED : MF_GRAYED));
	EnableMenuItem(hMenu, 1, MF_BYPOSITION | (flag ? MF_ENABLED : MF_GRAYED));
	//ツールバーボタン
	SendMessage(TBar.GetHandle(), TB_ENABLEBUTTON, IDM_OPEN, MAKELONG(flag, 0));
	SendMessage(TBar.GetHandle(), TB_ENABLEBUTTON, IDM_URL, MAKELONG(flag, 0));
}

//////////////////////////////////////////////////////////////////////
//ユーザー定義関数
//「プレイリストの作成・選択」と「プレイリストの再生」の状態を変更する
//////////////////////////////////////////////////////////////////////
void CMyWnd::AutoPlay(bool flag1, bool flag2) {

	HMENU hMenu = GetSubMenu(GetMenu(m_hWnd), 2);	//メニューハンドルの取得
	//メニューアイテム
	EnableMenuItem(hMenu, 0, MF_BYPOSITION | (flag1 ? MF_ENABLED : MF_GRAYED));
	EnableMenuItem(hMenu, 1, MF_BYPOSITION | (flag2 ? MF_ENABLED : MF_GRAYED));
	//ツールバーボタン
	SendMessage(TBar.GetHandle(), TB_ENABLEBUTTON, IDM_MAKELIST, MAKELONG(flag1, 0));
	SendMessage(TBar.GetHandle(), TB_ENABLEBUTTON, IDM_AUTOPLAY, MAKELONG(flag2, 0));
}

////////////////////////////////////////////
//ユーザー定義関数
//整数の秒数を「時間分秒」の文字列にして返す
////////////////////////////////////////////
char* CMyWnd::GetTimeStr(int tm) {

	static CSTR tmstr;
	int hour, min, sec;
	hour = tm / 3600;
	min = sec = tm % 3600;
	min /= 60;
	sec %= 60;
	tmstr = "残り";
	if(hour) {
		tmstr = tmstr + hour;
		tmstr = tmstr + "時間";
	}
	tmstr = tmstr + min + "分";
	tmstr = tmstr + sec + "秒";
	return tmstr.ToChar();
}

///////////////////////////////
//ユーザーダイアログの関数定義
//コントロール関数
///////////////////////////////
bool URLDLG::OnIdok() {

	char buff[MAX_PATH];
	SendItemMsg(IDC_URL, WM_GETTEXT, MAX_PATH, (LPARAM)buff);
	if(g_dshow.SetFileName(buff)) {
		EndModal(TRUE);
		return TRUE;
	}
	else {
		EndModal(FALSE);
		return FALSE;
	}
}

bool URLDLG::OnCancel() {

	EndModal(FALSE);
	return FALSE;
}

///////////////////////////////
//ユーザーダイアログの関数定義
//コントロール関数
///////////////////////////////
bool VERSIONDLG::OnIdok() {

	EndModal(TRUE);
	return TRUE;
}
