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拡張
{ 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.チップ種別.背景動画, "" },
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;
// 最近使ったファイル一覧を更新する。
this.ConfigのRecentUsedFilesをファイルメニューへ追加する();
-
+
// その他の初期化。
this.Act新規作成する();
this.Actガイド間隔を変更する( 16 ); // 初期は 1/16 間隔。
// 完了。
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.選択モード );
}
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再生を停止する()
{
( 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オプションを設定する()
{
this.Config.MaxOfUsedRecentFiles = (int) dialog.numericUpDown最近使用したファイルの最大表示個数.Value;
this.Config.ViewerPath = dialog.textBoxViewerPath.Text;
+ this.Viewer再生関連GUIのEnabledを設定する();
+
// [ファイル] メニューを修正。
this.ConfigのRecentUsedFilesをファイルメニューへ追加する();
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; // 以前の状態によらず、確実に更新するようにする。
}
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をファイルメニューへ追加する()
{
{
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イベントメソッド