Skip to content

fix(v3 web): 内部生成に切り替えると画面が固まるのを直す - #4

Merged
Yothuba3 merged 5 commits into
feature/v3from
fix/v3-generator-panel-freeze
Oct 28, 2026
Merged

Yothuba3 merged 5 commits into
feature/v3from
fix/v3-generator-panel-freeze

Conversation

@Yothuba3

@Yothuba3 Yothuba3 commented Oct 26, 2026 •

Copy link
Copy Markdown
Owner

概要

v3.2.0 / v3.2.1 で、内部生成モードに切り替えると画面が一切更新されなくなる(フリーズしたように見える)不具合を直します。Windows で報告されましたが、原因は Web 側にあり OS 共通です(macOS 実機では未確認)。

同じ原因(Host が null の項目を省く)の取りこぼしを Web 全体でなくし、テストで見つけられるようにしました。あわせて、実機確認で見つけた「TC 欄を 1 回クリックしても数字を打てない」問題と、「ループの開始 TC を終了 TC より後にすると、終了が開始より前のループ設定が残る」問題(Host)も直します。

原因

  • Host は null の項目を JSON から省きます(Protocol.cs の WhenWritingNull)。ループ無しの generator.loopEndTime は null ではなく、キーごと届きません。
  • 生成パネル(generator-panel.tsx)は loopEndTime !== null でループの有無を判定していたため、undefined を「ループ有り」と取り違え、終了 TC の欄を描こうとして TimecodeInput が undefined.split で例外を出していました。
  • Preact は描画中に例外が出ると、それ以降の再描画を一切しません。Host は動き続けて時刻も進みますが、画面だけが止まります。
  • Web のテスト用 fake-host は null を明示で入れていたので、テストでは出ませんでした。

変更

内部生成のフリーズ(0bc7908, 2339809)

  • 届かないときは null(ループ無し)として扱う
  • Host と同じ形(キー無し)の状態で生成パネルを描画するテストを追加
  • tools/tcb3/smoke-windows.ps1 に「内部生成へ切り替えて生成パネルが描かれるか」を追加。音声デバイスが要らないので CI とリリース前の発行物確認でも走ります

null の省略を Web 全体で正しく扱う(5013f70)

  • fake-host(fakeState と送信)も本物の Host と同じく null を省いて渡す。既存の描画テストが本番と同じ形の状態で走り、生成パネルの不具合を戻すと既存のモード切替テストも落ちる
  • protocol.ts の null になりうる項目をすべて ?: X | null にし、型検査で誤用を拾う。bridge-protocol.md にも同じ規則を書いた
  • 同じ原因の不具合をもう 1 件直した: 無音(ピーク 0)の wave は levelDbfs が省かれ、isHostMessage が捨てていた。LTC が止まってもレベル表示が最後の値のまま止まっていた

TC 欄(a06edeb)

  • 各欄 2 桁(maxlength=2)で、埋まった欄を 1 回クリックするとカーソルが立つだけになり、数字を打っても変わらなかった(ダブルクリックで選べば打てた)。欄に入ったら 2 桁を選び、打った数字で置き換える。クリック・Tab・矢印・桁あふれのどれでも同じ
  • クリックは mousedown の既定動作を止めて自分で選ぶ(focus で選ぶだけだと WebKit は mouseup で選択を解く)。右クリックは今までどおり

ループ範囲の検証(a255d16)

  • ループ有りで開始 TC を終了 TC より後に打つと、Host の generator.configure は検証エラーを返すのに、開始 TC(とフレームレート)を書き換えたまま戻していなかった。/state が開始 03:45:11:20・終了 01:03:10:00 のような、範囲として成り立たない組み合わせになる。Web は入力のたびに開始と終了を両方送るので、開始 TC を打つだけで起きる
  • Host は検証を全部済ませてから書き換え、1 つでも弾いたら何も変えない。FPS を 30→24 にしたとき開始 TC のフレームが 24 以上だと、FPS だけ変わって開始 TC が 30fps の値のまま残っていたのも同じ原因で、これも直る
  • 生成パネルは、終了 TC が開始 TC 以前の間は TC を送らず、欄の下に「終了 TC を開始 TC より後にしてください。直すまで TC の変更は反映されません」と出す(打っている途中で一時的にそうなることもあるので、エラーで弾くよりこちらにした)。音量や出力先はそのまま送る。FPS を変えたら、新しいレートにないフレーム番号を丸めてから送る
  • bridge-protocol.md の generator.configure に loopEndTime と「弾いたら何も変えない」を書いた

確認(Windows 11 実機)

  • Web: typecheck、テスト 89 件通過、dist を作り直した
  • Host: TimecodeBridge.Host.Tests 92 件通過。ループ範囲で足した 3 件は a255d16 の前のコードで落ちることを確認
  • v3.2.1 のリリース zip で再現: 内部生成へ切り替えると生成パネルが出ず、生成を始めても画面は「停止中」のまま更新されない(Host の /state /clock は進んでいる)
  • このブランチの Host を実際のマウス・キーボード操作で確認: 内部生成への切り替え(出力無し・ループ無しの初期状態を含む)、再生・ループ・停止・リセット、LTC 受信との往復、キューの追加と編集
  • 無音のレベル表示: 2 つ目の Host から CABLE In 16ch へ LTC を出し、ループバックで受信してから止める。v3.2.1 は 6 秒後も −1.9 dBFS のまま、このブランチは -- dBFS になり波形も平らになる
  • TC 欄: キュー追加のトリガー時間・生成パネルの開始 TC・OFFSET を、1 回クリック → 数字入力、←、↑、Tab で操作し、値が Host に届くことも確認
  • ループ範囲: 開発ビルドで、終了 01:03:10:00 のまま開始 TC を 03:45:11:20 に打つ → Host は変わらず注意書きが出る。終了 TC を直すと両方反映。注意書き中に音量を変えると音量だけ反映。FPS 30→24 でフレーム 29→23。ループを外すと開始 TC が入る。古い組み合わせを /command で直接送ると validation で何も変わらない。2 秒ループの再生で折り返す。この確認は画面操作の許可が下りなかったので、マウスではなく自動操作口(/eval)から入力欄へ input/change イベントを送って行った
  • smoke-windows.ps1 -LoopbackDevice "CABLE In 16ch": SMOKE PASS(LTC ループバック受信、誤り率 0%、LTC の時刻でキュー発火)
  • 追加した smoke の手順は、v3.2.1 のリリース版で NG(SMOKE FAIL)、このブランチで ok

未確認・別件

  • macOS 実機での確認(とくに TC 欄のクリック選択は WebKit 向けの作りで、Windows でしか触っていない)
  • 生成パネルの開始 TC は 1 打鍵ごとに Host へ送るため、機械的な速さで打つと Host の返す古い値で上書きされ桁が抜ける。人の速さ(1 打鍵 0.12 秒)では起きない。以前からの挙動で、この PR では直していない
  • loopEndTime を省いて開始 TC だけ送る呼び出しは、従来どおり開始 TC が終了 TC を越えるとループを外す(Web からは来ない)

🤖 Generated with Claude Code

Yothuba3 and others added 5 commits October 26, 2026 16:03
v3.2.0 から、内部生成へ切り替えると画面が一切更新されなくなっていた
(Host は動き続け、時刻も進んでいる)。

Host は null の項目を JSON から省く(WhenWritingNull)ので、ループ無しの
generator.loopEndTime は null ではなくキーごと届かない。生成パネルは
`!== null` で判定していたため undefined をループ有りと取り違え、終了 TC の
欄を描こうとして TimecodeInput が undefined.split で例外を出していた。
Preact は描画中の例外でそれ以降の再描画をしなくなるので、画面全体が止まる。
Web の fake-host は null を明示で入れていたのでテストでは出なかった。

- 届かないときは null(ループ無し)として扱う
- protocol.ts の型を省略可能にし、同じ取り違えを型検査で止める
- Host と同じ形(キー無し)の状態で描画するテストを足す
- bridge-protocol.md に loopEndTime を書き足す
- dist を作り直した

OS 共通の不具合(macOS 実機では未確認)。

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
v3.2.0〜v3.2.1 は内部生成へ切り替えると画面が固まったが、smoke-windows.ps1 は
内部生成の画面を一度も開いていなかったので、CI とリリース前の確認を通っていた。
音声デバイスの要らない手順なので CI(release-v3.yml の発行物の確認)でも走る。

v3.2.1 のリリース版で NG(SMOKE FAIL)、修正後で ok になることを確かめた。

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Host は null の項目を JSON からキーごと省く(WhenWritingNull)。Web の型は
`X | null` で、偽 Host は null を明示で入れていたため、本番でだけ undefined
が届いて壊れる箇所をテストで見つけられなかった(v3.2.1 の内部生成フリーズ)。

- 偽 Host(fakeState と送信)も本物と同じく null を省いて渡す。既存の描画
  テストが本番と同じ形の状態で走り、生成パネルの不具合を戻すと落ちる
- protocol.ts の null になりうる項目をすべて `?: X | null` にし、型検査で
  誤用を拾えるようにした。bridge-protocol.md にも同じ規則を書いた
- 無音(ピーク 0)の wave は levelDbfs が省かれ、isHostMessage が捨てていた。
  信号が止まってもレベル表示が最後の値(例 −1.9 dBFS)のまま止まっていた
  のを、-- dBFS と平らな波形に戻るようにした

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
TC 欄は各欄 2 桁(maxlength=2)で、埋まった欄をクリックするとカーソルが
立つだけになり、数字を打っても何も変わらなかった(ダブルクリックで選んで
からなら打てた)。欄に入ったら 2 桁を選び、打った数字で置き換える。
クリック・Tab・矢印・桁あふれのどれで入っても同じ。

クリックは mousedown の既定動作を止めて自分で選ぶ。focus で選ぶだけだと
WebKit(macOS)は続く mouseup で選択を解くため。右クリックは今までどおり。

Windows 実機で、キュー追加ダイアログのトリガー時間・生成パネルの開始 TC・
OFFSET を、マウスとキーボードで操作して確かめた。

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
内部生成でループを入れたまま開始 TC を終了 TC より後に打つと、Host の
generator.configure は検証エラーを返すのに、開始 TC(とフレームレート)を
書き換えたまま戻していなかった。開始 03:45:11:20・終了 01:03:10:00 のような
範囲として成り立たない設定が残る。Web は入力のたびに開始と終了を両方送るので、
開始 TC を打つだけで起きる。

Host は検証を全部済ませてから書き換え、1 つでも弾いたら何も変えない。
FPS を 30→24 にしたとき開始 TC のフレームが 24 以上だと、FPS だけ変わり
開始 TC が 30fps の値のまま残っていたのも、同じ原因で直る。

生成パネルは、終了 TC が開始 TC 以前の間は TC を送らず(打っている途中で
一時的にそうなることもある)、欄の下に反映していないことを出す。音量や
出力先はそのまま送る。FPS を変えたら、新しいレートにないフレーム番号を
丸めてから送る。

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@Yothuba3
Yothuba3 merged commit 12daeb7 into feature/v3 Oct 28, 2026
1 check passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant