feat(16-03): WriteTrackTags pipeline with player safety, scan mutex, events, and app wiring

- TagWriter struct with WriteTrackTags entry point orchestrating full pipeline
- PlayerStopper interface + playerAdapter for import-cycle-free player safety
- PipelineLocker interface + pipelineMu on Library for scan/write mutual exclusion
- TrackMetadataChanged event constant + auto-generated TypeScript events
- TagWriter wired into app.go as Wails binding with SetContext in OnStartup
- 5 pipeline integration tests: player safety, scan mutex, orphan cleanup, genre relink, full DB sync
- Lint fixes: static error, else-if, wsl cuddle, golines
This commit is contained in:
2026-03-17 10:55:10 -04:00
parent 2966079625
commit 64322f9353
7 changed files with 707 additions and 6 deletions
+22
View File
@@ -22,6 +22,7 @@ import (
"yellowjacket/backend/playlist"
"yellowjacket/backend/profiling"
"yellowjacket/backend/queue"
"yellowjacket/backend/tagwriter"
)
// YellowJacketApp is the main application struct for Wails.
@@ -37,6 +38,7 @@ type YellowJacketApp struct {
playlist *playlist.Service
queue *queue.Queue
mediaControls mediacontrols.Handler
tagWriter *tagwriter.TagWriter
appContext context.Context
appConfig *config.Config
startupErr error
@@ -115,6 +117,14 @@ func NewYellowJacketApp(
yjApp.logger.WithGroup("player"), yjApp.database,
)
// create tag writer
yjApp.tagWriter = tagwriter.NewTagWriter(
yjApp.logger,
yjApp.database,
&playerAdapter{p: yjApp.player},
yjApp.library,
)
yjApp.FEBindings = []any{
yjApp.FrontendUtil,
yjApp.appConfig,
@@ -122,11 +132,22 @@ func NewYellowJacketApp(
yjApp.playlist,
yjApp.queue,
yjApp.player,
yjApp.tagWriter,
}
return yjApp, nil
}
// playerAdapter wraps *player.Player to satisfy the tagwriter.PlayerStopper
// interface, breaking the import cycle between tagwriter and player.
type playerAdapter struct{ p *player.Player }
func (a *playerAdapter) CurrentFilePath() string {
return a.p.GetCurrentTrackInfo().FilePath
}
func (a *playerAdapter) StopAndRelease() { a.p.UnloadTrack() }
// WindowConfig returns the window configuration for use by the host.
func (yj *YellowJacketApp) WindowConfig() *config.WindowConfig {
return yj.appConfig.Window
@@ -157,6 +178,7 @@ func (yj *YellowJacketApp) OnStartup(ctx context.Context) {
}
yj.player.SetContext(ctx)
yj.tagWriter.SetContext(ctx)
// Wire queue (created in NewYellowJacketApp for Wails binding)
yj.queue.SetContext(ctx)