package factory import ( "fmt" "io" "net/http" "os" "strings" "aoiprxkit" "github.com/jan/fm-rds-tx/internal/config" "github.com/jan/fm-rds-tx/internal/ingest" "github.com/jan/fm-rds-tx/internal/ingest/adapters/httpraw" "github.com/jan/fm-rds-tx/internal/ingest/adapters/icecast" "github.com/jan/fm-rds-tx/internal/ingest/adapters/srt" "github.com/jan/fm-rds-tx/internal/ingest/adapters/stdinpcm" ) type Deps struct { Stdin io.Reader HTTP *http.Client SRTOpener aoiprxkit.SRTConnOpener } type AudioIngress interface { WritePCM16(data []byte) (int, error) } func BuildSource(cfg config.Config, deps Deps) (ingest.Source, AudioIngress, error) { switch normalizeIngestKind(cfg.Ingest.Kind) { case "", "none": return nil, nil, nil case "stdin", "stdin-pcm": reader := deps.Stdin if reader == nil { reader = os.Stdin } src := stdinpcm.New("stdin-main", reader, cfg.Ingest.Stdin.SampleRateHz, cfg.Ingest.Stdin.Channels, 1024) return src, nil, nil case "http-raw": src := httpraw.New("http-raw-main", cfg.Ingest.HTTPRaw.SampleRateHz, cfg.Ingest.HTTPRaw.Channels) return src, src, nil case "icecast": src := icecast.New( "icecast-main", cfg.Ingest.Icecast.URL, deps.HTTP, icecast.ReconnectConfig{ Enabled: cfg.Ingest.Reconnect.Enabled, InitialBackoffMs: cfg.Ingest.Reconnect.InitialBackoffMs, MaxBackoffMs: cfg.Ingest.Reconnect.MaxBackoffMs, }, icecast.WithDecoderPreference(cfg.Ingest.Icecast.Decoder), ) return src, nil, nil case "srt": srtCfg := aoiprxkit.SRTConfig{ URL: cfg.Ingest.SRT.URL, Mode: cfg.Ingest.SRT.Mode, SampleRateHz: cfg.Ingest.SRT.SampleRateHz, Channels: cfg.Ingest.SRT.Channels, } opts := []srt.Option{} if deps.SRTOpener != nil { opts = append(opts, srt.WithConnOpener(deps.SRTOpener)) } src := srt.New("srt-main", srtCfg, opts...) return src, nil, nil default: return nil, nil, fmt.Errorf("unsupported ingest kind: %s", cfg.Ingest.Kind) } } func SampleRateForKind(cfg config.Config) int { switch normalizeIngestKind(cfg.Ingest.Kind) { case "stdin", "stdin-pcm": if cfg.Ingest.Stdin.SampleRateHz > 0 { return cfg.Ingest.Stdin.SampleRateHz } case "http-raw": if cfg.Ingest.HTTPRaw.SampleRateHz > 0 { return cfg.Ingest.HTTPRaw.SampleRateHz } case "icecast": return 44100 case "srt": if cfg.Ingest.SRT.SampleRateHz > 0 { return cfg.Ingest.SRT.SampleRateHz } } return 44100 } func normalizeIngestKind(kind string) string { return strings.ToLower(strings.TrimSpace(kind)) }