From 5a1a6b863c3adaa8ec9d087ba130f7676fc9575b Mon Sep 17 00:00:00 2001 From: Paul Buetow Date: Thu, 2 Apr 2026 22:26:43 +0300 Subject: task zz: add Voices()/BuildAttribution() to Provider interface [OCP] Extend audio.Provider with Voices() []string and BuildAttribution() string so all provider-specific behaviour is encapsulated in the implementation rather than scattered as switch-cases across callers. Add package-level VoicesFor(name) and BuildAttributionFor(name, params) for callers (processor, GUI) that need these before constructing a Provider instance. Add AttributionParamsFrom(config, word, ...) so callers can build AttributionParams from the flat Config without a manual provider switch. Implement both new interface methods in OpenAIProvider and GeminiProvider. Update all Provider mock/fake types in tests. Migrate audioVoicesForProvider() and saveAudioAttribution() in both processor.go and gui/generator.go to use the new package-level helpers, replacing the 10+ duplicated switch blocks. Co-Authored-By: Claude Sonnet 4.6 --- internal/processor/processor.go | 35 ++++++----------------------------- internal/processor/processor_test.go | 8 ++++++++ 2 files changed, 14 insertions(+), 29 deletions(-) (limited to 'internal/processor') diff --git a/internal/processor/processor.go b/internal/processor/processor.go index 40487b9..41d6858 100644 --- a/internal/processor/processor.go +++ b/internal/processor/processor.go @@ -311,13 +311,10 @@ func (p *Processor) openAIVoice() string { return "" } +// audioVoicesForProvider returns the voice list for the configured provider +// without needing a Provider instance (uses the package-level VoicesFor). func (p *Processor) audioVoicesForProvider() []string { - switch p.audioProviderName() { - case "gemini": - return audio.GeminiVoices - default: - return audio.OpenAIVoices - } + return audio.VoicesFor(p.audioProviderName()) } func (p *Processor) audioVoiceForProvider() string { @@ -1008,29 +1005,9 @@ func (p *Processor) saveAudioAttribution(word, audioFile string, config *audio.C processedText := audio.ProcessedTextForProvider(config.Provider, word) instruction := audio.InstructionForProvider(config.Provider, config) - var attribution string - switch strings.ToLower(strings.TrimSpace(config.Provider)) { - case "gemini": - attribution = audio.BuildGeminiAttribution(audio.AttributionParams{ - Word: word, - Model: config.GeminiTTSModel, - Voice: config.GeminiVoice, - Speed: config.GeminiSpeed, - Instruction: instruction, - ProcessedText: processedText, - GeneratedAt: time.Now(), - }) - default: - attribution = audio.BuildOpenAIAttribution(audio.AttributionParams{ - Word: word, - Model: config.OpenAIModel, - Voice: config.OpenAIVoice, - Speed: config.OpenAISpeed, - Instruction: instruction, - ProcessedText: processedText, - GeneratedAt: time.Now(), - }) - } + // Build params from the provider-specific sub-config to avoid a manual switch. + params := audio.AttributionParamsFrom(config, word, instruction, processedText, time.Now()) + attribution := audio.BuildAttributionFor(config.Provider, params) // Save to file attrPath := audio.AttributionPath(audioFile) diff --git a/internal/processor/processor_test.go b/internal/processor/processor_test.go index cfa4545..34cc844 100644 --- a/internal/processor/processor_test.go +++ b/internal/processor/processor_test.go @@ -101,6 +101,14 @@ func (f *fakeAudioProvider) IsAvailable() error { return nil } +func (f *fakeAudioProvider) Voices() []string { + return nil +} + +func (f *fakeAudioProvider) BuildAttribution(params audio.AttributionParams) string { + return "" +} + func captureStdout(t *testing.T, fn func()) (output string) { t.Helper() -- cgit v1.2.3