Webcam resource validation + first-frame proof + CameraConflictProbe: MediaCaptureFrameSource validates post-init (VideoDeviceId match, stream properties, reader StartAsync status), subscribes Failed/CameraStreamStateChanged → SourceFailed; CameraManager.AcquireAsync requires first-frame proof (4s timeout) — silent empty box impossible; MainViewModel surfaces WebcamError chip + MessageBox with suspect-app names; fallback ladder VideoPreview → VideoRecord; 19041 SDK projection gaps documented; AGENTS.md + schema.md + HANDOFF.md memory-map rules added; 81 tests passing, 0 warnings
This commit is contained in:
@@ -74,7 +74,7 @@ public class MainViewModel : ViewModelBase
|
||||
private readonly ICameraEnumerator _cameraEnumerator;
|
||||
private readonly CameraManager _cameraManager;
|
||||
private Webcam? _webcam;
|
||||
|
||||
private string? _webcamError;
|
||||
private readonly IMicrophoneEnumerator _microphoneEnumerator;
|
||||
|
||||
// Screen backdrop: a permanent live capture (desktop/game) that every scene
|
||||
@@ -171,6 +171,17 @@ public class MainViewModel : ViewModelBase
|
||||
/// <summary>Shows the mirror / clip-shape row in the source chip when a webcam is selected.</summary>
|
||||
public bool IsWebcamSelected => SelectedElement is WebcamSceneConfig;
|
||||
|
||||
/// <summary>
|
||||
/// The reason the webcam feed is down (device in use, offline, locked, no frames),
|
||||
/// or null when it's alive. Surfaced as a red chip so a dead camera is never a
|
||||
/// silent empty box. Cleared the moment a real frame arrives.
|
||||
/// </summary>
|
||||
public string? WebcamError
|
||||
{
|
||||
get => _webcamError;
|
||||
private set => SetProperty(ref _webcamError, value);
|
||||
}
|
||||
|
||||
public StreamStatus StreamStatus
|
||||
{
|
||||
get => _streamStatus;
|
||||
@@ -783,6 +794,7 @@ public class MainViewModel : ViewModelBase
|
||||
id => new MediaCaptureFrameSource(id),
|
||||
System.Windows.Application.Current?.Dispatcher);
|
||||
_cameraManager.PreviewBitmapChanged += OnCameraPreviewBitmapChanged;
|
||||
_cameraManager.CameraFailed += OnCameraFailed;
|
||||
|
||||
_microphoneEnumerator = new WinRtMicrophoneEnumerator();
|
||||
|
||||
@@ -921,15 +933,25 @@ public class MainViewModel : ViewModelBase
|
||||
}
|
||||
|
||||
// CameraManager creates the shared WriteableBitmap on the UI thread at the
|
||||
// device's frame size; every scene's webcam config picks it up from here.
|
||||
// device's frame size; every scene's webcam config picks it up from here. A
|
||||
// bitmap means a real frame arrived — the camera is provably alive.
|
||||
private void OnCameraPreviewBitmapChanged(string deviceId, WriteableBitmap bitmap)
|
||||
{
|
||||
if (_webcam?.DeviceId != deviceId) return;
|
||||
WebcamError = null;
|
||||
foreach (var scene in Scenes)
|
||||
foreach (var config in scene.Elements.OfType<WebcamSceneConfig>())
|
||||
config.VideoImageSource = bitmap;
|
||||
}
|
||||
|
||||
// The camera failed to start or died asynchronously (in use, offline, locked,
|
||||
// no frames within the proof timeout) — surface it instead of a silent box.
|
||||
private void OnCameraFailed(string deviceId, string message)
|
||||
{
|
||||
if (_webcam?.DeviceId != deviceId) return;
|
||||
WebcamError = $"Webcam offline: {message}";
|
||||
}
|
||||
|
||||
// ─── Screen backdrop capture (live desktop/game) ───
|
||||
|
||||
private const string MonitorKeyPrefix = "monitor:";
|
||||
@@ -1348,7 +1370,7 @@ public class MainViewModel : ViewModelBase
|
||||
if (!started)
|
||||
{
|
||||
MessageBox.Show(
|
||||
"Couldn't start that camera. It may be in use by another app, or Windows camera access may be turned off.",
|
||||
WebcamError ?? "Couldn't start that camera. It may be in use by another app, or Windows camera access may be turned off.",
|
||||
"ytLlive", MessageBoxButton.OK, MessageBoxImage.Warning);
|
||||
}
|
||||
}
|
||||
@@ -1372,7 +1394,7 @@ public class MainViewModel : ViewModelBase
|
||||
if (!started)
|
||||
{
|
||||
MessageBox.Show(
|
||||
"Couldn't start that camera. It may be in use by another app, or Windows camera access may be turned off.",
|
||||
WebcamError ?? "Couldn't start that camera. It may be in use by another app, or Windows camera access may be turned off.",
|
||||
"ytLlive", MessageBoxButton.OK, MessageBoxImage.Warning);
|
||||
break;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user