mirror of
https://github.com/navidrome/navidrome.git
synced 2026-10-18 07:30:29 +00:00
feat(radio): publish radio metadata events
Signed-off-by: hiyukoim <11803292+hiyukoim@users.noreply.github.com>
This commit is contained in:
parent
8f70e0e4f3
commit
2109175304
@ -84,7 +84,8 @@ func CreateNativeAPIRouter(ctx context.Context) *nativeapi.Router {
|
||||
library := core.NewLibrary(dataStore, modelScanner, watcher, broker, manager)
|
||||
user := core.NewUser(dataStore, manager)
|
||||
maintenance := core.NewMaintenance(dataStore)
|
||||
metadataManager := radio.NewMetadataManagerService()
|
||||
titlePublisher := events.NewRadioMetadataPublisher(broker)
|
||||
metadataManager := radio.NewMetadataManagerService(titlePublisher)
|
||||
router := nativeapi.New(dataStore, share, playlistsPlaylists, insights, library, user, maintenance, manager, imageUploadService, metadataManager)
|
||||
return router
|
||||
}
|
||||
@ -249,7 +250,7 @@ func getPluginManager() *plugins.Manager {
|
||||
|
||||
// wire_injectors.go:
|
||||
|
||||
var allProviders = wire.NewSet(core.Set, artwork.Set, server.New, subsonic.New, jellyfin.New, nativeapi.New, public.New, persistence.New, lastfm.NewRouter, listenbrainz.NewRouter, events.GetBroker, scanner.New, scanner.GetWatcher, metrics.GetPrometheusInstance, db.Db, plugins.GetManager, sonic.New, wire.Bind(new(agents.PluginLoader), new(*plugins.Manager)), wire.Bind(new(scrobbler.PluginLoader), new(*plugins.Manager)), wire.Bind(new(lyrics.PluginLoader), new(*plugins.Manager)), wire.Bind(new(sonic.PluginLoader), new(*plugins.Manager)), wire.Bind(new(sonic.Engine), new(*sonic.Sonic)), wire.Bind(new(nativeapi.PluginManager), new(*plugins.Manager)), wire.Bind(new(nativeapi.RadioMetadataManager), new(*radio.MetadataManager)), wire.Bind(new(core.PluginUnloader), new(*plugins.Manager)), wire.Bind(new(plugins.PluginMetricsRecorder), new(metrics.Metrics)), wire.Bind(new(core.Watcher), new(scanner.Watcher)))
|
||||
var allProviders = wire.NewSet(core.Set, artwork.Set, server.New, subsonic.New, jellyfin.New, nativeapi.New, public.New, persistence.New, lastfm.NewRouter, listenbrainz.NewRouter, events.GetBroker, events.NewRadioMetadataPublisher, scanner.New, scanner.GetWatcher, metrics.GetPrometheusInstance, db.Db, plugins.GetManager, sonic.New, wire.Bind(new(agents.PluginLoader), new(*plugins.Manager)), wire.Bind(new(scrobbler.PluginLoader), new(*plugins.Manager)), wire.Bind(new(lyrics.PluginLoader), new(*plugins.Manager)), wire.Bind(new(sonic.PluginLoader), new(*plugins.Manager)), wire.Bind(new(sonic.Engine), new(*sonic.Sonic)), wire.Bind(new(nativeapi.PluginManager), new(*plugins.Manager)), wire.Bind(new(nativeapi.RadioMetadataManager), new(*radio.MetadataManager)), wire.Bind(new(core.PluginUnloader), new(*plugins.Manager)), wire.Bind(new(plugins.PluginMetricsRecorder), new(metrics.Metrics)), wire.Bind(new(core.Watcher), new(scanner.Watcher)))
|
||||
|
||||
func GetPluginManager(ctx context.Context) *plugins.Manager {
|
||||
manager := getPluginManager()
|
||||
|
||||
@ -42,6 +42,7 @@ var allProviders = wire.NewSet(
|
||||
lastfm.NewRouter,
|
||||
listenbrainz.NewRouter,
|
||||
events.GetBroker,
|
||||
events.NewRadioMetadataPublisher,
|
||||
scanner.New,
|
||||
scanner.GetWatcher,
|
||||
metrics.GetPrometheusInstance,
|
||||
|
||||
@ -7,8 +7,8 @@ import (
|
||||
"github.com/navidrome/navidrome/core/radio/icy"
|
||||
)
|
||||
|
||||
func NewMetadataManagerService() *MetadataManager {
|
||||
func NewMetadataManagerService(publisher TitlePublisher) *MetadataManager {
|
||||
return NewMetadataManager(func(ctx context.Context, streamURL string, handleTitle func(string)) error {
|
||||
return icy.ReadHTTPStreamTitles(ctx, http.DefaultClient, streamURL, handleTitle)
|
||||
}, nil)
|
||||
}, publisher)
|
||||
}
|
||||
|
||||
@ -7,6 +7,8 @@ import (
|
||||
"strings"
|
||||
"time"
|
||||
"unicode"
|
||||
|
||||
coreradio "github.com/navidrome/navidrome/core/radio"
|
||||
)
|
||||
|
||||
type eventCtxKey string
|
||||
@ -68,6 +70,26 @@ type NowPlayingCount struct {
|
||||
Count int `json:"count"`
|
||||
}
|
||||
|
||||
type RadioNowPlaying struct {
|
||||
baseEvent
|
||||
RadioID string `json:"radioId"`
|
||||
Title string `json:"title"`
|
||||
UpdatedAt time.Time `json:"updatedAt"`
|
||||
}
|
||||
|
||||
func NewRadioMetadataPublisher(broker Broker) coreradio.TitlePublisher {
|
||||
return func(ctx context.Context, update coreradio.TitleUpdate) {
|
||||
if broker == nil {
|
||||
return
|
||||
}
|
||||
broker.SendMessage(ctx, &RadioNowPlaying{
|
||||
RadioID: update.RadioID,
|
||||
Title: update.Title,
|
||||
UpdatedAt: update.UpdatedAt,
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func (rr *RefreshResource) With(resource string, ids ...string) *RefreshResource {
|
||||
if rr.resources == nil {
|
||||
rr.resources = make(map[string][]string)
|
||||
|
||||
@ -1,6 +1,11 @@
|
||||
package events
|
||||
|
||||
import (
|
||||
"context"
|
||||
"net/http"
|
||||
"time"
|
||||
|
||||
coreradio "github.com/navidrome/navidrome/core/radio"
|
||||
. "github.com/onsi/ginkgo/v2"
|
||||
. "github.com/onsi/gomega"
|
||||
)
|
||||
@ -21,6 +26,41 @@ var _ = Describe("Events", func() {
|
||||
})
|
||||
})
|
||||
|
||||
Describe("RadioNowPlaying", func() {
|
||||
It("serialises with a stable event name and payload", func() {
|
||||
updatedAt := time.Date(2026, time.June, 30, 12, 34, 56, 0, time.UTC)
|
||||
event := &RadioNowPlaying{
|
||||
RadioID: "rd-1",
|
||||
Title: "Artist - Title",
|
||||
UpdatedAt: updatedAt,
|
||||
}
|
||||
|
||||
Expect(event.Name(event)).To(Equal("radioNowPlaying"))
|
||||
Expect(event.Data(event)).To(Equal(`{"radioId":"rd-1","title":"Artist - Title","updatedAt":"2026-06-30T12:34:56Z"}`))
|
||||
})
|
||||
|
||||
It("publishes metadata updates through the broker", func() {
|
||||
ctx := context.Background()
|
||||
updatedAt := time.Date(2026, time.June, 30, 12, 34, 56, 0, time.UTC)
|
||||
broker := &capturingBroker{}
|
||||
|
||||
publish := NewRadioMetadataPublisher(broker)
|
||||
publish(ctx, coreradio.TitleUpdate{
|
||||
RadioID: "rd-1",
|
||||
Title: "Artist - Title",
|
||||
UpdatedAt: updatedAt,
|
||||
})
|
||||
|
||||
Expect(broker.ctx).To(Equal(ctx))
|
||||
Expect(broker.broadcast).To(BeNil())
|
||||
Expect(broker.event).To(Equal(&RadioNowPlaying{
|
||||
RadioID: "rd-1",
|
||||
Title: "Artist - Title",
|
||||
UpdatedAt: updatedAt,
|
||||
}))
|
||||
})
|
||||
})
|
||||
|
||||
Describe("RefreshResource", func() {
|
||||
var rr *RefreshResource
|
||||
BeforeEach(func() {
|
||||
@ -44,3 +84,20 @@ var _ = Describe("Events", func() {
|
||||
})
|
||||
})
|
||||
})
|
||||
|
||||
type capturingBroker struct {
|
||||
ctx context.Context
|
||||
event Event
|
||||
broadcast Event
|
||||
}
|
||||
|
||||
func (b *capturingBroker) ServeHTTP(http.ResponseWriter, *http.Request) {}
|
||||
|
||||
func (b *capturingBroker) SendMessage(ctx context.Context, event Event) {
|
||||
b.ctx = ctx
|
||||
b.event = event
|
||||
}
|
||||
|
||||
func (b *capturingBroker) SendBroadcastMessage(_ context.Context, event Event) {
|
||||
b.broadcast = event
|
||||
}
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user