OSDN Git Service

シンバルミュートチップを実装。
[strokestylet/CsWin10Desktop3.git] / SSTFEditor / メインフォーム.cs
index 706bc6f..4a33730 100644 (file)
@@ -3,8 +3,12 @@ using System.Collections.Generic;
 using System.Diagnostics;
 using System.Drawing;
 using System.IO;
+using System.IO.Pipes;
 using System.Linq;
 using System.Reflection;
+using System.ServiceModel;
+using System.ServiceModel.Channels;
+using System.Text.RegularExpressions;
 using System.Windows.Forms;
 using FDK;     // for string拡張
 
@@ -195,6 +199,8 @@ namespace SSTFEditor
                        { SSTFormat.チップ種別.Tom2_Rim, "LowTom(RimShot)" },
                        { SSTFormat.チップ種別.Tom3, "FloorTom" },
                        { SSTFormat.チップ種別.Tom3_Rim, "FloorTom(RimShot)" },
+                       { SSTFormat.チップ種別.LeftCymbal_Mute, "Mute" },
+                       { SSTFormat.チップ種別.RightCymbal_Mute, "Mute" },
                        { SSTFormat.チップ種別.Unknown, "" },
                        { SSTFormat.チップ種別.小節線, "" },
                        { SSTFormat.チップ種別.背景動画, "" },
@@ -223,6 +229,10 @@ namespace SSTFEditor
                protected int 現在のガイド間隔 = 0;
                protected Point 選択モードのコンテクストメニューを開いたときのマウスの位置;
 
+               protected ChannelFactory<SST.IStrokeStyleTService> SSTファクトリ = null;
+               protected SST.IStrokeStyleTService SSTサービス = null;
+               protected IClientChannel SSTサービスチャンネル = null;
+
                private bool bs_未保存である = false;
                private SSTFormat.チップ種別 bs_e現在のチップ種別;
                private int bs_GRID_PER_PIXEL = 1;
@@ -280,7 +290,7 @@ namespace SSTFEditor
                        
                        // 最近使ったファイル一覧を更新する。
                        this.ConfigのRecentUsedFilesをファイルメニューへ追加する();
-                       
+
                        // その他の初期化。
                        this.Act新規作成する();
                        this.Actガイド間隔を変更する( 16 );   // 初期は 1/16 間隔。
@@ -288,16 +298,41 @@ namespace SSTFEditor
 
                        // 完了。
                        this.初期化完了 = true;
+
+                       // コマンドライン引数に、存在するファイルの指定があれば開く。
+                       foreach( var arg in Environment.GetCommandLineArgs().Skip( 1 ) )    // 先頭は exe 名なのでスキップ。
+                       {
+                               if( Path.GetExtension( arg ).ToLower() == ".sstf" && File.Exists( arg ) )
+                               {
+                                       this.Act指定されたファイルを開く( arg );
+                                       break;
+                               }
+                       }
                }
                protected void Actアプリを終了する()
                {
+                       // SSTファクトリを閉じる。
+                       try
+                       {
+                               this.SSTサービスチャンネル?.Close();
+                               this.SSTサービスチャンネル = null;
+                               this.SSTサービス = null;
+
+                               this.SSTファクトリ?.Close();
+                               this.SSTファクトリ = null;
+                       }
+                       catch
+                       {
+                               // エラーは無視。
+                       }
+
                        // 一時ファイルが残っていれば、削除する。
                        if( File.Exists( this.最後にプレイヤーに渡した一時ファイル名 ) )
                                File.Delete( this.最後にプレイヤーに渡した一時ファイル名 );
 
                        // Config.xml を保存する。
                        this.Config.保存する( Path.Combine( this.ユーザフォルダパス, Properties.Resources.CONFIG_FILE_NAME ) );
-                       
+
                        FDK.Utilities.解放する( ref this.譜面 );
                        FDK.Utilities.解放する( ref this.選択モード );
                }
@@ -764,11 +799,80 @@ namespace SSTFEditor
                                this.最後にプレイヤーに渡した一時ファイル名, 
                                一時ファイルである: true );    // 一時ファイルなので、「最近使ったファイル一覧」には残さない。
 
-                       // プレイヤーを起動する。
-                       string 仮想ドラムオプション = ( 仮想ドラムを使う ) ? @" -h" : @"";
-                       Process.Start(
-                               this.Config.ViewerPath,
-                               $"\"{this.最後にプレイヤーに渡した一時ファイル名}\" -p {小節番号.ToString()}{仮想ドラムオプション}" );
+                       // SSTサービスを取得する。
+                       this.SSTサービスが起動していれば取得する();
+
+                       // プロセスの起動が必要か?
+                       bool ビュアープロセスを起動する = false;
+
+                       if( null == this.SSTサービス )
+                       {
+                               ビュアープロセスを起動する = true;
+                       }
+                       else
+                       {
+                               try
+                               {
+                                       this.SSTサービス.GetSoundDelay();
+                               }
+                               catch
+                               {
+                                       ビュアープロセスを起動する = true;
+                               }
+                       }
+
+                       // 必要ならビュアープロセスを起動する。
+                       if( ビュアープロセスを起動する )
+                       {
+                               try
+                               {
+                                       Process.Start( this.Config.ViewerPath, "-v" );  // ビュアーオプション付き
+                               }
+                               catch
+                               {
+                                       return; // 起動に失敗。
+                               }
+
+                               // Viewer の提供するSSTサービスへ接続する。
+                               this.SSTファクトリ = null;
+                               for( int retry = 0; retry < 10; retry++ )       // 最大10回リトライ。
+                               {
+                                       this.SSTサービスが起動していれば取得する();
+
+                                       if( null != this.SSTサービス )
+                                               break;  // サービスに接続できた。
+
+                                       // 少し待ってリトライ。
+                                       System.Threading.Thread.Sleep( 500 );
+                               }
+                               if( null == this.SSTサービス )
+                               {
+                                       this.Viewer再生関連GUIのEnabledを設定する();
+                                       return; // サービスへの接続に失敗した。
+                               }
+                       }
+
+                       // サウンドデバイス遅延を取得する。
+                       float 遅延ms = this.SSTサービス.GetSoundDelay();
+                       if( this.譜面.SSTFormatScore.Header.サウンドデバイス遅延ms != 遅延ms )
+                       {
+                               this.textBoxサウンド遅延ms.Text = 遅延ms.ToString();                            // GUI と
+                               this.譜面.SSTFormatScore.Header.サウンドデバイス遅延ms = 遅延ms;  // 譜面にセットする。
+                               this.未保存である = true;
+                       }
+
+                       // 演奏開始を指示する。
+                       try
+                       {
+                               this.SSTサービス.ViewerPlay(
+                                       path: this.最後にプレイヤーに渡した一時ファイル名,
+                                       startPart: 小節番号,
+                                       drumsSound: 仮想ドラムを使う );
+                       }
+                       catch
+                       {
+                               // 例外は無視。
+                       }
                }
                protected void Act再生を停止する()
                {
@@ -776,8 +880,15 @@ namespace SSTFEditor
                                ( false == File.Exists( this.Config.ViewerPath ) ) )
                                return;
 
-                       // プレイヤーを、演奏停止オプションをつけて起動する。
-                       Process.Start( this.Config.ViewerPath, @"-s" );
+                       // SSTサービスを取得する。
+                       this.SSTサービスが起動していれば取得する();
+
+                       // SSTサービスが起動していないなら何もしない。
+                       if( null == this.SSTサービス )
+                               return;
+
+                       // 演奏を停止する。
+                       this.SSTサービス.ViewerStop();
                }
                protected void Actオプションを設定する()
                {
@@ -797,6 +908,8 @@ namespace SSTFEditor
                                        this.Config.MaxOfUsedRecentFiles = (int) dialog.numericUpDown最近使用したファイルの最大表示個数.Value;
                                        this.Config.ViewerPath = dialog.textBoxViewerPath.Text;
 
+                                       this.Viewer再生関連GUIのEnabledを設定する();
+
                                        // [ファイル] メニューを修正。
                                        this.ConfigのRecentUsedFilesをファイルメニューへ追加する();
 
@@ -1329,6 +1442,8 @@ namespace SSTFEditor
                                this.textBox背景動画.Text = Path.GetFileName( 譜面.SSTFormatScore.背景動画ファイル名 );
                                this.次のプロパティ変更がUndoRedoリストに載らないようにする();
                                this.textBoxメモ.Text = ( this.譜面.SSTFormatScore.dicメモ.ContainsKey( 0 ) ) ? this.譜面.SSTFormatScore.dicメモ[ 0 ] : "";
+                               this.次のプロパティ変更がUndoRedoリストに載らないようにする();
+                               this.textBoxサウンド遅延ms.Text = this.譜面.SSTFormatScore.Header.サウンドデバイス遅延ms.ToString();
 
                                // ウィンドウのタイトルバーの表示変更(str編集中のファイル名 が確定した後に)
                                this.未保存である = true;     // 以前の状態によらず、確実に更新するようにする。
@@ -1391,34 +1506,33 @@ namespace SSTFEditor
                }
                protected void Viewer再生関連GUIのEnabledを設定する()
                {
-                       if( File.Exists( this.Config.ViewerPath ) )
-                       {
-                               // (A) Viewer が存在するなら、各GUIは有効。
-
-                               this.toolStripButton先頭から再生.Enabled = true;
-                               this.toolStripButton現在位置から再生.Enabled = true;
-                               this.toolStripButton現在位置からBGMのみ再生.Enabled = true;
-                               this.toolStripButton再生停止.Enabled = true;
+                       bool 各GUIは有効 = false;
 
-                               this.toolStripMenuItem先頭から再生.Enabled = true;
-                               this.toolStripMenuItem現在位置から再生.Enabled = true;
-                               this.toolStripMenuItem現在位置からBGMのみ再生.Enabled = true;
-                               this.toolStripMenuItem再生停止.Enabled = true;
+                       if( null != this.SSTサービス )
+                       {
+                               // (A) SSTサービスが起動しているなら、各GUIは有効。
+                               各GUIは有効 = true;
+                       }
+                       else if( File.Exists( this.Config.ViewerPath ) )
+                       {
+                               // (B) SSTサービスが起動していなくても、Viewer が存在するなら、各GUIは有効。
+                               各GUIは有効 = true;
                        }
                        else
                        {
-                               // (B) Viewer が存在しないなら、各GUIは無効。
+                               // (C) SSTサービスが起動しておらず、Viewer も存在しないなら、各GUIは無効。
+                               各GUIは有効 = false;
+                       }
 
-                               this.toolStripButton先頭から再生.Enabled = false;
-                               this.toolStripButton現在位置から再生.Enabled = false;
-                               this.toolStripButton現在位置からBGMのみ再生.Enabled = false;
-                               this.toolStripButton再生停止.Enabled = false;
+                       this.toolStripButton先頭から再生.Enabled = 各GUIは有効;
+                       this.toolStripButton現在位置から再生.Enabled = 各GUIは有効;
+                       this.toolStripButton現在位置からBGMのみ再生.Enabled = 各GUIは有効;
+                       this.toolStripButton再生停止.Enabled = 各GUIは有効;
 
-                               this.toolStripMenuItem先頭から再生.Enabled = false;
-                               this.toolStripMenuItem現在位置から再生.Enabled = false;
-                               this.toolStripMenuItem現在位置からBGMのみ再生.Enabled = false;
-                               this.toolStripMenuItem再生停止.Enabled = false;
-                       }
+                       this.toolStripMenuItem先頭から再生.Enabled = 各GUIは有効;
+                       this.toolStripMenuItem現在位置から再生.Enabled = 各GUIは有効;
+                       this.toolStripMenuItem現在位置からBGMのみ再生.Enabled = 各GUIは有効;
+                       this.toolStripMenuItem再生停止.Enabled = 各GUIは有効;
                }
                protected void ConfigのRecentUsedFilesをファイルメニューへ追加する()
                {
@@ -1495,6 +1609,37 @@ namespace SSTFEditor
                {
                        this.toolStripLabel音量.Text = ( this.dic音量ラベル.ContainsKey( this.現在のチップ音量 ) ) ? this.dic音量ラベル[ this.現在のチップ音量 ] : @"???";
                }
+               protected void SSTサービスが起動していれば取得する()
+               {
+                       // ファクトリが未生成なら生成する。
+                       if( null == this.SSTファクトリ )
+                       {
+                               this.SSTファクトリ = new ChannelFactory<SST.IStrokeStyleTService>( new NetNamedPipeBinding( NetNamedPipeSecurityMode.None ) );
+                               this.SSTサービスチャンネル = null;
+                               this.SSTサービス = null;
+                       }
+
+                       // サービスが未取得なら取得する。
+                       if( ( null == this.SSTサービス ) || ( null == this.SSTサービスチャンネル ) )       // サービスとチャンネルは同じオブジェクト。
+                       {
+                               try
+                               {
+                                       this.SSTサービス = this.SSTファクトリ.CreateChannel( new EndpointAddress( "net.pipe://localhost/StrokeStyleT/Viewer" ) );
+                                       this.SSTサービスチャンネル = this.SSTサービス as IClientChannel;
+                                       this.SSTサービスチャンネル.Open();
+                                       this.SSTサービスチャンネル.Closed += ( sender, e ) => {
+                                               this.SSTサービスチャンネル = null;
+                                               this.SSTサービス = null;
+                                       };
+                               }
+                               catch
+                               {
+                                       // 取得失敗。
+                                       this.SSTサービス = null;
+                                       this.SSTサービスチャンネル = null;
+                               }
+                       }
+               }
 
                // GUIイベントメソッド