The master meter was a fixed 420px, but each sound bay's ladder fills its column — on a wide window a bay could be longer than the master, which is the opposite of what was asked. Master now stretches between 420 and 760 px, and the three bay ladders cap at 320 with the same cap for each, so they stay the same relative size to one another and stay shorter than the master at every window width.
272 lines
20 KiB
XML
272 lines
20 KiB
XML
<UserControl x:Class="ytLive.Controls.AudioDock"
|
||
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
|
||
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
||
xmlns:controls="clr-namespace:ytLive.Controls">
|
||
<!-- The sound bars. Replaces the empty bottom-bar spacer; collapses to the telemetry strip
|
||
on short windows (AudioDockLayout decides the height, not this file). -->
|
||
<Border x:Name="DockRoot" Background="{StaticResource Brush.SurfaceContainer}"
|
||
BorderBrush="{StaticResource Brush.Outline}" BorderThickness="0,1,0,0">
|
||
<Grid>
|
||
<Grid.RowDefinitions>
|
||
<!-- Master FIRST: during a live session attention is on the preview, so the
|
||
master strip sits against it and the bays hang below (creator, 2026-10-30). -->
|
||
<RowDefinition Height="44"/>
|
||
<RowDefinition Height="*"/>
|
||
</Grid.RowDefinitions>
|
||
|
||
<!-- Four bays (creator ruling 2026-11-01): MIC | GAME | TRAX | LIP-SYNC. The three
|
||
sound bays share equal width so their meters stay the same relative size; lip-sync
|
||
is narrow because its function is one slider and three presets. -->
|
||
<Grid x:Name="Bays" Grid.Row="1" Margin="8,4,8,6">
|
||
<Grid.ColumnDefinitions>
|
||
<ColumnDefinition Width="*"/>
|
||
<ColumnDefinition Width="*"/>
|
||
<ColumnDefinition Width="*"/>
|
||
<ColumnDefinition Width="0.45*"/>
|
||
</Grid.ColumnDefinitions>
|
||
|
||
<!-- MIC -->
|
||
<Border Grid.Column="0" Background="{StaticResource Brush.SurfaceContainerLow}" CornerRadius="{StaticResource Radius.Sm}" Margin="0,0,4,0" Padding="10,6">
|
||
<Grid>
|
||
<Grid.RowDefinitions>
|
||
<RowDefinition Height="Auto"/>
|
||
<RowDefinition Height="Auto"/>
|
||
<RowDefinition Height="*"/>
|
||
</Grid.RowDefinitions>
|
||
<Grid Grid.Row="0" Cursor="Hand" ToolTip="Change microphone" MouseLeftButtonUp="MicLabel_MouseLeftButtonUp">
|
||
<Grid.ColumnDefinitions>
|
||
<ColumnDefinition Width="Auto"/>
|
||
<ColumnDefinition Width="*"/>
|
||
</Grid.ColumnDefinitions>
|
||
<Border Background="{StaticResource Brush.SurfaceContainerHighest}" CornerRadius="{StaticResource Radius.Sm}" Padding="5,1">
|
||
<TextBlock Text="MIC 1" FontSize="9" FontWeight="Bold" Foreground="{StaticResource Brush.OnSurfaceVariant}"/>
|
||
</Border>
|
||
<TextBlock Grid.Column="1" Margin="6,0,0,0" FontSize="11" VerticalAlignment="Center"
|
||
TextTrimming="CharacterEllipsis" Text="{Binding MicSourceName, TargetNullValue='No microphone'}"
|
||
Foreground="{StaticResource Brush.OnSurface}"/>
|
||
</Grid>
|
||
<controls:SegmentMeter Grid.Row="1" Height="10" Margin="0,6,0,0" Orientation="Horizontal"
|
||
MaxWidth="320" HorizontalAlignment="Left"
|
||
Level="{Binding MicMeterFraction}" Segments="24"/>
|
||
<DockPanel Grid.Row="2" Margin="0,6,0,0" VerticalAlignment="Bottom">
|
||
<Button DockPanel.Dock="Left" Width="24" Height="20" Margin="0,0,6,0"
|
||
Style="{StaticResource YtButtonSecondary}" Padding="0"
|
||
Command="{Binding ToggleMicMuteCommand}" ToolTip="{Binding MicMuteText}">
|
||
<Ellipse Width="9" Height="9" Fill="{Binding MicStatusBrush}"/>
|
||
</Button>
|
||
<TextBlock DockPanel.Dock="Right" Width="56" TextAlignment="Right" FontSize="10"
|
||
FontFamily="{StaticResource FontFamily.Mono}" VerticalAlignment="Center"
|
||
Foreground="{StaticResource Brush.OnSurfaceVariant}" Text="{Binding MicVolumeDbLabel}"/>
|
||
<Slider Minimum="-60" Maximum="6" SmallChange="0.5" LargeChange="3"
|
||
Value="{Binding MicVolumeDb, Mode=TwoWay}" VerticalAlignment="Center"/>
|
||
</DockPanel>
|
||
</Grid>
|
||
</Border>
|
||
|
||
<!-- GAME / PC, then TRAX beneath it: meter -> desktop volume -> TRAX line -->
|
||
<Border Grid.Column="1" Background="{StaticResource Brush.SurfaceContainerLow}" CornerRadius="{StaticResource Radius.Sm}" Margin="4,0" Padding="10,6">
|
||
<Grid>
|
||
<Grid.RowDefinitions>
|
||
<RowDefinition Height="Auto"/>
|
||
<RowDefinition Height="Auto"/>
|
||
<RowDefinition Height="Auto"/>
|
||
</Grid.RowDefinitions>
|
||
<Grid Grid.Row="0">
|
||
<Grid.ColumnDefinitions>
|
||
<ColumnDefinition Width="Auto"/>
|
||
<ColumnDefinition Width="*"/>
|
||
<ColumnDefinition Width="Auto"/>
|
||
</Grid.ColumnDefinitions>
|
||
<Border Background="{StaticResource Brush.SurfaceContainerHighest}" CornerRadius="{StaticResource Radius.Sm}" Padding="5,1">
|
||
<TextBlock Text="GAME / PC" FontSize="9" FontWeight="Bold" Foreground="{StaticResource Brush.OnSurfaceVariant}"/>
|
||
</Border>
|
||
<TextBlock Grid.Column="1" Margin="6,0,0,0" FontSize="11" VerticalAlignment="Center"
|
||
TextTrimming="CharacterEllipsis" Foreground="{StaticResource Brush.OnSurfaceVariant}"
|
||
Text="Desktop loopback · incl. TRAX"
|
||
ToolTip="Everything playing on the desktop — including TRAX, which rides the same device."/>
|
||
<Border Grid.Column="2" Background="{StaticResource Brush.SurfaceContainerHighest}"
|
||
CornerRadius="{StaticResource Radius.Sm}" Padding="5,1"
|
||
Visibility="{Binding IsGameDucking, Converter={StaticResource BoolToVis}}">
|
||
<TextBlock FontSize="9" FontWeight="Bold" FontFamily="{StaticResource FontFamily.Mono}"
|
||
Foreground="{StaticResource Brush.Secondary}" Text="{Binding GameDuckLabel}"/>
|
||
</Border>
|
||
</Grid>
|
||
|
||
<controls:SegmentMeter Grid.Row="1" Height="10" Margin="0,6,0,4" Orientation="Horizontal"
|
||
MaxWidth="320" HorizontalAlignment="Left"
|
||
Level="{Binding GameMeterFraction}" Segments="24"/>
|
||
|
||
<!-- Desktop volume, directly beneath its meter. -->
|
||
<DockPanel Grid.Row="2" VerticalAlignment="Center">
|
||
<Button DockPanel.Dock="Left" Width="24" Height="20" Margin="0,0,6,0"
|
||
Style="{StaticResource YtButtonSecondary}" Padding="0"
|
||
Command="{Binding ToggleGameMuteCommand}" ToolTip="Mute desktop audio">
|
||
<Ellipse Width="9" Height="9" Fill="{Binding GameMeterBrush}"/>
|
||
</Button>
|
||
<TextBlock DockPanel.Dock="Right" Width="56" TextAlignment="Right" FontSize="10"
|
||
FontFamily="{StaticResource FontFamily.Mono}" VerticalAlignment="Center"
|
||
Foreground="{StaticResource Brush.OnSurfaceVariant}" Text="{Binding GameVolumeDbLabel}"/>
|
||
<Slider Minimum="-60" Maximum="6" SmallChange="0.5" LargeChange="3"
|
||
Value="{Binding GameVolumeDb, Mode=TwoWay}" VerticalAlignment="Center"/>
|
||
</DockPanel>
|
||
|
||
</Grid>
|
||
</Border>
|
||
|
||
<!-- TRAX: its own bay and its own meter now (creator ruling 2026-11-01). It used to
|
||
be a strip inside the game bay because the desktop ladder "already carried it";
|
||
that hid whether the music was actually playing. -->
|
||
<Border Grid.Column="2" Background="{StaticResource Brush.SurfaceContainerLow}" CornerRadius="{StaticResource Radius.Sm}" Margin="4,0" Padding="10,6">
|
||
<Grid>
|
||
<Grid.RowDefinitions>
|
||
<RowDefinition Height="Auto"/>
|
||
<RowDefinition Height="Auto"/>
|
||
<RowDefinition Height="Auto"/>
|
||
</Grid.RowDefinitions>
|
||
<Grid Grid.Row="0">
|
||
<Grid.ColumnDefinitions>
|
||
<ColumnDefinition Width="Auto"/>
|
||
<ColumnDefinition Width="*"/>
|
||
</Grid.ColumnDefinitions>
|
||
<Border Background="{StaticResource Brush.SurfaceContainerHighest}" CornerRadius="{StaticResource Radius.Sm}" Padding="5,1">
|
||
<TextBlock Text="TRAX" FontSize="9" FontWeight="Bold" Foreground="{StaticResource Brush.OnSurfaceVariant}"/>
|
||
</Border>
|
||
<TextBlock Grid.Column="1" Margin="6,0,0,0" FontSize="11" VerticalAlignment="Center"
|
||
TextTrimming="CharacterEllipsis" Foreground="{StaticResource Brush.OnSurfaceVariant}"
|
||
Text="{Binding TraxTrackLabel}" Cursor="Hand"
|
||
MouseLeftButtonUp="TraxLabel_MouseLeftButtonUp"
|
||
MouseRightButtonUp="TraxLabel_MouseRightButtonUp"/>
|
||
</Grid>
|
||
|
||
<controls:SegmentMeter Grid.Row="1" Height="10" Margin="0,6,0,4" Orientation="Horizontal"
|
||
MaxWidth="320" HorizontalAlignment="Left"
|
||
Level="{Binding TraxMeterFraction}" Segments="24"/>
|
||
|
||
<DockPanel Grid.Row="2" VerticalAlignment="Center">
|
||
<Button DockPanel.Dock="Left" Width="24" Height="20" Margin="0,0,6,0" Padding="0"
|
||
Style="{StaticResource YtButtonSecondary}" Click="TraxPlayPause_Click"
|
||
ToolTip="{Binding TraxToolTip}">
|
||
<TextBlock FontSize="9" Foreground="{StaticResource Brush.OnSurface}">
|
||
<TextBlock.Style>
|
||
<Style TargetType="TextBlock">
|
||
<Setter Property="Text" Value="▶"/>
|
||
<Style.Triggers>
|
||
<DataTrigger Binding="{Binding IsMusicPlaying}" Value="True">
|
||
<Setter Property="Text" Value="❚❚"/>
|
||
</DataTrigger>
|
||
</Style.Triggers>
|
||
</Style>
|
||
</TextBlock.Style>
|
||
</TextBlock>
|
||
</Button>
|
||
<StackPanel DockPanel.Dock="Right" Orientation="Horizontal" VerticalAlignment="Center">
|
||
<Button Content="−" Width="18" Height="16" Padding="0" FontSize="11"
|
||
Style="{StaticResource YtButtonSecondary}" Click="TraxStepDown_Click"
|
||
IsEnabled="{Binding CanLowerTrax}" ToolTip="5 dB quieter"/>
|
||
<TextBlock Width="52" TextAlignment="Center" FontSize="10" VerticalAlignment="Center"
|
||
FontFamily="{StaticResource FontFamily.Mono}"
|
||
Foreground="{StaticResource Brush.OnSurfaceVariant}"
|
||
Text="{Binding TraxVolumeDbLabel}"/>
|
||
<Button Content="+" Width="18" Height="16" Padding="0" FontSize="11"
|
||
Style="{StaticResource YtButtonSecondary}" Click="TraxStepUp_Click"
|
||
IsEnabled="{Binding CanRaiseTrax}" ToolTip="5 dB louder"/>
|
||
</StackPanel>
|
||
</DockPanel>
|
||
</Grid>
|
||
</Border>
|
||
|
||
<!-- LIP-SYNC (narrow: one slider, three presets) -->
|
||
<Border Grid.Column="3" Background="{StaticResource Brush.SurfaceContainerLow}" CornerRadius="{StaticResource Radius.Sm}" Margin="4,0,0,0" Padding="10,6">
|
||
<Grid>
|
||
<Grid.RowDefinitions>
|
||
<RowDefinition Height="Auto"/>
|
||
<RowDefinition Height="*"/>
|
||
</Grid.RowDefinitions>
|
||
<Grid Grid.Row="0">
|
||
<Grid.ColumnDefinitions>
|
||
<ColumnDefinition Width="Auto"/>
|
||
<ColumnDefinition Width="*"/>
|
||
</Grid.ColumnDefinitions>
|
||
<Border Background="{StaticResource Brush.SurfaceContainerHighest}" CornerRadius="{StaticResource Radius.Sm}" Padding="5,1">
|
||
<TextBlock Text="LIP-SYNC" FontSize="9" FontWeight="Bold" Foreground="{StaticResource Brush.OnSurfaceVariant}"/>
|
||
</Border>
|
||
<TextBlock Grid.Column="1" Margin="6,0,0,0" FontSize="10" VerticalAlignment="Center"
|
||
FontFamily="{StaticResource FontFamily.Mono}" TextAlignment="Right"
|
||
Foreground="{StaticResource Brush.Tertiary}" Text="{Binding SyncOffsetLabel}"/>
|
||
</Grid>
|
||
<StackPanel Grid.Row="1" VerticalAlignment="Bottom">
|
||
<Slider Minimum="-200" Maximum="200" SmallChange="5" LargeChange="25"
|
||
TickFrequency="5" IsSnapToTickEnabled="True"
|
||
Value="{Binding AudioSyncOffsetMs, Mode=TwoWay}" VerticalAlignment="Center"/>
|
||
<StackPanel Orientation="Horizontal" Margin="0,2,0,0" HorizontalAlignment="Right">
|
||
<Button Content="0" Width="26" Height="16" FontSize="9" Padding="0" Margin="0,0,4,0"
|
||
Style="{StaticResource YtButtonSecondary}" Click="SyncPreset_Click" Tag="0"/>
|
||
<Button Content="+50" Width="30" Height="16" FontSize="9" Padding="0" Margin="0,0,4,0"
|
||
Style="{StaticResource YtButtonSecondary}" Click="SyncPreset_Click" Tag="50"/>
|
||
<Button Content="+100" Width="34" Height="16" FontSize="9" Padding="0"
|
||
Style="{StaticResource YtButtonSecondary}" Click="SyncPreset_Click" Tag="100"/>
|
||
</StackPanel>
|
||
</StackPanel>
|
||
</Grid>
|
||
</Border>
|
||
</Grid>
|
||
|
||
<!-- Master strip: always visible, even collapsed. Rebuilt 2026-11-01 — the meter is
|
||
CENTRED under the preview and is the biggest one on screen; MASTER's own label is
|
||
larger than the bay labels. The kbps / fps / dropped counters that used to end this
|
||
line are gone: the live readouts already sit above the preview. -->
|
||
<Border x:Name="MasterStrip" Grid.Row="0" Background="{StaticResource Brush.SurfaceContainerLowest}" Padding="12,0">
|
||
<Grid>
|
||
<Grid.ColumnDefinitions>
|
||
<ColumnDefinition Width="Auto"/>
|
||
<ColumnDefinition Width="*"/>
|
||
<ColumnDefinition Width="Auto"/>
|
||
</Grid.ColumnDefinitions>
|
||
|
||
<!-- Left: the imbalance flag, the one case that silently ruins a mix. -->
|
||
<Border Grid.Column="0" Margin="0,0,8,0" Padding="5,1" VerticalAlignment="Center"
|
||
CornerRadius="{StaticResource Radius.Sm}" Background="{StaticResource Brush.SurfaceContainerHigh}"
|
||
Visibility="{Binding MasterImbalance, Converter={StaticResource BoolToVis}}"
|
||
ToolTip="Left and right differ by more than 6 dB — one side may be inaudible.">
|
||
<TextBlock Text="L/R" FontSize="9" FontWeight="Bold" FontFamily="{StaticResource FontFamily.Mono}"
|
||
Foreground="{StaticResource Brush.Attention}"/>
|
||
</Border>
|
||
|
||
<!-- Centre: MASTER + the long meter + its reading. The ladder stretches with the
|
||
window between 420 and 760 px — always longer than the 320-capped bay meters. -->
|
||
<Grid Grid.Column="1" VerticalAlignment="Center" HorizontalAlignment="Center">
|
||
<Grid.ColumnDefinitions>
|
||
<ColumnDefinition Width="Auto"/>
|
||
<ColumnDefinition Width="*"/>
|
||
<ColumnDefinition Width="Auto"/>
|
||
</Grid.ColumnDefinitions>
|
||
<TextBlock Grid.Column="0" Text="MASTER" FontSize="12" FontWeight="Bold" VerticalAlignment="Center"
|
||
Foreground="{StaticResource Brush.OnSurface}"/>
|
||
<controls:SegmentMeter Grid.Column="1" Height="14" Margin="12,0,0,0" MinWidth="420" MaxWidth="760"
|
||
Orientation="Horizontal" Segments="32"
|
||
Level="{Binding MasterMeterFraction}" VerticalAlignment="Center"/>
|
||
<TextBlock Grid.Column="2" Width="72" Margin="10,0,0,0" FontSize="12"
|
||
FontFamily="{StaticResource FontFamily.Mono}" VerticalAlignment="Center"
|
||
Foreground="{StaticResource Brush.OnSurface}"
|
||
Text="{Binding MasterLevelLabel}"/>
|
||
</Grid>
|
||
|
||
<!-- Right: MONO (accessibility, remembered) + the session clock. -->
|
||
<StackPanel Grid.Column="2" Orientation="Horizontal" VerticalAlignment="Center">
|
||
<ToggleButton Height="20" Padding="8,0"
|
||
Style="{StaticResource SegmentToggle}" IsChecked="{Binding MonoOutput, Mode=TwoWay}"
|
||
ToolTip="Fold the output to mono — both ears hear everything">
|
||
<TextBlock Text="MONO" FontSize="10" FontWeight="Bold"
|
||
Foreground="{Binding Foreground, RelativeSource={RelativeSource AncestorType=ToggleButton}}"/>
|
||
</ToggleButton>
|
||
<TextBlock FontSize="11" FontFamily="{StaticResource FontFamily.Mono}" Margin="12,0,0,0"
|
||
VerticalAlignment="Center"
|
||
Foreground="{StaticResource Brush.OnSurfaceVariant}"
|
||
Text="{Binding CurrentHealth.StreamDuration, StringFormat={}{0:hh\:mm\:ss}}"/>
|
||
</StackPanel>
|
||
</Grid>
|
||
</Border>
|
||
</Grid>
|
||
</Border>
|
||
</UserControl>
|