///////////////////////////////////////////////
//SpeechRecognitionEngineのテスト−Windows版
///////////////////////////////////////////////
using System;
using System.Windows;
using System.Windows.Controls;		//コントロールを利用する為
using System.Windows.Media.Imaging;	//BitmapFrameを使用する為
using System.Speech.Recognition;	//音声認識エンジン

namespace SpeechRecognitionWin
{
	///////////////////////////
	//エントリーポイントクラス
	///////////////////////////
	class MainApp
	{
		[STAThread]
		public static void Main()
		{
			MainWindow mwnd = new MainWindow();
			Application ap = new Application();
			ap.Run(mwnd);
		}
	}

	public partial class MainWindow : Window
	{
		//MainWindowクラスの変数
		SpeechRecognitionEngine recEng;	//音声認識エンジン
		TextBox TBox;					//テキストボックス
		ListBox LBox;					//リストボックス
		Button extBtn;					//終了ボタン

		//コンストラクター
		public MainWindow()
		{
			//this.Icon = BitmapFrame.Create(new Uri("Icon.ico", UriKind.Relative));	//同じフォールダーのIcon.icoを読んで使用する
			this.WindowStyle = WindowStyle.ThreeDBorderWindow;
			this.Background = SystemColors.WindowBrush;
			this.WindowStartupLocation = WindowStartupLocation.CenterScreen;
			this.Width = 525;
			this.Height = 350;
			this.ResizeMode = ResizeMode.CanResizeWithGrip;
			this.ShowActivated = true;							//アクティブ状態で初期表示するかどうか−規定値 true
			this.ShowInTaskbar = true;							//タスクバ−にボタン表示するか否か
			this.Title = "Speech Recognition";
			this.Loaded += Window_Loaded;
		}
		
		//WM_CREATE時処理
		private void Window_Loaded(object sender, EventArgs e)
		{
			//コントロールの設定
			InitControls();
			//インストールされている音声認識エンジンでインスタンスを生成
			recEng = new SpeechRecognitionEngine(SelectEngine());
			//DictationGrammar (ディクティション用の辞書)の追加
			recEng.LoadGrammar(new DictationGrammar());
			try
			{
				//音声認識エンジンへの入力設定
				recEng.SetInputToDefaultAudioDevice();
				//非同期音声認識を継続、複数音声認識を実行する
				recEng.RecognizeAsync(RecognizeMode.Multiple);
			}
			catch
			{
				MessageBox.Show("音声標準出力がありません", "エラー", MessageBoxButton.OK, MessageBoxImage.Error);
			}
			//音声認識イベントハンドラー
			recEng.SpeechRecognized += new EventHandler<SpeechRecognizedEventArgs>(recEng_SpeechRecognized);
			//recEng.SpeechRecognized += recEng_SpeechRecognized;
			//音声推定イベントハンドラー
			recEng.SpeechHypothesized += new EventHandler<SpeechHypothesizedEventArgs>(recEng_SpeechHypothesized);
			//recEng.SpeechHypothesized += recEng_SpeechHypothesized;
		}

		//インストールされた音声認識エンジンを表示し、選択させる
		public RecognizerInfo SelectEngine()
		{
			//全音声認識エンジンをリストボックスに表示
			foreach(RecognizerInfo ri in SpeechRecognitionEngine.InstalledRecognizers())
			{
				LBox.Items.Add(ri.Culture.Name);
			}
			//音声認識エンジンの選択
			RecognizerInfo info = null;
			while(info == null)	//選択しない限り終了しない
			{
				//インストールされた音声認識エンジンを順に表示
				foreach(RecognizerInfo ri in SpeechRecognitionEngine.InstalledRecognizers())
				{
					MessageBoxResult result = MessageBox.Show(
									"以下のエンジンが見つかりました。\r\n\r\n" + 
									ri.Name + " : " + ri.Culture.Name + 
									"\r\n\r\nこれを選択しますか？（キャンセル−終了）", "音声認識エンジン", 
									MessageBoxButton.YesNoCancel, MessageBoxImage.Question);
					if(result == MessageBoxResult.Yes)	//選択
					{
						info = ri;
						MessageBox.Show(ri.Culture.Name + " で音声認識を開始します。", "通知", MessageBoxButton.OK, MessageBoxImage.Information);
						break;
					}
					else if(result == MessageBoxResult.Cancel)	//終了
					{
						Close();
					}
				}
			}
			return info;
		}

		//コントロールの設定
		public void InitControls()
		{
			//グリッド（Grid）を作成
			Grid grid = new Grid();
			//縦二列を作成・定義
			ColumnDefinition colL = new ColumnDefinition();
			ColumnDefinition colR = new ColumnDefinition();
			colL.Width = new GridLength(this.Width / 2, GridUnitType.Pixel);
			//colL.Width = GridLength.Auto;
			colR.Width = GridLength.Auto;
			grid.ColumnDefinitions.Add(colL);
			grid.ColumnDefinitions.Add(colR);
			//テキストボックスを作成
			TBox = new TextBox();
			//位置、フォントサイズとその他設定
			TBox.Margin = new Thickness(5, 5, 5, 5);
			TBox.FontSize = 12;
			TBox.HorizontalAlignment = HorizontalAlignment.Left;
			TBox.TextWrapping = TextWrapping.NoWrap;
			TBox.HorizontalScrollBarVisibility = ScrollBarVisibility.Visible;
			TBox.VerticalScrollBarVisibility = ScrollBarVisibility.Visible;
			//グリッド左列にをテキストボックスを登録
			Grid.SetColumn(TBox, 0);		//Gridクラスの静的メソッドである点に注意
			grid.Children.Add(TBox);
			//ドックパネル（DockPanel）を作成
			DockPanel dPanel = new DockPanel();
			//ラベルを生成
			Label lbl = new Label();
			lbl.Content = "このPCにインストールされている音声認識エンジン";
			lbl.HorizontalAlignment = HorizontalAlignment.Center;
			DockPanel.SetDock(lbl, Dock.Top);	//DockPanelクラスの静的メソッドである点に注意
			dPanel.Children.Add(lbl);
			//リストボックスを生成
			LBox = new ListBox();
			LBox.SelectionMode = SelectionMode.Single;
			LBox.Margin = new Thickness(10, 10, 10, 10);
			LBox.HorizontalAlignment = HorizontalAlignment.Stretch;
			LBox.VerticalAlignment = VerticalAlignment.Stretch;
			DockPanel.SetDock (LBox, Dock.Top);	//DockPanelクラスの静的メソッドである点に注意
			dPanel.Children.Add(LBox);
			//終了ボタンを生成
			extBtn = new Button();
			extBtn.Width = 60;
			extBtn.Height = 24;
			extBtn.Margin = new Thickness(10, 10, 10, 10);	//構造体 Thickness(左, 上, 右, 下)
			extBtn.HorizontalAlignment = HorizontalAlignment.Stretch;	//HorizontalAlignment.Right;
			extBtn.VerticalAlignment = VerticalAlignment.Bottom;
			extBtn.Content = "終了";
			extBtn.Click += extBtn_Click;
			DockPanel.SetDock (extBtn, Dock.Bottom);	//DockPanelクラスの静的メソッドである点に注意
			dPanel.Children.Add(extBtn);
			//グリッド右列にドックパネルを登録
			Grid.SetColumn(dPanel, 1);			//Gridクラスの静的メソッドである点に注意
			grid.Children.Add(dPanel);
			//MainWindowにgridを追加
			this.Content = grid;
		}

		//終了処理
		protected override void OnClosed(EventArgs e)
		{
			base.OnClosed(e);
			//終了時に音声認識エンジンを開放する。
			recEng.Dispose();
		}

		//認識時の処理
		void recEng_SpeechRecognized(object sender, SpeechRecognizedEventArgs e)
		{
			this.TBox.Text = "認識：" + e.Result.Text + "(" + e.Result.Confidence + ")\r\n" + this.TBox.Text;
		}

		//推定時の処理
		void recEng_SpeechHypothesized(object sender, SpeechHypothesizedEventArgs e)
		{
			this.TBox.Text = "推定：" + e.Result.Text + "("+ e.Result.Confidence + ")\r\n" + this.TBox.Text;
		}

		//終了ボタンクリック時の処理
		void extBtn_Click(object sender, RoutedEventArgs e)
		{
			Close();
		}
	}
}
