feat(dock): TRAX becomes a background level, not a channel strip
Creator ruling (2026-10-30): TRAX is background music and is controlled separately from desktop and mic — so KISS it: - TRAX loses its own ladder and slider. It is one number plus ±5 dB buttons, disabled at the ends (−60 dB floor, +6 dB ceiling). - It STARTS at −50 dB, taken from the creator's own meter readings, and moves in 5 dB clicks. If that proves inaudible on their setup, six clicks lands at −20 — the buttons exist for exactly that, and `TraxDefaultDb` is one constant. - Layout follows: Desktop's volume now sits directly beneath its ladder, and the TRAX row (name, play/pause, level) sits beneath that, inside the GAME bay. The bays are MIC | GAME+TRAX | LIP-SYNC. - The metering tap on the player stays (it is how "is the music producing sound" is answered) but has no ladder of its own; the desktop bed already shows the music. Guards updated: TraxBayTests now asserts the stepper wiring and that the row has NO SegmentMeter; GameBayTests asserts the desktop fader sits below the desktop ladder.
This commit is contained in:
+66
-89
@@ -18,11 +18,11 @@
|
||||
<Grid x:Name="Bays" Grid.Row="1" Margin="8,4,8,6">
|
||||
<Grid.ColumnDefinitions>
|
||||
<ColumnDefinition Width="*"/>
|
||||
<ColumnDefinition Width="*"/>
|
||||
<ColumnDefinition Width="*"/>
|
||||
<ColumnDefinition Width="1.4*"/>
|
||||
<ColumnDefinition Width="*"/>
|
||||
</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>
|
||||
@@ -30,10 +30,7 @@
|
||||
<RowDefinition Height="Auto"/>
|
||||
<RowDefinition Height="*"/>
|
||||
</Grid.RowDefinitions>
|
||||
|
||||
<!-- Clicking the name opens the mic picker: the label is the control. -->
|
||||
<Grid Grid.Row="0" Cursor="Hand" ToolTip="Change microphone"
|
||||
MouseLeftButtonUp="MicLabel_MouseLeftButtonUp">
|
||||
<Grid Grid.Row="0" Cursor="Hand" ToolTip="Change microphone" MouseLeftButtonUp="MicLabel_MouseLeftButtonUp">
|
||||
<Grid.ColumnDefinitions>
|
||||
<ColumnDefinition Width="Auto"/>
|
||||
<ColumnDefinition Width="*"/>
|
||||
@@ -42,14 +39,11 @@
|
||||
<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'}"
|
||||
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"
|
||||
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"
|
||||
@@ -58,21 +52,22 @@
|
||||
</Button>
|
||||
<TextBlock DockPanel.Dock="Right" Width="56" TextAlignment="Right" FontSize="10"
|
||||
FontFamily="{StaticResource FontFamily.Mono}" VerticalAlignment="Center"
|
||||
Foreground="{StaticResource Brush.OnSurfaceVariant}"
|
||||
Text="{Binding MicVolumeDbLabel}"/>
|
||||
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="*"/>
|
||||
<RowDefinition Height="Auto"/>
|
||||
<RowDefinition Height="Auto"/>
|
||||
</Grid.RowDefinitions>
|
||||
|
||||
<Grid Grid.Row="0">
|
||||
<Grid.ColumnDefinitions>
|
||||
<ColumnDefinition Width="Auto"/>
|
||||
@@ -82,15 +77,10 @@
|
||||
<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>
|
||||
<!-- TRAX plays through the default device, so the loopback bed carries it:
|
||||
this ladder shows everything the viewer hears from the desktop,
|
||||
music included. The TRAX bay's ladder is a tap on the player. -->
|
||||
<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."/>
|
||||
<!-- The duck badge only exists while the duck is happening, and it carries
|
||||
the gain the mixer actually applied. -->
|
||||
<Border Grid.Column="2" Background="{StaticResource Brush.SurfaceContainerHighest}"
|
||||
CornerRadius="{StaticResource Radius.Sm}" Padding="5,1"
|
||||
Visibility="{Binding IsGameDucking, Converter={StaticResource BoolToVis}}">
|
||||
@@ -99,10 +89,11 @@
|
||||
</Border>
|
||||
</Grid>
|
||||
|
||||
<controls:SegmentMeter Grid.Row="1" Height="10" Margin="0,6,0,0" Orientation="Horizontal"
|
||||
<controls:SegmentMeter Grid.Row="1" Height="10" Margin="0,6,0,4" Orientation="Horizontal"
|
||||
Level="{Binding GameMeterFraction}" Segments="24"/>
|
||||
|
||||
<DockPanel Grid.Row="2" Margin="0,6,0,0" VerticalAlignment="Bottom">
|
||||
<!-- 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">
|
||||
@@ -110,79 +101,69 @@
|
||||
</Button>
|
||||
<TextBlock DockPanel.Dock="Right" Width="56" TextAlignment="Right" FontSize="10"
|
||||
FontFamily="{StaticResource FontFamily.Mono}" VerticalAlignment="Center"
|
||||
Foreground="{StaticResource Brush.OnSurfaceVariant}"
|
||||
Text="{Binding GameVolumeDbLabel}"/>
|
||||
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>
|
||||
|
||||
<!-- TRAX: background music — one number, two buttons. No meter: it is
|
||||
background, and the desktop ladder already carries it. -->
|
||||
<Border Grid.Row="3" Margin="0,4,0,0" Padding="6,3" CornerRadius="{StaticResource Radius.Sm}"
|
||||
Background="{StaticResource Brush.SurfaceContainerLowest}">
|
||||
<Grid>
|
||||
<Grid.ColumnDefinitions>
|
||||
<ColumnDefinition Width="Auto"/>
|
||||
<ColumnDefinition Width="*"/>
|
||||
<ColumnDefinition Width="Auto"/>
|
||||
<ColumnDefinition Width="Auto"/>
|
||||
</Grid.ColumnDefinitions>
|
||||
<TextBlock Text="TRAX" FontSize="9" FontWeight="Bold" VerticalAlignment="Center"
|
||||
Foreground="{StaticResource Brush.OnSurfaceVariant}"/>
|
||||
<TextBlock Grid.Column="1" Margin="6,0,0,0" FontSize="10" VerticalAlignment="Center"
|
||||
TextTrimming="CharacterEllipsis" Foreground="{StaticResource Brush.OnSurface}"
|
||||
Text="{Binding TraxTrackLabel}" Cursor="Hand"
|
||||
MouseLeftButtonUp="TraxLabel_MouseLeftButtonUp"
|
||||
MouseRightButtonUp="TraxLabel_MouseRightButtonUp"/>
|
||||
<Button Grid.Column="2" Width="20" Height="16" Margin="4,0,0,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 Grid.Column="3" Orientation="Horizontal" Margin="6,0,0,0" 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.Tertiary}"
|
||||
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>
|
||||
</Grid>
|
||||
</Border>
|
||||
</Grid>
|
||||
</Border>
|
||||
<Border Grid.Column="2" Background="{StaticResource Brush.SurfaceContainerLow}" CornerRadius="{StaticResource Radius.Sm}" Margin="4,0" Padding="10,6">
|
||||
|
||||
<!-- LIP-SYNC -->
|
||||
<Border Grid.Column="2" 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="*"/>
|
||||
<ColumnDefinition Width="Auto"/>
|
||||
<ColumnDefinition Width="Auto"/>
|
||||
</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>
|
||||
<!-- The name is the control: left-click toggles play, right-click picks (§TRAX). -->
|
||||
<TextBlock Grid.Column="1" Margin="6,0,0,0" FontSize="11" VerticalAlignment="Center"
|
||||
TextTrimming="CharacterEllipsis" Foreground="{StaticResource Brush.OnSurface}"
|
||||
Text="{Binding TraxTrackLabel}"
|
||||
MouseLeftButtonUp="TraxLabel_MouseLeftButtonUp"
|
||||
MouseRightButtonUp="TraxLabel_MouseRightButtonUp" Cursor="Hand"/>
|
||||
<Button Grid.Column="2" Width="22" Height="18" Style="{StaticResource YtButtonSecondary}" Padding="0"
|
||||
Margin="4,0,0,0" Click="TraxPlayPause_Click" ToolTip="{Binding TraxToolTip}">
|
||||
<TextBlock FontSize="10" 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>
|
||||
<Border Grid.Column="3" Margin="4,0,0,0" Background="{StaticResource Brush.SurfaceContainerHighest}"
|
||||
CornerRadius="{StaticResource Radius.Sm}" Padding="5,1"
|
||||
Visibility="{Binding IsTraxDucking, Converter={StaticResource BoolToVis}}">
|
||||
<TextBlock FontSize="9" FontWeight="Bold" FontFamily="{StaticResource FontFamily.Mono}"
|
||||
Foreground="{StaticResource Brush.Secondary}" Text="DUCK"/>
|
||||
</Border>
|
||||
</Grid>
|
||||
|
||||
<controls:SegmentMeter Grid.Row="1" Height="10" Margin="0,6,0,6" Orientation="Horizontal"
|
||||
Level="{Binding TraxMeterFraction}" Segments="24"/>
|
||||
|
||||
<DockPanel Grid.Row="1" Margin="0,22,0,0" VerticalAlignment="Bottom">
|
||||
<TextBlock DockPanel.Dock="Right" Width="56" TextAlignment="Right" FontSize="10"
|
||||
FontFamily="{StaticResource FontFamily.Mono}" VerticalAlignment="Center"
|
||||
Foreground="{StaticResource Brush.OnSurfaceVariant}"
|
||||
Text="{Binding TraxVolumeDbLabel}"/>
|
||||
<Slider Minimum="-60" Maximum="6" SmallChange="0.5" LargeChange="3"
|
||||
Value="{Binding TraxVolumeDb, Mode=TwoWay}" VerticalAlignment="Center"/>
|
||||
</DockPanel>
|
||||
</Grid>
|
||||
</Border>
|
||||
<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"/>
|
||||
@@ -193,13 +174,9 @@
|
||||
</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}"/>
|
||||
Foreground="{StaticResource Brush.Tertiary}" Text="{Binding SyncOffsetLabel}"/>
|
||||
</Grid>
|
||||
|
||||
<StackPanel Grid.Row="1" VerticalAlignment="Bottom">
|
||||
<!-- A detent marker would need a custom track; the 0 ms preset is the
|
||||
detent as a button, which is also easier to hit than a snap. -->
|
||||
<Slider Minimum="-200" Maximum="200" SmallChange="5" LargeChange="25"
|
||||
TickFrequency="5" IsSnapToTickEnabled="True"
|
||||
Value="{Binding AudioSyncOffsetMs, Mode=TwoWay}" VerticalAlignment="Center"/>
|
||||
|
||||
@@ -39,6 +39,16 @@ public partial class AudioDock : UserControl
|
||||
vm.OpenMicPickerCommand.Execute(null);
|
||||
}
|
||||
|
||||
private void TraxStepDown_Click(object sender, RoutedEventArgs e)
|
||||
{
|
||||
if (DataContext is ViewModels.MainViewModel vm) vm.StepTrax(-1);
|
||||
}
|
||||
|
||||
private void TraxStepUp_Click(object sender, RoutedEventArgs e)
|
||||
{
|
||||
if (DataContext is ViewModels.MainViewModel vm) vm.StepTrax(+1);
|
||||
}
|
||||
|
||||
private void SyncPreset_Click(object sender, RoutedEventArgs e)
|
||||
{
|
||||
if (DataContext is not ViewModels.MainViewModel vm) return;
|
||||
|
||||
Reference in New Issue
Block a user