// 生成と終了 /// <summary> /// 指定した画像ファイルから描画可能画像を作成する。 /// </summary> public 描画可能画像(VariablePath 画像ファイルパス, BindFlags bindFlags = BindFlags.ShaderResource) : base(画像ファイルパス, bindFlags | BindFlags.RenderTarget) { //using var _ = new LogBlock( Log.現在のメソッド名 ); this._Bitmap = this._作成したテクスチャとデータを共有するビットマップターゲットを作成する(); }
/// <summary> /// 指定した画像ファイルから画像を作成する。 /// </summary> public 画像(VariablePath 画像ファイルパス, BindFlags bindFlags = BindFlags.ShaderResource) : base( Global.GraphicResources.D3D11Device1, Folder.カルチャを考慮した絶対パスを返す(画像ファイルパス.数なしパス), bindFlags) { }
public ScoreDBRecord(VariablePath 譜面ファイルの絶対パス, ユーザ設定 userConfig) { // 譜面を読み込む。(ノーツ数やBPMを算出するため、ヘッダだけじゃなくすべてを読み込む。) var 譜面 = SSTF.スコア.ファイルから生成する(譜面ファイルの絶対パス.数なしパス); var ノーツ数マップ = _ノーツ数を算出して返す(譜面, userConfig); var(最小BPM, 最大BPM) = _最小最大BPMを調べて返す(譜面); // 読み込んだ譜面から反映する。 this.ScorePath = 譜面ファイルの絶対パス.数なしパス; this.Title = 譜面.曲名; this.LastWriteTime = File.GetLastWriteTime(this.ScorePath).ToString("G"); this.Level = 譜面.難易度; this.MinBPM = 最小BPM; this.MaxBPM = 最大BPM; this.TotalNotes_LeftCymbal = ノーツ数マップ[演奏.表示レーン種別.LeftCymbal]; this.TotalNotes_HiHat = ノーツ数マップ[演奏.表示レーン種別.HiHat]; this.TotalNotes_LeftPedal = ノーツ数マップ[演奏.表示レーン種別.Foot]; this.TotalNotes_Snare = ノーツ数マップ[演奏.表示レーン種別.Snare]; this.TotalNotes_Bass = ノーツ数マップ[演奏.表示レーン種別.Bass]; this.TotalNotes_HighTom = ノーツ数マップ[演奏.表示レーン種別.Tom1]; this.TotalNotes_LowTom = ノーツ数マップ[演奏.表示レーン種別.Tom2]; this.TotalNotes_FloorTom = ノーツ数マップ[演奏.表示レーン種別.Tom3]; this.TotalNotes_RightCymbal = ノーツ数マップ[演奏.表示レーン種別.RightCymbal]; this.PreImage = string.IsNullOrEmpty(譜面.プレビュー画像ファイル名) ? "" : 譜面.プレビュー画像ファイル名; this.Artist = 譜面.アーティスト名; this.PreSound = string.IsNullOrEmpty(譜面.プレビュー音声ファイル名) ? "" : 譜面.プレビュー音声ファイル名; this.BGMAdjust = 0; }
public フォント画像D2D(VariablePath 文字盤の画像ファイルパス, VariablePath 文字盤の矩形リストファイルパス, float 文字幅補正dpx = 0f, float 透明度 = 1f) : base( Global.GraphicResources.WicImagingFactory2, Global.GraphicResources.既定のD2D1DeviceContext, 文字盤の画像ファイルパス, 文字盤の矩形リストファイルパス, 文字幅補正dpx, 透明度) { }
/// <summary> /// 指定されたシステムサウンドを生成する。 /// </summary> /// <remarks> /// 既に生成済みのサウンドは再生成しない。 /// </remarks> public void 読み込む(システムサウンド種別 type) { // 既に生成済みなら何もしない。 if (this._種別toサウンドマップ.ContainsKey(type)) { return; } // ファイル名は、<Alias>.ogg とする。 var path = new VariablePath($@"$(SystemSounds)\{type.GetAlias()}.ogg"); // ファイルがないなら無視。 if (!File.Exists(path.数なしパス)) { Log.ERROR($"システムサウンドファイルが見つかりません。スキップします。[{path.変数付きパス}]"); return; } if (this._SoundDevice.TryGetTarget(out var device)) { // サンプルソースを読み込む。 var sampleSource = SampleSourceFactory.Create(device, path.数なしパス, 1.0) ?? // システムサウンドは常に再生速度 = 1.0 throw new Exception($"システムサウンドの読み込みに失敗しました。[{path.変数付きパス}]"); // サウンドを生成してマップに登録。 var sound = new PolySound(device, sampleSource, 2); this._種別toサウンドマップ[type] = (sampleSource, sound); } Log.Info($"システムサウンドを読み込みました。[{path.変数付きパス}]"); }
// 生成と終了 public 描画可能画像D2D(VariablePath 画像ファイルパス) : base(画像ファイルパス, new BitmapProperties1 { BitmapOptions = BitmapOptions.Target }) { //using var _ = new LogBlock( Log.現在のメソッド名 ); }
// 登録、停止、再開 /// <summary> /// 指定したAVI番号に動画ファイルを登録する。 /// </summary> public void 登録する(int AVI番号, VariablePath 動画ファイルの絶対パス, double 再生速度 = 1.0) { using var _ = new LogBlock(Log.現在のメソッド名); if (0 > AVI番号 || 36 * 36 <= AVI番号) { throw new ArgumentOutOfRangeException($"AVI番号が範囲(0~1295)を超えています。[{AVI番号}]"); } if (!(File.Exists(動画ファイルの絶対パス.数なしパス))) { Log.WARNING($"動画ファイルが存在しません。[{動画ファイルの絶対パス.変数付きパス}]"); return; } // すでに登録済みなら解放する。 if (this._動画リスト.ContainsKey(AVI番号)) { this._動画リスト[AVI番号].Dispose(); } // 新しいVideoを生成して登録する。 this._動画リスト[AVI番号] = new Video( Global.GraphicResources.MFDXGIDeviceManager, Global.GraphicResources.既定のD2D1DeviceContext, 動画ファイルの絶対パス, 再生速度); }
// 生成と終了 /// <summary> /// コンストラクタ。 /// 指定された画像ファイルと矩形リストyamlファイルを使って、フォント画像を生成する。 /// </summary> public フォント画像(VariablePath 文字盤の画像ファイルパス, VariablePath 文字盤設定ファイルパス, float 文字幅補正dpx = 0f, float 透明度 = 1f) { this._文字盤 = new 画像(文字盤の画像ファイルパス); this._矩形リスト = new 矩形リスト(文字盤設定ファイルパス); this.文字幅補正dpx = 文字幅補正dpx; this.透明度 = 透明度; }
public 画像D2D(VariablePath 画像ファイルパス, BitmapProperties1?bitmapProperties1 = null) : base( Global.GraphicResources.WicImagingFactory2, Global.GraphicResources.既定のD2D1DeviceContext, Folder.カルチャを考慮した絶対パスを返す(画像ファイルパス.数なしパス), bitmapProperties1) { }
/// <summary> /// 指定した画像ファイルから描画可能画像を作成する。 /// </summary> public 描画可能画像(VariablePath 画像ファイルパス, BindFlags bindFlags = BindFlags.ShaderResource | BindFlags.RenderTarget) : base( Global.GraphicResources.D3D11Device1, Global.GraphicResources.既定のD2D1DeviceContext, Folder.カルチャを考慮した絶対パスを返す(画像ファイルパス.数なしパス), bindFlags) { }
/// <summary> /// コンストラクタ。 /// 指定されたファイルを指定されたフォーマットでデコードし、内部にオンメモリで保管する。 /// </summary> public MediaFoundationOnMemoryWaveSource(VariablePath ファイルパス, CSCore.WaveFormat deviceFormat) : base(ファイルパス, deviceFormat) { // 読み込み&デコード完了まで待機。 if (!(this._デコードタスク.Wait(60 * 1000))) { throw new TimeoutException($"デコードタスクがタイムアウトしました。[{ファイルパス.変数付きパス}]"); } }
public void Open(VariablePath DBファイルパス) { // DBへ接続し、開く。(DBファイルが存在しない場合は自動的に生成される。) var db接続文字列 = new SqliteConnectionStringBuilder() { DataSource = DBファイルパス.数なしパス }.ToString(); this.Connection = new SqliteConnection(db接続文字列); this.Connection.Open(); }
// ローカル /// <summary> /// YAMLファイルを最新版にバージョンアップする。 /// </summary> private static void _Yamlを最新版にバージョンアップする(VariablePath path) { int version = 0; #region " YAML階層のルートノード 'Version' を検索し、バージョン値を取得する。" //---------------- { var yamlText = File.ReadAllText(path.数なしパス); var yamlStream = new YamlStream(); yamlStream.Load(new StringReader(yamlText)); var rootMapping = (YamlMappingNode)yamlStream.Documents[0].RootNode; var versionNode = new YamlScalarNode("Version"); if (rootMapping.Children.ContainsKey(versionNode)) { var versionValue = rootMapping.Children[versionNode] as YamlScalarNode; version = int.Parse(versionValue?.Value ?? "1"); // 取得 } } //---------------- #endregion while (version < UserConfig.VERSION) { switch (version) { case 14: #region " 14 → 最新版 " //---------------- { // 変更がないので、全メンバを代入でコピーするよりも、v14をシリアライズ → v15でデシリアライズ するほうを選ぶ。 var v14yamlText = File.ReadAllText(path.数なしパス); var v14deserializer = new Deserializer(); var v14config = v14deserializer.Deserialize <old.UserConfig.v014_UserConfig>(v14yamlText); var v14serializer = new SerializerBuilder() .WithTypeInspector(inner => new CommentGatheringTypeInspector(inner)) .WithEmissionPhaseObjectGraphVisitor(args => new CommentsObjectGraphVisitor(args.InnerVisitor)) .EmitDefaults() .Build(); var v14yaml = v14serializer.Serialize(v14config); var v15deserializer = new Deserializer(); var v15config = v15deserializer.Deserialize <UserConfig>(v14yamlText); // 変更なし v15config.Version = UserConfig.VERSION; v15config.保存する(); version = v15config.Version; } //---------------- #endregion break; } } }
public static UserConfig 読み込むFromPath(VariablePath path) { using var _ = new LogBlock(Log.現在のメソッド名); var yamlText = File.ReadAllText(path.数なしパス); var deserializer = new Deserializer(); var config = deserializer.Deserialize <UserConfig>(yamlText); if (VERSION != config.Version) { throw new Exception("バージョンが違います。"); } return(config); }
public Video(VariablePath ファイルパス, double 再生速度 = 1.0) : this() { using var _ = new LogBlock(Log.現在のメソッド名); this.再生速度 = 再生速度; try { this._VideoSource = new MediaFoundationFileVideoSource(ファイルパス, 再生速度); } catch { Log.WARNING($"動画のデコードに失敗しました。[{ファイルパス.変数付きパス}"); this._VideoSource = null; return; } this._ファイルから生成した = true; }
public void 矩形リストをyamlファイルから読み込む(VariablePath yamlファイルパス) { // yaml ファイルを読み込む。 var yamlText = File.ReadAllText(yamlファイルパス.数なしパス); var deserializer = new YamlDotNet.Serialization.Deserializer(); var yaml = deserializer.Deserialize <YAMLマップ>(yamlText); // 内容から矩形リストを作成。 foreach (var kvp in yaml.RectangleList) { if (4 == kvp.Value.Length) { this.文字列to矩形[kvp.Key] = new RectangleF(kvp.Value[0], kvp.Value[1], kvp.Value[2], kvp.Value[3]); } else { Log.ERROR($"矩形リストの書式が不正です。[{yamlファイルパス.変数付きパス}]"); } } }
// 生成と終了 /// <summary> /// 指定した画像ファイルから画像を作成する。 /// </summary> public 画像(VariablePath 画像ファイルパス, BindFlags bindFlags = BindFlags.ShaderResource) { //using var _ = new LogBlock( Log.現在のメソッド名 ); #region " 条件チェック " //---------------- if (string.IsNullOrEmpty(画像ファイルパス.数なしパス)) { Log.ERROR($"画像ファイルパスの指定がありません。"); return; } if (!File.Exists(画像ファイルパス.数なしパス)) { Log.ERROR($"画像ファイルが存在しません。[{画像ファイルパス.変数付きパス}]"); return; } //---------------- #endregion this._CreateShaderResourceViewFromFile(Global.D3D11Device1, bindFlags, 画像ファイルパス); }
// 登録、発声停止、再開 /// <summary> /// 指定したWAV番号にサウンドファイルを登録する。 /// </summary> /// <remarks> /// サウンドの生成に失敗した場合には登録を行わない。 /// </remarks> /// <param name="wav番号">登録する番号。0~1295。すでに登録されている場合は上書き更新される。</param> /// <param name="サウンドファイル">登録するサウンドファイルのパス。</param> public void 登録する(int wav番号, VariablePath サウンドファイル, bool 多重再生する, bool BGMである) { using var _ = new LogBlock(Log.現在のメソッド名); if ((0 > wav番号) || (36 * 36 <= wav番号)) { throw new ArgumentOutOfRangeException($"WAV番号が範囲(0~1295)を超えています。[{wav番号}]"); } if (!(File.Exists(サウンドファイル.数なしパス))) { Log.WARNING($"サウンドファイルが存在しません。[{サウンドファイル.変数付きパス}]"); return; } // 先に ISampleSource を生成する。 var sampleSource = Global.App.WAVキャッシュ.作成する(サウンドファイル); if (sampleSource is null) { Log.WARNING($"サウンドのデコードに失敗しました。[{サウンドファイル.変数付きパス}"); return; } // サウンドを登録する。 if (this._WAV情報リスト.ContainsKey(wav番号)) { this._WAV情報リスト[wav番号].Dispose(); // すでに登録済みなら先に解放する。 } int 多重度 = (多重再生する) ? this._既定の多重度 : 1; this._WAV情報リスト[wav番号] = new WAV情報(wav番号, 多重度, BGMである); this._WAV情報リスト[wav番号].サウンドを生成する(Global.App.サウンドデバイス, sampleSource); Log.Info($"サウンドを読み込みました。[{サウンドファイル.変数付きパス}]"); }
// 登録、停止、再開 /// <summary> /// 指定したAVI番号に動画ファイルを登録する。 /// </summary> public void 登録する(int AVI番号, VariablePath 動画ファイルの絶対パス, double 再生速度 = 1.0) { if (0 > AVI番号 || 36 * 36 <= AVI番号) { throw new ArgumentOutOfRangeException($"AVI番号が範囲(0~1295)を超えています。[{AVI番号}]"); } if (!(File.Exists(動画ファイルの絶対パス.数なしパス))) { Log.WARNING($"動画ファイルが存在しません。[{動画ファイルの絶対パス.変数付きパス}]"); return; } // すでに登録済みなら解放する。 if (this._動画リスト.ContainsKey(AVI番号)) { this._動画リスト[AVI番号].Dispose(); } // 新しいVideoを生成して登録する。 this._動画リスト[AVI番号] = new Video(動画ファイルの絶対パス, 再生速度); }
/// <summary> /// 指定されたフォルダ内に配置可能な、新しいログファイル名を生成して返す。 /// </summary> /// <param name="ログフォルダパス">ログファイルを配置するフォルダのパス。</param> /// <param name="ログファイルの接頭辞">ログファイル名に付与する接頭辞。</param> /// <param name="最大保存期間">フォルダ内に保存しておく最大の期間。</param> /// <returns>生成されたログファイル名。パス付き。</returns> /// <remarks> /// ログファイル名は、現在時刻をベースに名付けられる。 /// 同時に、フォルダ内に存在するすべてのファイルの更新時刻をチェックし、最大保存期間を超える古いファイルは、自動的に削除する。 /// </remarks> public static string ログファイル名を生成する(VariablePath ログフォルダパス, string ログファイルの接頭辞, TimeSpan 最大保存期間) { var 現在の日時 = DateTime.Now; if (Directory.Exists(ログフォルダパス.数なしパス)) { // (A) フォルダがある場合 → 最大保存期間を超える古いファイルを削除する。 var 削除対象ファイルs = Directory.GetFiles(ログフォルダパス.数なしパス).Where( (file) => (File.GetLastWriteTime(file) < (現在の日時 - 最大保存期間))); foreach (var path in 削除対象ファイルs) { File.Delete(path); } } else { // (B) フォルダがない場合 → 作成する。 Directory.CreateDirectory(ログフォルダパス.数なしパス); } // 現在の時刻をもとに、新しいログファイル名を生成して返す。 return(Path.Combine(ログフォルダパス.数なしパス, $"{ログファイルの接頭辞}{現在の日時.ToString( "yyyyMMdd-HHmmssffff" )}.txt")); }
public static void 最新版にバージョンアップする() { using var _ = new LogBlock(Log.現在のメソッド名); var path = new VariablePath(@"$(AppData)\Configuration.yaml"); int version = 0; if (!File.Exists(path.数なしパス)) { return; } #region " YAML階層のルートノード 'Version' を検索し、バージョン値を取得する。" //---------------- { var yamlText = File.ReadAllText(path.数なしパス); var yamlStream = new YamlStream(); yamlStream.Load(new StringReader(yamlText)); var rootMapping = (YamlMappingNode)yamlStream.Documents[0].RootNode; var versionNode = new YamlScalarNode("Version"); if (rootMapping.Children.ContainsKey(versionNode)) { var versionValue = rootMapping.Children[versionNode] as YamlScalarNode; version = int.Parse(versionValue?.Value ?? "1"); // 取得 } } //---------------- #endregion while (version < SystemConfig.VERSION) { switch (version) { case 1: { break; // 存在しない } case 2: { #region " 2 → 3 " //---------------- var v2 = old.SystemConfig.v002_システム設定.読み込む(path); var v3 = new old.SystemConfig.v003_システム設定(v2); v3.保存する(path); version = v3.Version; break; //---------------- #endregion } case 3: { #region " 3 → 4 " //---------------- var v3 = old.SystemConfig.v003_システム設定.読み込む(path); var v4 = new old.SystemConfig.v004_SystemConfig(v3); v4.保存する(); version = v4.Version; break; //---------------- #endregion } case 4: { #region " 4 → 5 " //---------------- var v4 = old.SystemConfig.v004_SystemConfig.読み込む(path); var v5 = new old.SystemConfig.v005_SystemConfig(v4); v5.保存する(); version = v5.Version; break; //---------------- #endregion } case 5: { #region " 5 → 6 " //---------------- var v5 = old.SystemConfig.v005_SystemConfig.読み込む(path); var v6 = new old.SystemConfig.v006_SystemConfig(v5); v6.保存する(); version = v6.Version; break; //---------------- #endregion } case 6: { #region " 6 → 最新版 " //---------------- var v6 = old.SystemConfig.v006_SystemConfig.読み込む(path); var v7 = new SystemConfig(v6); v7.保存する(); version = v7.Version; break; //---------------- #endregion } } } }
public void すべて生成する(SoundDevice device) { using var _ = new LogBlock(Log.現在のメソッド名); this._すべて解放する(); lock (this._Sound利用権) { // SSTの既定のサウンドを、subChipId = 0 としてプリセット登録する。 var soundList = new List <(SSTF.チップ種別 type, VariablePath path)>() { (SSTF.チップ種別.LeftCrash, @"$(DrumSounds)\LeftCrash.wav"), (SSTF.チップ種別.Ride, @"$(DrumSounds)\Ride.wav"), (SSTF.チップ種別.Ride_Cup, @"$(DrumSounds)\RideCup.wav"), (SSTF.チップ種別.China, @"$(DrumSounds)\China.wav"), (SSTF.チップ種別.Splash, @"$(DrumSounds)\Splash.wav"), (SSTF.チップ種別.HiHat_Open, @"$(DrumSounds)\HiHatOpen.wav"), (SSTF.チップ種別.HiHat_HalfOpen, @"$(DrumSounds)\HiHatHalfOpen.wav"), (SSTF.チップ種別.HiHat_Close, @"$(DrumSounds)\HiHatClose.wav"), (SSTF.チップ種別.HiHat_Foot, @"$(DrumSounds)\HiHatFoot.wav"), (SSTF.チップ種別.Snare, @"$(DrumSounds)\Snare.wav"), (SSTF.チップ種別.Snare_OpenRim, @"$(DrumSounds)\SnareOpenRim.wav"), (SSTF.チップ種別.Snare_ClosedRim, @"$(DrumSounds)\SnareClosedRim.wav"), (SSTF.チップ種別.Snare_Ghost, @"$(DrumSounds)\SnareGhost.wav"), (SSTF.チップ種別.Bass, @"$(DrumSounds)\Bass.wav"), (SSTF.チップ種別.Tom1, @"$(DrumSounds)\Tom1.wav"), (SSTF.チップ種別.Tom1_Rim, @"$(DrumSounds)\Tom1Rim.wav"), (SSTF.チップ種別.Tom2, @"$(DrumSounds)\Tom2.wav"), (SSTF.チップ種別.Tom2_Rim, @"$(DrumSounds)\Tom2Rim.wav"), (SSTF.チップ種別.Tom3, @"$(DrumSounds)\Tom3.wav"), (SSTF.チップ種別.Tom3_Rim, @"$(DrumSounds)\Tom3Rim.wav"), (SSTF.チップ種別.RightCrash, @"$(DrumSounds)\RightCrash.wav"), (SSTF.チップ種別.LeftCymbal_Mute, @"$(DrumSounds)\LeftCymbalMute.wav"), (SSTF.チップ種別.RightCymbal_Mute, @"$(DrumSounds)\RightCymbalMute.wav"), }; foreach (var sound in soundList) { var path = new VariablePath(Folder.カルチャを考慮した絶対パスを返す(sound.path.数なしパス)); if (!File.Exists(sound.path.数なしパス)) { Log.ERROR($"サウンドファイルが存在しません。[{path.変数付きパス}]"); continue; } // サウンドファイルを読み込んでデコードする。 var sampleSource = SampleSourceFactory.Create(device, path.数なしパス, 1.0); // ドラムサウンドは常に 1.0 if (sampleSource is null) { Log.ERROR($"サウンドの生成に失敗しました。[{path.変数付きパス}]"); continue; } // コンテキストを作成する。 var context = new ドラムサウンドコンテキスト(sampleSource, ドラムサウンド.多重度); // 多重度分のサウンドを生成する。 for (int i = 0; i < context.Sounds.Length; i++) { context.Sounds[i] = new Sound(device, context.SampleSource); } // コンテキストを辞書に追加する。 if (this._チップtoコンテキスト.ContainsKey((sound.type, 0))) { // すでに辞書に存在してるなら、解放してから削除する。 this._チップtoコンテキスト[(sound.type, 0)].Dispose();
/// <summary> /// 指定した画像ファイルから描画可能画像を作成する。 /// </summary> public 描画可能画像(VariablePath 画像ファイルパス, BindFlags bindFlags = BindFlags.ShaderResource | BindFlags.RenderTarget) : base(Global.GraphicResources.D3D11Device1, Global.GraphicResources.既定のD2D1DeviceContext, 画像ファイルパス, bindFlags) { }
// 生成と終了 public MediaFoundationFileVideoSource(VariablePath ファイルパス, double 再生速度 = 1.0) { using var _ = new LogBlock(Log.現在のメソッド名); this.再生速度 = Math.Max(0.01, Math.Min(10.0, 再生速度)); #region " フレームキューを生成。" //---------------- // キューサイズは3フレームとする。 this._FrameQueue = new BlockingQueue <VideoFrame>(3); //---------------- #endregion #region " ファイルから SourceReaderEx を生成する。" //---------------- using (var ビデオ属性 = new MediaAttributes()) { // DXVAに対応しているGPUの場合には、それをデコードに利用するよう指定する。 ビデオ属性.Set(SourceReaderAttributeKeys.D3DManager, Global.MFDXGIDeviceManager); // 追加のビデオプロセッシングを有効にする。 ビデオ属性.Set(SourceReaderAttributeKeys.EnableAdvancedVideoProcessing, true); // 真偽値が bool だったり // 追加のビデオプロセッシングを有効にしたら、こちらは無効に。 ビデオ属性.Set(SinkWriterAttributeKeys.ReadwriteDisableConverters, 0); // int だったり // 属性を使って、SourceReaderEx を生成。 using var sourceReader = new SourceReader(ファイルパス.数なしパス, ビデオ属性); // パスは URI 扱い this._SourceReaderEx = sourceReader.QueryInterface <SourceReaderEx>(); } // 最初のビデオストリームだけを選択。 this._SourceReaderEx.SetStreamSelection(SourceReaderIndex.AllStreams, false); this._SourceReaderEx.SetStreamSelection(SourceReaderIndex.FirstVideoStream, true); //---------------- #endregion #region " ビデオの長さを取得する。" //---------------- this.総演奏時間sec = (long)((this._SourceReaderEx.GetPresentationAttribute(SourceReaderIndex.MediaSource, PresentationDescriptionAttributeKeys.Duration) / this.再生速度) / 10_000_000.0); //---------------- #endregion #region " デコーダを選択し、完全メディアタイプを取得する。" //---------------- // 部分メディアタイプを設定する。 using (var 部分MediaType = new MediaType()) { // フォーマットは ARGB32 で固定とする。(SourceReaderEx を使わない場合、H264 では ARGB32 が選べないので注意。) 部分MediaType.Set(MediaTypeAttributeKeys.MajorType, MediaTypeGuids.Video); 部分MediaType.Set(MediaTypeAttributeKeys.Subtype, VideoFormatGuids.Argb32); // 部分メディアタイプを SourceReaderEx にセットする。SourceReaderEx は、必要なデコーダをロードするだろう。 this._SourceReaderEx.SetCurrentMediaType(SourceReaderIndex.FirstVideoStream, 部分MediaType); } // 完成されたメディアタイプを取得する。 this._MediaType = this._SourceReaderEx.GetCurrentMediaType(SourceReaderIndex.FirstVideoStream); //---------------- #endregion #region " ビデオのフレームサイズを取得する。(動画の途中でのサイズ変更は考慮しない。)" //---------------- long packedFrameSize = this._MediaType.Get(MediaTypeAttributeKeys.FrameSize); this.フレームサイズ = new Size2F((packedFrameSize >> 32) & 0xFFFFFFFF, (packedFrameSize) & 0xFFFFFFFF); //---------------- #endregion this._デコードキャンセル = new CancellationTokenSource(); this._デコード起動完了通知 = new ManualResetEventSlim(false); this._一時停止解除通知 = new ManualResetEventSlim(true); }
public SQLiteDB(VariablePath DBファイルパス) { this.Open(DBファイルパス); }
/// <summary> /// 指定した画像ファイルから画像を作成する。 /// </summary> public 画像(VariablePath 画像ファイルパス, BindFlags bindFlags = BindFlags.ShaderResource) : base(Global.GraphicResources.D3D11Device1, 画像ファイルパス, bindFlags) { }
protected void Bitmapを生成する(VariablePath 画像ファイルパス, BitmapProperties1?bitmapProperties1 = null) { var decoder = (BitmapDecoder)null !; var sourceFrame = (BitmapFrameDecode)null !; var converter = (FormatConverter)null !; try { // 以下、生成に失敗しても例外は発生しない。ただ描画メソッドで表示されなくなるだけ。 #region " 事前チェック。" //----------------- if (string.IsNullOrEmpty(画像ファイルパス.数なしパス)) { Log.ERROR($"画像ファイルパスが null または空文字列です。[{画像ファイルパス.変数付きパス}]"); return; } if (!File.Exists(画像ファイルパス.数なしパス)) { Log.ERROR($"画像ファイルが存在しません。[{画像ファイルパス.変数付きパス}]"); return; } //----------------- #endregion #region " 画像ファイルに対応できるデコーダを見つける。" //----------------- try { decoder = new BitmapDecoder( Global.WicImagingFactory2, 画像ファイルパス.数なしパス, NativeFileAccess.Read, DecodeOptions.CacheOnLoad); } catch (SharpDXException e) { Log.ERROR($"画像ファイルに対応するコーデックが見つかりません。(0x{e.HResult:x8})[{画像ファイルパス.変数付きパス}]"); return; } //----------------- #endregion #region " 最初のフレームをデコードし、取得する。" //----------------- try { sourceFrame = decoder.GetFrame(0); } catch (SharpDXException e) { Log.ERROR($"画像ファイルの最初のフレームのデコードに失敗しました。(0x{e.HResult:x8})[{画像ファイルパス.変数付きパス}]"); return; } //----------------- #endregion #region " 32bitPBGRA へのフォーマットコンバータを生成する。" //----------------- try { // WICイメージングファクトリから新しいコンバータを生成。 converter = new FormatConverter(Global.WicImagingFactory2); // コンバータに変換元フレームや変換後フォーマットなどを設定。 converter.Initialize( sourceRef: sourceFrame, dstFormat: SharpDX.WIC.PixelFormat.Format32bppPBGRA, // Premultiplied BGRA dither: BitmapDitherType.None, paletteRef: null, alphaThresholdPercent: 0.0, paletteTranslate: BitmapPaletteType.MedianCut); } catch (SharpDXException e) { Log.ERROR($"32bitPBGRA へのフォーマットコンバータの生成または初期化に失敗しました。(0x{e.HResult:x8})[{画像ファイルパス.変数付きパス}]"); return; } //----------------- #endregion #region " コンバータを使って、フレームを WICビットマップ経由で D2D ビットマップに変換する。" //----------------- try { // WIC ビットマップを D2D ビットマップに変換する。 this.Bitmap?.Dispose(); this.Bitmap = bitmapProperties1 switch { null => Bitmap1.FromWicBitmap(Global.既定のD2D1DeviceContext, converter), _ => Bitmap1.FromWicBitmap(Global.既定のD2D1DeviceContext, converter, bitmapProperties1), }; } catch (SharpDXException e) { Log.ERROR($"Direct2D1.Bitmap1 への変換に失敗しました。(0x{e.HResult:x8})[{画像ファイルパス.変数付きパス}]"); return; } //----------------- #endregion this.サイズ = new Size2F(this.Bitmap.PixelSize.Width, this.Bitmap.PixelSize.Height); } finally { converter?.Dispose(); sourceFrame?.Dispose(); decoder?.Dispose(); } }
// 生成と終了 public 画像D2D(VariablePath 画像ファイルパス, BitmapProperties1?bitmapProperties1 = null) { //using var _ = new LogBlock( Log.現在のメソッド名 ); this.Bitmapを生成する(画像ファイルパス, bitmapProperties1); }
/// <summary> /// 指定されたファイルに対応するデータを(未生成なら)生成し、返す。 /// 生成に失敗したら null。 /// </summary> public T?作成する(VariablePath ファイルパス) { try { if (!File.Exists(ファイルパス.数なしパス)) { Log.ERROR($"ファイルが存在しません。[{ファイルパス.変数付きパス}]"); return(null); // 失敗 } var fileInfo = new FileInfo(ファイルパス.数なしパス); if (this._キャッシュデータリスト.TryGetValue(ファイルパス.数なしパス, out var キャッシュ情報)) // キャッシュにある { if (キャッシュ情報.ファイルの最終更新日時 == fileInfo.LastWriteTime) // ファイルは更新されていない { #region " (A) データがキャッシュに存在していて、ファイルも更新されていない場合 → それを貸与する " //---------------- キャッシュ情報.最終貸与世代 = this.現世代; // 更新 return(キャッシュ情報.生成データ); //---------------- #endregion } else { #region " (B) データがキャッシュに存在しているが、ファイルが更新されている場合 → 再作成して貸与する " //---------------- (キャッシュ情報.生成データ as IDisposable)?.Dispose(); キャッシュ情報.生成データ = this.ファイルからデータを生成する?.Invoke(ファイルパス); if (キャッシュ情報.生成データ is null) { this._キャッシュデータリスト.Remove(ファイルパス.数なしパス); return(null); // 失敗 } キャッシュ情報.ファイルの最終更新日時 = fileInfo.LastWriteTime; キャッシュ情報.最終貸与世代 = 現世代; return(キャッシュ情報.生成データ); //---------------- #endregion } } else { #region " (C) データがキャッシュに存在しない場合 → 新規作成して貸与する " //---------------- var 生成データ = this.ファイルからデータを生成する?.Invoke(ファイルパス); if (生成データ is null) { return(null); // 失敗 } this._キャッシュデータリスト.Add( // キャッシュに追加 ファイルパス.数なしパス, new キャッシュ情報 <T>() { ファイルパス = ファイルパス, ファイルの最終更新日時 = fileInfo.LastWriteTime, 生成データ = 生成データ, 最終貸与世代 = this.現世代, }); return(生成データ); //---------------- #endregion } } catch { return(null); // 例外発生 } }
/// <summary> /// ユーザDBファイルを最新版に更新する。 /// </summary> /// <remarks> /// v012 移行にバージョンアップする場合は、RecordDB.sqlite3 の生成も行う。 /// </remarks> public static void 最新版にバージョンアップする() { using var _ = new LogBlock(Log.現在のメソッド名); var userdbPath = new VariablePath(@"$(AppData)\UserDB.sqlite3"); var userYamls = Directory.EnumerateFiles( path: Folder.フォルダ変数の内容を返す("AppData"), searchPattern: @"User_*.yaml", searchOption: SearchOption.TopDirectoryOnly); if (0 < userYamls.Count()) { #region " (A) User_*.yaml が存在している " //---------------- // それらを最新版にバージョンアップする。 foreach (var userYaml in userYamls) { _Yamlを最新版にバージョンアップする(userYaml); } //---------------- #endregion } else if (File.Exists(userdbPath.数なしパス)) { #region " (B) User_*.yaml が存在せず UserDB.sqlite3 が存在している " //---------------- // Records レコードは、UserDB(v12)からRecordDBに分離された。 // ・UserDB v011 までは、UserDB の Records テーブルに格納されている。RecordDB.Records テーブルのレコードのバージョンは v001~v006(全部同一)。 // ・UserDB v012 以降は、UserDB から独立して、RecordDB.Records テーブルに格納される。Recordsのレコードのバージョンは v007。 var Users = new List <UserConfig>(); int userdb_version; #region " Users テーブルを最新版にして読み込む。" //---------------- using (var userdb = new SQLiteDB(userdbPath.数なしパス)) { userdb_version = (int)userdb.UserVersion; using var idsQuery = new SqliteCommand("SELECT * FROM Users", userdb.Connection); var ids = idsQuery.ExecuteReader(); while (ids.Read()) { Users.Add(new UserConfig(ids)); } } //---------------- #endregion #region " Users テーブルを User_*.yaml に出力する。" //---------------- foreach (var user in Users) { user.保存する(); } //---------------- #endregion #region " RecordDB.sqlite3 がなければ新規作成する。" //---------------- if (!File.Exists(RecordDB.RecordDBPath.数なしパス)) { using var recorddb = new RecordDB(); // ファイルがなければ新規作成される using var cmd = new SqliteCommand($"CREATE TABLE Records { old.RecordDBRecord.v007_RecordDBRecord.ColumnList}", recorddb.Connection); cmd.ExecuteNonQuery(); recorddb.UserVersion = old.RecordDBRecord.v007_RecordDBRecord.VERSION; Log.Info($"RecordDB(v007) を生成しました。"); } //---------------- #endregion if (12 > userdb_version) { #region " UserDB.Rcords テーブルを読み込み、RecordDB.Records テーブルへ出力する。" //---------------- using var userdb = new SQLiteDB(userdbPath.数なしパス); using var recorddb = new RecordDB(); foreach (var user in Users) { using var recordsQuery = new SqliteCommand($"SELECT * FROM Records WHERE Id = @UserId", userdb.Connection); recordsQuery.Parameters.Add(new SqliteParameter("@UserId", user.Id)); var records = recordsQuery.ExecuteReader(); while (records.Read()) { var record = new old.RecordDBRecord.v007_RecordDBRecord(records); // 読み込んで record.InsertTo(recorddb); // 書き込む } } //---------------- #endregion } //---------------- #endregion } else { #region " (C) User_*.yamlも UserDB.sqlite3 も存在しない " //---------------- #region " 新規に User_*.yaml を生成する。" //---------------- var autoPlayer = new UserConfig() { Id = "AutoPlayer", Name = "AutoPlayer", AutoPlay_LeftCymbal = 1, AutoPlay_HiHat = 1, AutoPlay_LeftPedal = 1, AutoPlay_Snare = 1, AutoPlay_Bass = 1, AutoPlay_HighTom = 1, AutoPlay_LowTom = 1, AutoPlay_FloorTom = 1, AutoPlay_RightCymbal = 1, // 他は既定値 }; autoPlayer.保存する(); var guest = new UserConfig() { Id = "Guest", Name = "Guest", // 他は既定値 }; guest.保存する(); //---------------- #endregion #region " 新規に RecordDB.sqlite3 を生成する。" //---------------- var recorddbPath = new VariablePath(@"$(AppData)\RecordDB.sqlite3"); // 念のため if (File.Exists(recorddbPath.数なしパス)) { File.Delete(recorddbPath.数なしパス); } using var recorddb = new SQLiteDB(recorddbPath.数なしパス); // ファイルがなければ新規生成される。 using var cmd = new SqliteCommand(RecordDBRecord.GetCreateTableSQL(), recorddb.Connection); cmd.ExecuteNonQuery(); recorddb.UserVersion = RecordDBRecord.VERSION; Log.Info($"RecordDB を生成しました。"); //---------------- #endregion //---------------- #endregion } }