fix(build): the wordmark number counts commits again, not compiles
GenerateBuildStamp read BuildCounter.txt, added 1 and wrote it back on every CoreCompile, so the number tracked BUILDS: a day of iteration reached #1122 against 563 commits. It now uses git rev-list count of HEAD, which is what the comment always claimed (and why the file existed in .gitignore). No counter file, no drift; a missing git still falls back to the start. Also moves the MIC and lip-sync volume bars up one line: both were pinned to the floor of their bay by a star row plus VerticalAlignment=Bottom. They now sit directly under their headers, with the auto rows sized to content.
This commit is contained in:
+1
-1
@@ -20,7 +20,7 @@ MARCOM.md
|
|||||||
CREDENTIALS.md
|
CREDENTIALS.md
|
||||||
.aider*
|
.aider*
|
||||||
ffmpeg/
|
ffmpeg/
|
||||||
BuildCounter.txt
|
BuildCounter.txt # unused since 2026-11-01 (the build stamp is the git commit count)
|
||||||
|
|
||||||
# Steamworks runtime (steam_api64.dll, 312 KB) — extracted from the SDK zip, never committed;
|
# Steamworks runtime (steam_api64.dll, 312 KB) — extracted from the SDK zip, never committed;
|
||||||
# scripts/steam-sdk.sh documents which file and why. Same rule as ffmpeg/: the pin is the audit trail.
|
# scripts/steam-sdk.sh documents which file and why. Same rule as ffmpeg/: the pin is the audit trail.
|
||||||
|
|||||||
@@ -0,0 +1 @@
|
|||||||
|
1122
|
||||||
@@ -31,7 +31,7 @@
|
|||||||
<Grid.RowDefinitions>
|
<Grid.RowDefinitions>
|
||||||
<RowDefinition Height="Auto"/>
|
<RowDefinition Height="Auto"/>
|
||||||
<RowDefinition Height="Auto"/>
|
<RowDefinition Height="Auto"/>
|
||||||
<RowDefinition Height="*"/>
|
<RowDefinition Height="Auto"/>
|
||||||
</Grid.RowDefinitions>
|
</Grid.RowDefinitions>
|
||||||
<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>
|
<Grid.ColumnDefinitions>
|
||||||
@@ -47,7 +47,7 @@
|
|||||||
</Grid>
|
</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,0" Orientation="Horizontal"
|
||||||
Level="{Binding MicMeterFraction}" Segments="24"/>
|
Level="{Binding MicMeterFraction}" Segments="24"/>
|
||||||
<DockPanel Grid.Row="2" Margin="0,6,0,0" VerticalAlignment="Bottom">
|
<DockPanel Grid.Row="2" Margin="0,6,0,0">
|
||||||
<Button DockPanel.Dock="Left" Width="24" Height="20" Margin="0,0,6,0"
|
<Button DockPanel.Dock="Left" Width="24" Height="20" Margin="0,0,6,0"
|
||||||
Style="{StaticResource YtButtonSecondary}" Padding="0"
|
Style="{StaticResource YtButtonSecondary}" Padding="0"
|
||||||
Command="{Binding ToggleMicMuteCommand}" ToolTip="{Binding MicMuteText}">
|
Command="{Binding ToggleMicMuteCommand}" ToolTip="{Binding MicMuteText}">
|
||||||
@@ -177,7 +177,7 @@
|
|||||||
<Grid>
|
<Grid>
|
||||||
<Grid.RowDefinitions>
|
<Grid.RowDefinitions>
|
||||||
<RowDefinition Height="Auto"/>
|
<RowDefinition Height="Auto"/>
|
||||||
<RowDefinition Height="*"/>
|
<RowDefinition Height="Auto"/>
|
||||||
</Grid.RowDefinitions>
|
</Grid.RowDefinitions>
|
||||||
<Grid Grid.Row="0">
|
<Grid Grid.Row="0">
|
||||||
<Grid.ColumnDefinitions>
|
<Grid.ColumnDefinitions>
|
||||||
@@ -191,7 +191,7 @@
|
|||||||
FontFamily="{StaticResource FontFamily.Mono}" TextAlignment="Right"
|
FontFamily="{StaticResource FontFamily.Mono}" TextAlignment="Right"
|
||||||
Foreground="{StaticResource Brush.Tertiary}" Text="{Binding SyncOffsetLabel}"/>
|
Foreground="{StaticResource Brush.Tertiary}" Text="{Binding SyncOffsetLabel}"/>
|
||||||
</Grid>
|
</Grid>
|
||||||
<StackPanel Grid.Row="1" VerticalAlignment="Bottom">
|
<StackPanel Grid.Row="1" Margin="0,6,0,0">
|
||||||
<Slider Minimum="-200" Maximum="200" SmallChange="5" LargeChange="25"
|
<Slider Minimum="-200" Maximum="200" SmallChange="5" LargeChange="25"
|
||||||
TickFrequency="5" IsSnapToTickEnabled="True"
|
TickFrequency="5" IsSnapToTickEnabled="True"
|
||||||
Value="{Binding AudioSyncOffsetMs, Mode=TwoWay}" VerticalAlignment="Center"/>
|
Value="{Binding AudioSyncOffsetMs, Mode=TwoWay}" VerticalAlignment="Center"/>
|
||||||
|
|||||||
@@ -36,7 +36,7 @@ C# / WPF (.NET 8) following MVVM:
|
|||||||
| `Models/` | Plain data types — Scene, Source (incl. `ClipShape`, `IsMirrored`, `VideoImageSource`), QualityOption, StreamConfig, StreamHealth, YouTubeChannel, ChatMessage, **Socials (`SocialService` enum + `SocialEntry`/`SocialsConfig` + `SocialServiceIcons`) — the social bar** |
|
| `Models/` | Plain data types — Scene, Source (incl. `ClipShape`, `IsMirrored`, `VideoImageSource`), QualityOption, StreamConfig, StreamHealth, YouTubeChannel, ChatMessage, **Socials (`SocialService` enum + `SocialEntry`/`SocialsConfig` + `SocialServiceIcons`) — the social bar** |
|
||||||
| `ViewModels/` | MainViewModel — `public partial class`, one file per functional area (Scenes, Background, Webcam, Audio, Trax, Socials, Streaming, Chat, Overlays, Account, License, Recording — split complete, see `ViewModels/index.md`); **Chat.cs is a thin delegating facade over `Services/ChatOverlayLayer.cs` (Commit G, first true decomposition), and now also over `Services/AlertOverlayLayer.cs` (TASK 43 — the native alert box, same true-component pattern)**; GoLiveViewModel, ReuseImageViewModel, CameraPickerViewModel, **SocialsDialogViewModel** |
|
| `ViewModels/` | MainViewModel — `public partial class`, one file per functional area (Scenes, Background, Webcam, Audio, Trax, Socials, Streaming, Chat, Overlays, Account, License, Recording — split complete, see `ViewModels/index.md`); **Chat.cs is a thin delegating facade over `Services/ChatOverlayLayer.cs` (Commit G, first true decomposition), and now also over `Services/AlertOverlayLayer.cs` (TASK 43 — the native alert box, same true-component pattern)**; GoLiveViewModel, ReuseImageViewModel, CameraPickerViewModel, **SocialsDialogViewModel** |
|
||||||
| `Services/` | YouTube OAuth2, stream/broadcast management, live chat polling, LayoutStore (SQLite), **SocialValidator (`ISocialValidator` seam + `HttpSocialValidator` default)**, **webcam: `VideoFrame` seam + `CameraDeviceInfo`/`ICameraEnumerator`/`ICameraFrameSource` interfaces + `MediaCaptureCameraEnumerator`/`MediaCaptureFrameSource` (WinRT) + `CameraManager`**, **screen capture: `IFullScreenDetector`/`Win32FullScreenDetector` + `IScreenCaptureSource`/`ScreenCaptureFrameSource` (WinRT GraphicsCapture) + `ScreenCaptureManager` + `ScreenCaptureSourceFactory` + `Direct3D11Helper`/`CaptureInterop` (COM bridges)**, **media source: `IMediaFrameSource` + `MediaVideoSource` (spawns ffmpeg `rawvideo` BGRA decode) + `MediaVideoSourceManager` (refcount-by-path session owner) + pure `RawVideoFrameReader` + `IDecodeProcess`/`FfmpegDecodeProcess` process seam (binary-stdout mirror of `IEncoderProcess`; see [`TASKS/task-21-media-source.md`](TASKS/task-21-media-source.md))**, **compositor: `SceneCompositor` + `CompositorOptions` + pure `StretchMath` + `StaticPixelCache` (see [`docs/ai/frame-pipeline.md`](docs/ai/frame-pipeline.md) → "Scene compositor")**, **alerts: `ChatOverlayLayer` + `AlertOverlayLayer`/`AlertRenderer` (the native celebration-zone overlay, TASK 43 — see [`docs/ai/overlays.md`](docs/ai/overlays.md))**, **audio: `IAudioSource` seam + `WasapiLoopbackAudioSource`/`WasapiMicAudioSource` (NAudio WASAPI) + `AudioMixer` + pure `AudioLevelMeter`/`WaveToFloat`/`VoiceFilterChain`/`LowShelfFilter`/`HighShelfFilter`/`NoiseGate`/`Compressor`/`AutoDucker`/`AudioRingBuffer`/`TinyResampler`/`AudioSyncDelay` + `MusicPlayer` + `ITraxPlayer` (TRAX toggle seam — FakePlayer in tests; the dot is green/red/gray and the error scrolls terse in the desktop-audio bar; MusicVolume fixed 0.5) + `IAudioPipeWriter`/`NamedPipeAudioWriter` (see [`docs/ai/output.md`](docs/ai/output.md) → "Live audio capture")**, **encoder: `IFfmpegEncoder`/`FfmpegEncoder` + `IEncoderProcess`/`FfmpegEncoderProcess` + `IFfmpegLocator`/`FfmpegLocator` + pure `FfmpegArgs`/`FfmpegProgressParser`/`FfmpegEncoderPicker` + the `FramePump` frame producer (see [`docs/ai/output.md`](docs/ai/output.md) → "Live encoder" + [`docs/ai/frame-pipeline.md`](docs/ai/frame-pipeline.md) → "Live frame pipeline")**, **notifications: `INotificationService` seam (`AppNotificationSeverity` Info/Success/Warning/Error) + `NotificationService` (Notification.Wpf toasts, see "Toast notifications")** |
|
| `Services/` | YouTube OAuth2, stream/broadcast management, live chat polling, LayoutStore (SQLite), **SocialValidator (`ISocialValidator` seam + `HttpSocialValidator` default)**, **webcam: `VideoFrame` seam + `CameraDeviceInfo`/`ICameraEnumerator`/`ICameraFrameSource` interfaces + `MediaCaptureCameraEnumerator`/`MediaCaptureFrameSource` (WinRT) + `CameraManager`**, **screen capture: `IFullScreenDetector`/`Win32FullScreenDetector` + `IScreenCaptureSource`/`ScreenCaptureFrameSource` (WinRT GraphicsCapture) + `ScreenCaptureManager` + `ScreenCaptureSourceFactory` + `Direct3D11Helper`/`CaptureInterop` (COM bridges)**, **media source: `IMediaFrameSource` + `MediaVideoSource` (spawns ffmpeg `rawvideo` BGRA decode) + `MediaVideoSourceManager` (refcount-by-path session owner) + pure `RawVideoFrameReader` + `IDecodeProcess`/`FfmpegDecodeProcess` process seam (binary-stdout mirror of `IEncoderProcess`; see [`TASKS/task-21-media-source.md`](TASKS/task-21-media-source.md))**, **compositor: `SceneCompositor` + `CompositorOptions` + pure `StretchMath` + `StaticPixelCache` (see [`docs/ai/frame-pipeline.md`](docs/ai/frame-pipeline.md) → "Scene compositor")**, **alerts: `ChatOverlayLayer` + `AlertOverlayLayer`/`AlertRenderer` (the native celebration-zone overlay, TASK 43 — see [`docs/ai/overlays.md`](docs/ai/overlays.md))**, **audio: `IAudioSource` seam + `WasapiLoopbackAudioSource`/`WasapiMicAudioSource` (NAudio WASAPI) + `AudioMixer` + pure `AudioLevelMeter`/`WaveToFloat`/`VoiceFilterChain`/`LowShelfFilter`/`HighShelfFilter`/`NoiseGate`/`Compressor`/`AutoDucker`/`AudioRingBuffer`/`TinyResampler`/`AudioSyncDelay` + `MusicPlayer` + `ITraxPlayer` (TRAX toggle seam — FakePlayer in tests; the dot is green/red/gray and the error scrolls terse in the desktop-audio bar; MusicVolume fixed 0.5) + `IAudioPipeWriter`/`NamedPipeAudioWriter` (see [`docs/ai/output.md`](docs/ai/output.md) → "Live audio capture")**, **encoder: `IFfmpegEncoder`/`FfmpegEncoder` + `IEncoderProcess`/`FfmpegEncoderProcess` + `IFfmpegLocator`/`FfmpegLocator` + pure `FfmpegArgs`/`FfmpegProgressParser`/`FfmpegEncoderPicker` + the `FramePump` frame producer (see [`docs/ai/output.md`](docs/ai/output.md) → "Live encoder" + [`docs/ai/frame-pipeline.md`](docs/ai/frame-pipeline.md) → "Live frame pipeline")**, **notifications: `INotificationService` seam (`AppNotificationSeverity` Info/Success/Warning/Error) + `NotificationService` (Notification.Wpf toasts, see "Toast notifications")** |
|
||||||
| `Helpers/` | ViewModelBase (INotifyPropertyChanged), RelayCommand, ImageCache, AppLog (file logger), FocusPreservingListBox, OAuthCredentials, **TokenStore (DPAPI session persistence)**, **BuildStamp (wordmark release counter `#N`, incremented by `GenerateBuildStamp` from the local `BuildCounter.txt`; per-build GUID/time are logged to startup.log)**, visibility converters |
|
| `Helpers/` | ViewModelBase (INotifyPropertyChanged), RelayCommand, ImageCache, AppLog (file logger), FocusPreservingListBox, OAuthCredentials, **TokenStore (DPAPI session persistence)**, **BuildStamp (wordmark release counter `#N` = `git rev-list --count HEAD`, so it moves once per COMMIT; per-build GUID/time are logged to startup.log)**, visibility converters |
|
||||||
| `Themes/` | `Controls.xaml` — the single dark-theme source, merged once in `App.xaml` (see `Themes/index.md`) |
|
| `Themes/` | `Controls.xaml` — the single dark-theme source, merged once in `App.xaml` (see `Themes/index.md`) |
|
||||||
| `MainWindow.xaml` | Dark theme; top bar + health banner; work area has a fixed 360px left column and preview column, top-left readouts/resolution and scene strip above preview, lower left panel + preview; bottom bar is an empty spacer |
|
| `MainWindow.xaml` | Dark theme; top bar + health banner; work area has a fixed 360px left column and preview column, top-left readouts/resolution and scene strip above preview, lower left panel + preview; bottom bar is an empty spacer |
|
||||||
|
|
||||||
|
|||||||
+10
-13
@@ -38,11 +38,12 @@
|
|||||||
<BuildStampId>$([System.Guid]::NewGuid().ToString('N').Substring(0,8))</BuildStampId>
|
<BuildStampId>$([System.Guid]::NewGuid().ToString('N').Substring(0,8))</BuildStampId>
|
||||||
<BuildStampTime>$([System.DateTime]::Now.ToString('yyyy-MM-dd HH:mm:ss'))</BuildStampTime>
|
<BuildStampTime>$([System.DateTime]::Now.ToString('yyyy-MM-dd HH:mm:ss'))</BuildStampTime>
|
||||||
<!-- RELEASE COUNTER (creator ruling 2026-09-04): the UI shows a sequential number that
|
<!-- RELEASE COUNTER (creator ruling 2026-09-04): the UI shows a sequential number that
|
||||||
ticks +1 per COMMIT, starting at 13 — a per-BUILD GUID changed on every launch and read
|
ticks +1 per COMMIT — a per-BUILD GUID changed on every launch and read as noise
|
||||||
as noise (rightly). Derived from git rev-list count (stable per commit, no bookkeeping).
|
(rightly). It is git rev-list count of HEAD, evaluated below.
|
||||||
Baseline 241 = count at introduction, first display 13. Missing git or unparsed output
|
⛔ It used to read BuildCounter.txt, add 1 and write it back on EVERY CoreCompile, so it
|
||||||
falls back to the start (build never breaks). GUID + compile time stay in startup.log,
|
counted BUILDS: one day of iteration reached #1122 against 563 commits (2026-11-01).
|
||||||
where build-identity forensics actually live. -->
|
No counter file now: the commit count cannot drift. Missing git falls back to the
|
||||||
|
start, so the build never breaks. GUID + compile time stay in startup.log. -->
|
||||||
<BuildNumberBaseline>17</BuildNumberBaseline>
|
<BuildNumberBaseline>17</BuildNumberBaseline>
|
||||||
<BuildNumberStart>13</BuildNumberStart>
|
<BuildNumberStart>13</BuildNumberStart>
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
@@ -51,14 +52,10 @@
|
|||||||
<Output TaskParameter="ConsoleOutput" PropertyName="CommitCountRaw" />
|
<Output TaskParameter="ConsoleOutput" PropertyName="CommitCountRaw" />
|
||||||
</Exec>
|
</Exec>
|
||||||
<PropertyGroup>
|
<PropertyGroup>
|
||||||
<CommitCount>$(CommitCountRaw.Trim())</CommitCount>
|
<!-- First integer in git's output: the Exec can echo the count twice, and a multi-line value
|
||||||
<BuildCounterFile>$(ProjectDir)BuildCounter.txt</BuildCounterFile>
|
would fail the numeric check below and silently pin the stamp. -->
|
||||||
<PriorBuildCount Condition="Exists('$(BuildCounterFile)')">$([System.IO.File]::ReadAllText('$(BuildCounterFile)').Trim())</PriorBuildCount>
|
<CommitCount>$([System.Text.RegularExpressions.Regex]::Match('$(CommitCountRaw)', '[0-9]+').Value)</CommitCount>
|
||||||
<PriorBuildCount Condition="'$(PriorBuildCount)' == ''">423</PriorBuildCount>
|
<BuildNumber Condition="'$(CommitCount)' != ''">$(CommitCount)</BuildNumber>
|
||||||
<BuildNumber>$([MSBuild]::Add($(PriorBuildCount), 1))</BuildNumber>
|
|
||||||
</PropertyGroup>
|
|
||||||
<WriteLinesToFile File="$(BuildCounterFile)" Lines="$(BuildNumber)" Overwrite="true" WriteOnlyWhenDifferent="false" />
|
|
||||||
<PropertyGroup>
|
|
||||||
<BuildNumber Condition="! $([System.Text.RegularExpressions.Regex]::IsMatch('$(BuildNumber)', '^[0-9]+$'))">$(BuildNumberStart)</BuildNumber>
|
<BuildNumber Condition="! $([System.Text.RegularExpressions.Regex]::IsMatch('$(BuildNumber)', '^[0-9]+$'))">$(BuildNumberStart)</BuildNumber>
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
|
|||||||
Reference in New Issue
Block a user