Unit 5. The dock's first working bay: - 24-segment ladder fed by `MicMeterFraction` — the MEASURED display level (already scaled by the volume and zeroed when muted), never the gain setting. - Fader in dB via `MicVolumeDb` (−60 … +6, 0 = unity) with a mono-weight readout (`MicVolumeDbLabel`), so "−6.0 dB" is what the creator reads instead of "0.50". - Mute button whose dot uses the existing MicStatusBrush; clicking the device name opens the mic picker, so the label stays the control (the KISS rule: one place to change the mic). The preview's own mic row stays for now — it is removed in the final unit, after the dock bays are complete, so nothing is lost if a bay misbehaves. Guard: MicBayTests — the bay binds the dB face and the measured level (not the gain), the fader range IS the scale's range, the VM surface exists, and mute still zeroes the ladder.
62 lines
2.2 KiB
C#
62 lines
2.2 KiB
C#
using System.Windows;
|
||
using System.Windows.Controls;
|
||
using ytLive.Models;
|
||
|
||
namespace ytLive.Controls;
|
||
|
||
/// <summary>The sound bars (creator ruling 2026-10-30). This unit owns the SHELL: the piece of the
|
||
/// window it occupies and the collapse behaviour. The bays and the master readouts fill in over
|
||
/// the following units, so nothing here pretends to be a working meter.
|
||
///
|
||
/// <para>Collapse is driven by the window height, not a user setting: at 1366×768 a full dock
|
||
/// squeezes the preview, and the creator should not have to manage that.</para></summary>
|
||
public partial class AudioDock : UserControl
|
||
{
|
||
private Window? _window;
|
||
|
||
public AudioDock()
|
||
{
|
||
InitializeComponent();
|
||
Loaded += OnLoaded;
|
||
Unloaded += OnUnloaded;
|
||
}
|
||
|
||
/// <summary>Is the dock showing only the telemetry strip?</summary>
|
||
internal bool IsCollapsed { get; private set; }
|
||
|
||
/// <summary>Test seam: the same code the window's SizeChanged runs, without a window.</summary>
|
||
internal void ApplyWindowHeight(double windowHeight)
|
||
{
|
||
var collapsed = AudioDockLayout.IsCollapsed(windowHeight);
|
||
IsCollapsed = collapsed;
|
||
Height = AudioDockLayout.HeightFor(windowHeight);
|
||
Bays.Visibility = collapsed ? Visibility.Collapsed : Visibility.Visible;
|
||
}
|
||
|
||
private void MicLabel_MouseLeftButtonUp(object sender, System.Windows.Input.MouseButtonEventArgs e)
|
||
{
|
||
if (DataContext is ViewModels.MainViewModel vm && vm.OpenMicPickerCommand.CanExecute(null))
|
||
vm.OpenMicPickerCommand.Execute(null);
|
||
}
|
||
|
||
private void OnLoaded(object sender, RoutedEventArgs e)
|
||
{
|
||
_window = Window.GetWindow(this);
|
||
if (_window == null)
|
||
{
|
||
ApplyWindowHeight(AudioDockLayout.CollapseBelowHeight); // no host: show the dock
|
||
return;
|
||
}
|
||
_window.SizeChanged += OnWindowSizeChanged;
|
||
ApplyWindowHeight(_window.ActualHeight > 0 ? _window.ActualHeight : _window.Height);
|
||
}
|
||
|
||
private void OnUnloaded(object sender, RoutedEventArgs e)
|
||
{
|
||
if (_window != null) _window.SizeChanged -= OnWindowSizeChanged;
|
||
_window = null;
|
||
}
|
||
|
||
private void OnWindowSizeChanged(object sender, SizeChangedEventArgs e) => ApplyWindowHeight(e.NewSize.Height);
|
||
}
|