TASK 3 milestone 1: webcam capture (MediaCapture CPU-first, CameraManager refcount, picker, clip/mirror, schema v2, tests)

This commit is contained in:
2026-08-06 14:35:34 -07:00
parent d97b5d375c
commit 98cdc4b3f4
23 changed files with 1099 additions and 40 deletions
+59 -16
View File
@@ -229,7 +229,9 @@
Click="AddSourceButton_Click">
<Button.ContextMenu>
<ContextMenu DataContext="{Binding PlacementTarget.DataContext, RelativeSource={RelativeSource Self}}">
<MenuItem Header="Webcam" Command="{Binding AddSourceCommand}" CommandParameter="webcam"/>
<MenuItem Header="Webcam" Command="{Binding AddSourceCommand}" CommandParameter="webcam"
IsEnabled="{Binding CanAddWebcam}"
ToolTip="One webcam at a time — it's already in your stream"/>
<MenuItem Header="Screen" Command="{Binding AddSourceCommand}" CommandParameter="screen"/>
<MenuItem Header="Background" Command="{Binding AddSourceCommand}" CommandParameter="background"/>
<MenuItem Header="Image" Command="{Binding AddImageCommand}"/>
@@ -319,21 +321,53 @@
</ItemsControl.ItemContainerStyle>
<ItemsControl.ItemTemplate>
<DataTemplate>
<Image Width="{Binding Width}" Height="{Binding Height}"
Opacity="{Binding Opacity}" Stretch="UniformToFill"
Source="{Binding ImageSource}"
RenderOptions.BitmapScalingMode="HighQuality">
<Image.Style>
<Style TargetType="Image">
<Setter Property="Visibility" Value="Collapsed"/>
<Style.Triggers>
<DataTrigger Binding="{Binding Type}" Value="Image">
<Setter Property="Visibility" Value="Visible"/>
</DataTrigger>
</Style.Triggers>
</Style>
</Image.Style>
</Image>
<Grid Width="{Binding Width}" Height="{Binding Height}"
Opacity="{Binding Opacity}"
RenderTransformOrigin="0.5,0.5">
<Grid.RenderTransform>
<ScaleTransform ScaleX="{Binding MirrorScale}"/>
</Grid.RenderTransform>
<Image Stretch="UniformToFill"
Source="{Binding DisplaySource}"
RenderOptions.BitmapScalingMode="HighQuality">
<Image.Style>
<Style TargetType="Image">
<Setter Property="Visibility" Value="Collapsed"/>
<Style.Triggers>
<DataTrigger Binding="{Binding Type}" Value="Image">
<Setter Property="Visibility" Value="Visible"/>
</DataTrigger>
<MultiDataTrigger>
<MultiDataTrigger.Conditions>
<Condition Binding="{Binding Type}" Value="Webcam"/>
<Condition Binding="{Binding ClipShape}" Value="Traditional"/>
</MultiDataTrigger.Conditions>
<Setter Property="Visibility" Value="Visible"/>
</MultiDataTrigger>
</Style.Triggers>
</Style>
</Image.Style>
</Image>
<Ellipse>
<Ellipse.Style>
<Style TargetType="Ellipse">
<Setter Property="Visibility" Value="Collapsed"/>
<Style.Triggers>
<MultiDataTrigger>
<MultiDataTrigger.Conditions>
<Condition Binding="{Binding Type}" Value="Webcam"/>
<Condition Binding="{Binding ClipShape}" Value="Round"/>
</MultiDataTrigger.Conditions>
<Setter Property="Visibility" Value="Visible"/>
</MultiDataTrigger>
</Style.Triggers>
</Style>
</Ellipse.Style>
<Ellipse.Fill>
<ImageBrush ImageSource="{Binding DisplaySource}" Stretch="UniformToFill"/>
</Ellipse.Fill>
</Ellipse>
</Grid>
</DataTemplate>
</ItemsControl.ItemTemplate>
</ItemsControl>
@@ -441,6 +475,15 @@
<TextBlock x:Name="OpacityValueText" Text="100%" Foreground="#e0e0e0" FontSize="13"
Width="40" Margin="8,0,0,0" VerticalAlignment="Center"/>
</StackPanel>
<StackPanel Orientation="Horizontal" Margin="0,10,0,0"
Visibility="{Binding IsWebcamSelected, Converter={StaticResource BoolToVis}}">
<Button Content="{Binding SelectedSource.MirrorButtonText}"
Style="{StaticResource YtButtonSecondary}" Padding="10,4"
Click="MirrorButton_Click"/>
<Button Content="{Binding SelectedSource.ShapeButtonText}"
Style="{StaticResource YtButtonSecondary}" Padding="10,4"
Margin="8,0,0,0" Click="ShapeButton_Click"/>
</StackPanel>
<TextBlock Text="Drag to move · drag the corner dot to resize"
Foreground="#a0a0b0" FontSize="11" Margin="0,4,0,0"/>
</StackPanel>