@@ -83,6 +83,8 @@ pub struct LiveSessionManager {
8383 pause : crate :: capture:: audio_loopback:: SessionPause ,
8484 /// P3:预备会话(引擎预热——选窗口阶段后台加载;start 交接复用)
8585 prepared : Arc < Mutex < Option < PreparedSession > > > ,
86+ /// v0.7.2(REQ-151):会话信息聚合(面板数据源——屏幕 worker 写入,事件/命令读取)
87+ session_info : crate :: session_info:: SessionInfoCollector ,
8688}
8789
8890impl Default for LiveSessionManager {
@@ -99,6 +101,7 @@ impl Clone for LiveSessionManager {
99101 latest_frame : self . latest_frame . clone ( ) ,
100102 pause : self . pause . clone ( ) ,
101103 prepared : self . prepared . clone ( ) ,
104+ session_info : self . session_info . clone ( ) ,
102105 }
103106 }
104107}
@@ -111,6 +114,7 @@ impl LiveSessionManager {
111114 latest_frame : Arc :: new ( Mutex :: new ( None ) ) ,
112115 pause : Default :: default ( ) ,
113116 prepared : Arc :: new ( Mutex :: new ( None ) ) ,
117+ session_info : crate :: session_info:: SessionInfoCollector :: new ( ) ,
114118 }
115119 }
116120
@@ -183,6 +187,10 @@ impl LiveSessionManager {
183187 // 跨会话残留会让新会话起始即暂停、时间戳偏移)
184188 self . pause . reset ( ) ;
185189 let pause = self . pause . clone ( ) ;
190+ // v0.7.2(REQ-151):从窗口标题初始化会话信息(平台/系列/集号——
191+ // 标题信号零成本;时长/分P 由屏幕 worker 播放器 OCR 增量补充)
192+ self . session_info
193+ . init_from_title ( params. source_window . as_deref ( ) . unwrap_or ( & params. title ) ) ;
186194
187195 // P3:尝试交接预备线程
188196 if let Some ( p) = self . prepared . lock ( ) . expect ( "prepared lock poisoned" ) . take ( ) {
@@ -194,6 +202,7 @@ impl LiveSessionManager {
194202 stop : flag. clone ( ) ,
195203 latest_frame : latest_frame. clone ( ) ,
196204 pause : pause. clone ( ) ,
205+ session_info : self . session_info . clone ( ) ,
197206 } ;
198207 match p. tx . send ( PrepareMsg :: Start ( Box :: new ( handoff) ) ) {
199208 Ok ( ( ) ) => {
@@ -208,7 +217,7 @@ impl LiveSessionManager {
208217 let thread = std:: thread:: Builder :: new ( )
209218 . name ( "entropy-live-session" . into ( ) )
210219 . spawn ( move || {
211- run_session ( h. stop , h. params , h. session_id , h. latest_frame , h. pause )
220+ run_session ( h. stop , h. params , h. session_id , h. latest_frame , h. pause , h . session_info )
212221 } )
213222 . map_err ( |e| AppError :: Io ( format ! ( "启动会话线程失败: {}" , e) ) ) ?;
214223 * guard = Some ( ActiveSession { stop_flag, thread, session_id } ) ;
@@ -241,9 +250,13 @@ impl LiveSessionManager {
241250 }
242251
243252 // 回退:内联加载(现状路径——模型加载在会话线程内完成)
253+ // 会话信息聚合器先 clone(move 闭包不得借用 &self)
254+ let inline_session_info = self . session_info . clone ( ) ;
244255 let thread = std:: thread:: Builder :: new ( )
245256 . name ( "entropy-live-session" . into ( ) )
246- . spawn ( move || run_session ( flag, params, session_id, latest_frame, pause) )
257+ . spawn ( move || {
258+ run_session ( flag, params, session_id, latest_frame, pause, inline_session_info)
259+ } )
247260 . map_err ( |e| AppError :: Io ( format ! ( "启动会话线程失败: {}" , e) ) ) ?;
248261 * guard = Some ( ActiveSession { stop_flag, thread, session_id } ) ;
249262 Ok ( session_id)
@@ -395,6 +408,8 @@ fn run_session(
395408 latest_frame : Arc < Mutex < Option < crate :: live_session_frame:: LatestCapturedFrame > > > ,
396409 // 2026-08 A1:会话暂停共享状态(manager 持同一实例;捕获线程维护补偿时长)
397410 pause : crate :: capture:: audio_loopback:: SessionPause ,
411+ // v0.7.2(REQ-151):会话信息聚合(屏幕 worker 播放器 OCR 写入)
412+ session_info : crate :: session_info:: SessionInfoCollector ,
398413) {
399414 let db = params. db . clone ( ) ;
400415 let engines = params. engines . clone ( ) ;
@@ -422,7 +437,16 @@ fn run_session(
422437 return ;
423438 }
424439 } ;
425- run_session_after_engine ( asr_engine, stop, params, session_id, latest_frame, pause, epoch) ;
440+ run_session_after_engine (
441+ asr_engine,
442+ stop,
443+ params,
444+ session_id,
445+ latest_frame,
446+ pause,
447+ epoch,
448+ session_info,
449+ ) ;
426450}
427451
428452/// 会话装配后半段(引擎就绪后):音频捕获 → 屏幕 worker → 主循环 → 后台融合。
@@ -443,12 +467,16 @@ pub(crate) fn run_session_after_engine(
443467 pause : crate :: capture:: audio_loopback:: SessionPause ,
444468 // A1:会话纪元——音频/屏幕/flush 三处时间戳的唯一基准(ADR-008)
445469 epoch : Instant ,
470+ // v0.7.2(REQ-151):会话信息聚合(屏幕 worker 播放器 OCR 写入)
471+ session_info : crate :: session_info:: SessionInfoCollector ,
446472) {
447473 let db = params. db . clone ( ) ;
448474 let engines = params. engines . clone ( ) ;
449475 // ADR-007:会话启动成功(引擎就绪)→ 广播录制态(前端全局采集徽标依赖此事件;
450476 // 音频/屏幕后续故障走自动恢复不再终止会话)
451477 let _ = params. app . emit ( "live:status" , "recording" ) ;
478+ // v0.7.2(REQ-151):标题信息就绪即推送(平台/系列/集号;时长待播放器 OCR)
479+ let _ = params. app . emit ( "live:session-info" , session_info. snapshot ( ) ) ;
452480
453481 // 2) 音频捕获:捕获线程 → channel → 会话线程(引擎非 Send)
454482 // @ai-context: ADR-007:start 不再因设备缺失返回 Err——捕获线程内部自动重连
@@ -531,6 +559,8 @@ pub(crate) fn run_session_after_engine(
531559 let foreground_monitor = crate :: foreground_timeline:: ForegroundMonitor :: new ( params. hwnd ) ;
532560 // 2026-08 A1:屏幕 worker 共享暂停状态(暂停跳过采样;恢复后时间戳补偿)
533561 let worker_pause = pause. clone ( ) ;
562+ // v0.7.2(REQ-151):会话信息聚合(worker 播放器 OCR 写入)
563+ let worker_session_info = session_info. clone ( ) ;
534564 match std:: thread:: Builder :: new ( )
535565 . name ( "entropy-screen-worker" . into ( ) )
536566 . spawn ( move || {
@@ -553,6 +583,8 @@ pub(crate) fn run_session_after_engine(
553583 foreground_monitor,
554584 // 2026-08 A1:暂停共享状态
555585 worker_pause,
586+ // v0.7.2(REQ-151):会话信息聚合(播放器 OCR 写入)
587+ worker_session_info,
556588 )
557589 } ) {
558590 Ok ( h) => Some ( h) ,
0 commit comments