# 通知設計書 16-WarningBell

## 概要

ターミナルのベル文字（ASCII 0x07、BEL）検出時に発火するイベントベースの通知の設計書である。プロファイル設定に応じて、音声再生、ウィンドウフラッシュ、タスクバーフラッシュの各種フィードバックを提供する。

### 本通知の処理概要

WarningBellは、ターミナル出力に含まれるベル文字（BEL、ASCII 0x07）を検出した際にトリガーされるイベントチェーンである。ControlCore -> TermControl -> TerminalPaneContent -> Tab -> TerminalPageの順にイベントが伝播し、プロファイルのBellStyle設定に応じた複数の通知手段が実行される。

**業務上の目的・背景**：ベル文字はUNIX系OSやWindowsコンソールにおいて、プログラムからユーザーへの注意喚起に使用される標準的なメカニズムである。コマンド完了通知、エラー通知、対話的プロンプトなどで利用される。Windows Terminalでは、プロファイルごとにベル通知の方法（音声、ウィンドウフラッシュ、タスクバーフラッシュ）を柔軟に設定できるようにしている。

**通知の送信タイミング**：Terminal::WarningBell()メソッドが呼ばれた時点でトリガーされる。これはVTパーサーがBEL文字を検出した際に呼び出される。ただし、TermControlレベルで1000ミリ秒のスロットリング（ThrottledFunc）が適用され、短期間の連続ベルは抑制される。

**通知の受信者**：アプリケーションを操作中のユーザー（音声・ウィンドウフラッシュ）。バックグラウンドで実行中の場合はタスクバーフラッシュにより通知される。

**通知内容の概要**：BellStyle設定に応じた以下の通知が実行される。(1) Audible: 音声再生（カスタムサウンドまたはシステムハンドサウンド）、(2) Window: ウィンドウの点滅アニメーション、(3) Taskbar: タスクバーアイコンのフラッシュ。

**期待されるアクション**：ユーザーは通知を受けてターミナルに注意を向ける。自動化されたプロセスの完了通知として利用している場合は、ターミナルへの切り替えが期待される。

## 通知種別

ベル/警告通知（イベントベース、マルチモーダル通知）

## 送信仕様

### 基本情報

| 項目 | 内容 |
|-----|------|
| 送信方式 | 非同期（バックグラウンドスレッドからUIスレッドへディスパッチ） |
| 優先度 | 中 |
| リトライ | 無し |

### 送信先決定ロジック

ベル文字が発生したターミナルが属するペイン・タブに紐づくユーザーに通知される。BellStyleのTaskbarフラグが設定されている場合は、TerminalPageを経由してAppHost（ウィンドウ管理層）にまで伝播する。

## 通知テンプレート

### BellStyle設定

| フラグ | 値 | 説明 |
|-------|-----|------|
| Audible | ビットフラグ | 音声再生 |
| Window | ビットフラグ | ウィンドウの点滅アニメーション |
| Taskbar | ビットフラグ | タスクバーアイコンのフラッシュ |

### 本文テンプレート

```
（本通知はテキストメッセージを含まない。視覚的・聴覚的フィードバックのみ。）
```

### 添付ファイル

該当なし。

## テンプレート変数

| 変数名 | 説明 | データ取得元 | 必須 |
|--------|------|-------------|-----|
| BellStyle | ベル通知の方法 | Profile.BellStyle() | Yes |
| BellSound | カスタムサウンドファイルパス | Profile.BellSound() | No |

## 送信トリガー・条件

### トリガー一覧

| トリガー種別 | トリガーイベント | 送信条件 | 説明 |
|------------|----------------|---------|------|
| VT出力 | BEL文字（0x07）検出 | BellStyleが0以外 | VTパーサーがベル文字を検出 |

### 送信抑止条件

| 条件 | 説明 |
|-----|------|
| BellStyleが0 | プロファイル設定でベル通知が完全に無効の場合 |
| スロットリング期間中 | 前回のベルから1000ミリ秒以内の場合（TermControl側ThrottledFunc） |
| コントロールが閉じている | `_IsClosing()`がtrueの場合 |

## 処理フロー

### 送信フロー

```mermaid
flowchart TD
    A[VTパーサーがBEL文字検出] --> B[Terminal::WarningBell]
    B --> C[_pfnWarningBellコールバック]
    C --> D[ControlCore::_terminalWarningBell]
    D --> E[ControlCore::WarningBell.raise]
    E --> F[TermControl::_coreWarningBell]
    F --> G[ThrottledFunc _playWarningBell.Run]
    G --> H{1000ms以内に既に発火済み?}
    H -->|Yes| I[スキップ]
    H -->|No| J[TermControl::WarningBell.raise]
    J --> K[TerminalPaneContent::_controlWarningBellHandler]
    K --> L{BellStyleが0?}
    L -->|Yes| I
    L -->|No| M{Audibleフラグ?}
    M -->|Yes| N{カスタムサウンド?}
    N -->|Yes| O[MediaPlayerで再生]
    N -->|No| P[PlaySound - SystemHand]
    M -->|No| Q{Windowフラグ?}
    Q -->|Yes| R[BellLightOn - 点滅アニメーション]
    Q -->|No| S{Taskbarフラグ?}
    S -->|Yes| T[BellRequested.raise -> タスクバーフラッシュ]
    S -->|No| I
    R --> S
    P --> Q
    O --> Q
```

## データベース参照・更新仕様

### 参照テーブル一覧

該当なし。

### 更新テーブル一覧

該当なし。

## エラー処理

### エラーケース一覧

| エラー種別 | 発生条件 | 対処方法 |
|----------|---------|---------|
| MediaPlayerの生成失敗 | Windows N SKUでメディア機能が利用不可 | `CATCH_LOG()`でログのみ記録し、音声再生をスキップ |
| サウンドファイルの読み込み失敗 | カスタムサウンドファイルが存在しない場合 | 例外をキャッチし、処理を継続 |

### リトライ仕様

| 項目 | 内容 |
|-----|------|
| リトライ回数 | 0 |
| リトライ間隔 | - |
| リトライ対象エラー | - |

## 配信設定

### レート制限

| 項目 | 内容 |
|-----|------|
| スロットリング間隔 | 1000ミリ秒（TerminalWarningBellInterval） |
| 方式 | Leading edge throttle（最初のイベントは即座に発火、以降は間隔経過後） |

### 配信時間帯

制限なし。

## セキュリティ考慮事項

- ベル文字はターミナルアプリケーションの出力から任意に発生させることができるため、悪意のあるプログラムが大量のベル文字を送信してユーザーに妨害を行う可能性がある。ThrottledFuncによるスロットリングがこのリスクを軽減している。
- カスタムサウンドファイルのパスはプロファイル設定で指定されるため、ユーザーが意図したファイルのみが再生される。

## 備考

- スロットリングはTermControlレベル（`_playWarningBell`）で適用される。ControlCoreレベルではスロットリングされない。
- BellStyleフラグは複数同時に設定可能（例：Audible + Window + Taskbar）。
- カスタムサウンドはProfileの`BellSound()`リストからランダムに1つが選択される。
- ウィンドウ点滅アニメーション（BellLightOn）はComposition APIを使用し、1000ミリ秒のアニメーション期間が設定されている。
- Taskbarフラッシュは、TerminalPaneContent -> Tab -> TerminalPage -> AppHostの順に`BellRequested`イベントで伝播する。

---

## コードリーディングガイド

本通知を理解するために参照すべきファイルと、推奨する読み解き順序を以下に示す。

### 推奨読解順序

#### Step 1: データ構造を理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 1-1 | IPaneContent.idl | `src/cascadia/TerminalApp/IPaneContent.idl` | 行14-17: BellEventArgsランタイムクラス。FlashTaskbarプロパティ |
| 1-2 | TerminalPaneContent.h | `src/cascadia/TerminalApp/TerminalPaneContent.h` | 行14-20: BellEventArgsの実装。FlashTaskbarプロパティのtil::property |
| 1-3 | ControlCore.idl | `src/cascadia/TerminalControl/ControlCore.idl` | 行193: WarningBellイベントの宣言 |
| 1-4 | TermControl.idl | `src/cascadia/TerminalControl/TermControl.idl` | 行70: TermControlのWarningBellイベント宣言 |

**読解のコツ**: WarningBellイベントは引数なし（`TypedEventHandler<Object, Object>`）であり、BellStyleの判定はTerminalPaneContentレベルで行われる。

#### Step 2: エントリーポイントを理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 2-1 | TerminalApi.cpp | `src/cascadia/TerminalCore/TerminalApi.cpp` | 行79-82: `Terminal::WarningBell()`メソッド。`_pfnWarningBell()`コールバックを呼び出す |
| 2-2 | Terminal.hpp | `src/cascadia/TerminalCore/Terminal.hpp` | 行141: WarningBell()メソッド宣言、行224: SetWarningBellCallbackメソッド、行323: _pfnWarningBellメンバ |

#### Step 3: ControlCore/TermControl層を理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 3-1 | ControlCore.cpp | `src/cascadia/TerminalControl/ControlCore.cpp` | 行112-113: コールバック設定。行1582-1587: `_terminalWarningBell`メソッド |
| 3-2 | TermControl.cpp | `src/cascadia/TerminalControl/TermControl.cpp` | 行361-372: ThrottledFunc `_playWarningBell`の定義（1000msスロットリング）。行395: CoreのWarningBellイベント購読。行3697-3699: `_coreWarningBell`ハンドラ |

#### Step 4: TerminalPaneContent層を理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 4-1 | TerminalPaneContent.cpp | `src/cascadia/TerminalApp/TerminalPaneContent.cpp` | 行36: WarningBellイベント購読。行264-297: `_controlWarningBellHandler`メソッド。BellStyle判定、音声再生、ウィンドウフラッシュ、BellRequested.raise |
| 4-2 | TerminalPaneContent.cpp | `src/cascadia/TerminalApp/TerminalPaneContent.cpp` | 行301-327: `_playBellSound`コルーチン。MediaPlayerによるカスタムサウンド再生 |

**主要処理フロー**:
1. **行270**: `static_cast<int>(_profile.BellStyle()) != 0`でBellStyleの有効性を判定
2. **行272**: `WI_IsFlagSet(...BellStyle::Audible)`で音声再生判定
3. **行276-286**: カスタムサウンドまたはシステムサウンドの再生
4. **行289-292**: `WI_IsFlagSet(...BellStyle::Window)`でウィンドウ点滅判定、`BellLightOn()`呼び出し
5. **行295-296**: BellRequested.raiseでTaskbarフラグをBellEventArgsとして伝播

### プログラム呼び出し階層図

```
Terminal::WarningBell (TerminalApi.cpp:79)
    |
    +-- _pfnWarningBell() コールバック
            |
            +-- ControlCore::_terminalWarningBell (ControlCore.cpp:1582)
                    |
                    +-- WarningBell.raise() (ControlCore.cpp:1587)
                            |
                            +-- TermControl::_coreWarningBell (TermControl.cpp:3697)
                                    |
                                    +-- _playWarningBell->Run() [ThrottledFunc 1000ms]
                                            |
                                            +-- TermControl::WarningBell.raise()
                                                    |
                                                    +-- TerminalPaneContent::_controlWarningBellHandler
                                                            |
                                                            +-- [Audible] PlaySound / _playBellSound
                                                            +-- [Window] BellLightOn()
                                                            +-- [Taskbar] BellRequested.raise()
                                                                    |
                                                                    +-- Tab -> TerminalPage -> AppHost
```

### データフロー図

```
[入力]                   [処理]                              [出力]

VT BEL文字(0x07)    Terminal::WarningBell()
        |                |
        v           ControlCore                          [Audible]
     コールバック    _terminalWarningBell()               PlaySound / MediaPlayer
        |                |
        v           TermControl                          [Window]
     イベント       _playWarningBell (スロットリング)     BellLightOn (点滅)
        |                |
        v           TerminalPaneContent                  [Taskbar]
     BellStyle判定   _controlWarningBellHandler()        FlashTaskbar
                    Profile.BellStyle()から判定
```

### 関連ファイル一覧

| ファイル | パス | 種別 | 役割 |
|---------|------|------|------|
| TerminalApi.cpp | `src/cascadia/TerminalCore/TerminalApi.cpp` | ソース | WarningBell()メソッド（エントリーポイント） |
| Terminal.hpp | `src/cascadia/TerminalCore/Terminal.hpp` | ヘッダー | コールバック定義 |
| Terminal.cpp | `src/cascadia/TerminalCore/Terminal.cpp` | ソース | SetWarningBellCallback（行1150） |
| ControlCore.cpp | `src/cascadia/TerminalControl/ControlCore.cpp` | ソース | _terminalWarningBell（行1582） |
| ControlCore.idl | `src/cascadia/TerminalControl/ControlCore.idl` | IDL定義 | WarningBellイベント宣言（行193） |
| TermControl.cpp | `src/cascadia/TerminalControl/TermControl.cpp` | ソース | ThrottledFunc定義・イベント伝播 |
| TermControl.idl | `src/cascadia/TerminalControl/TermControl.idl` | IDL定義 | WarningBellイベント宣言（行70） |
| TerminalPaneContent.cpp | `src/cascadia/TerminalApp/TerminalPaneContent.cpp` | ソース | BellStyle判定・通知実行 |
| TerminalPaneContent.h | `src/cascadia/TerminalApp/TerminalPaneContent.h` | ヘッダー | BellEventArgs定義 |
| IPaneContent.idl | `src/cascadia/TerminalApp/IPaneContent.idl` | IDL定義 | BellEventArgsランタイムクラス |
