Go-based FM stereo transmitter with RDS, Windows-first and cross-platform
Вы не можете выбрать более 25 тем Темы должны начинаться с буквы или цифры, могут содержать дефисы(-) и должны содержать не более 35 символов.

97 строки
2.5KB

  1. package factory
  2. import (
  3. "fmt"
  4. "io"
  5. "net/http"
  6. "os"
  7. "strings"
  8. "aoiprxkit"
  9. "github.com/jan/fm-rds-tx/internal/config"
  10. "github.com/jan/fm-rds-tx/internal/ingest"
  11. "github.com/jan/fm-rds-tx/internal/ingest/adapters/httpraw"
  12. "github.com/jan/fm-rds-tx/internal/ingest/adapters/icecast"
  13. "github.com/jan/fm-rds-tx/internal/ingest/adapters/srt"
  14. "github.com/jan/fm-rds-tx/internal/ingest/adapters/stdinpcm"
  15. )
  16. type Deps struct {
  17. Stdin io.Reader
  18. HTTP *http.Client
  19. SRTOpener aoiprxkit.SRTConnOpener
  20. }
  21. type AudioIngress interface {
  22. WritePCM16(data []byte) (int, error)
  23. }
  24. func BuildSource(cfg config.Config, deps Deps) (ingest.Source, AudioIngress, error) {
  25. switch normalizeIngestKind(cfg.Ingest.Kind) {
  26. case "", "none":
  27. return nil, nil, nil
  28. case "stdin", "stdin-pcm":
  29. reader := deps.Stdin
  30. if reader == nil {
  31. reader = os.Stdin
  32. }
  33. src := stdinpcm.New("stdin-main", reader, cfg.Ingest.Stdin.SampleRateHz, cfg.Ingest.Stdin.Channels, 1024)
  34. return src, nil, nil
  35. case "http-raw":
  36. src := httpraw.New("http-raw-main", cfg.Ingest.HTTPRaw.SampleRateHz, cfg.Ingest.HTTPRaw.Channels)
  37. return src, src, nil
  38. case "icecast":
  39. src := icecast.New(
  40. "icecast-main",
  41. cfg.Ingest.Icecast.URL,
  42. deps.HTTP,
  43. icecast.ReconnectConfig{
  44. Enabled: cfg.Ingest.Reconnect.Enabled,
  45. InitialBackoffMs: cfg.Ingest.Reconnect.InitialBackoffMs,
  46. MaxBackoffMs: cfg.Ingest.Reconnect.MaxBackoffMs,
  47. },
  48. icecast.WithDecoderPreference(cfg.Ingest.Icecast.Decoder),
  49. )
  50. return src, nil, nil
  51. case "srt":
  52. srtCfg := aoiprxkit.SRTConfig{
  53. URL: cfg.Ingest.SRT.URL,
  54. Mode: cfg.Ingest.SRT.Mode,
  55. SampleRateHz: cfg.Ingest.SRT.SampleRateHz,
  56. Channels: cfg.Ingest.SRT.Channels,
  57. }
  58. opts := []srt.Option{}
  59. if deps.SRTOpener != nil {
  60. opts = append(opts, srt.WithConnOpener(deps.SRTOpener))
  61. }
  62. src := srt.New("srt-main", srtCfg, opts...)
  63. return src, nil, nil
  64. default:
  65. return nil, nil, fmt.Errorf("unsupported ingest kind: %s", cfg.Ingest.Kind)
  66. }
  67. }
  68. func SampleRateForKind(cfg config.Config) int {
  69. switch normalizeIngestKind(cfg.Ingest.Kind) {
  70. case "stdin", "stdin-pcm":
  71. if cfg.Ingest.Stdin.SampleRateHz > 0 {
  72. return cfg.Ingest.Stdin.SampleRateHz
  73. }
  74. case "http-raw":
  75. if cfg.Ingest.HTTPRaw.SampleRateHz > 0 {
  76. return cfg.Ingest.HTTPRaw.SampleRateHz
  77. }
  78. case "icecast":
  79. return 44100
  80. case "srt":
  81. if cfg.Ingest.SRT.SampleRateHz > 0 {
  82. return cfg.Ingest.SRT.SampleRateHz
  83. }
  84. }
  85. return 44100
  86. }
  87. func normalizeIngestKind(kind string) string {
  88. return strings.ToLower(strings.TrimSpace(kind))
  89. }