0.3.32
This commit is contained in:
@@ -62,6 +62,15 @@ type playbackResponse struct {
|
||||
// separate features with separate switches, and a house that has turned the skip button
|
||||
// off has not asked to lose the credits pane with it.
|
||||
EndCreditsAvailable bool `json:"endCreditsAvailable"`
|
||||
// Whether Sonarr can name when this continuing show's next episode airs. Rides here for
|
||||
// the same reason the other availability flags do: the player asks once at the start of
|
||||
// playback and the notice itself takes no further request. Absent (all fields blank)
|
||||
// means either the show isn't Sonarr-tracked, isn't continuing, or has no scheduled
|
||||
// airing to report — the client shows nothing in every one of those cases.
|
||||
NextAiringAvailable bool `json:"nextAiringAvailable"`
|
||||
NextAiringLabel string `json:"nextAiringLabel,omitempty"`
|
||||
NextAiringDayLabel string `json:"nextAiringDayLabel,omitempty"`
|
||||
NextAiringEpisodeCode string `json:"nextAiringEpisodeCode,omitempty"`
|
||||
}
|
||||
|
||||
type playableSubtitle struct {
|
||||
@@ -114,6 +123,10 @@ type nextEpisodeResponse struct {
|
||||
TrickplayAvailable bool `json:"trickplayAvailable"`
|
||||
SkipIntroAvailable bool `json:"skipIntroAvailable"`
|
||||
EndCreditsAvailable bool `json:"endCreditsAvailable"`
|
||||
NextAiringAvailable bool `json:"nextAiringAvailable"`
|
||||
NextAiringLabel string `json:"nextAiringLabel,omitempty"`
|
||||
NextAiringDayLabel string `json:"nextAiringDayLabel,omitempty"`
|
||||
NextAiringEpisodeCode string `json:"nextAiringEpisodeCode,omitempty"`
|
||||
}
|
||||
|
||||
// handlePlayback resolves what to actually play.
|
||||
@@ -235,6 +248,8 @@ func (s *Server) handlePlayback(w http.ResponseWriter, r *http.Request, sess sto
|
||||
"negotiation_duration", time.Since(negotiationStarted).Round(time.Millisecond),
|
||||
)
|
||||
|
||||
nextAiringAvailable, nextAiringLabel, nextAiringDayLabel, nextAiringCode :=
|
||||
s.nextAiringFieldsFor(ctx, target)
|
||||
writeJSON(w, http.StatusOK, playbackResponse{
|
||||
ItemID: target.ID,
|
||||
Title: title,
|
||||
@@ -257,6 +272,10 @@ func (s *Server) handlePlayback(w http.ResponseWriter, r *http.Request, sess sto
|
||||
TrickplayAvailable: s.trickplayEnabled(ctx),
|
||||
SkipIntroAvailable: s.skipIntroEnabled(ctx),
|
||||
EndCreditsAvailable: s.endCreditsEnabled(ctx),
|
||||
NextAiringAvailable: nextAiringAvailable,
|
||||
NextAiringLabel: nextAiringLabel,
|
||||
NextAiringDayLabel: nextAiringDayLabel,
|
||||
NextAiringEpisodeCode: nextAiringCode,
|
||||
})
|
||||
}
|
||||
|
||||
@@ -336,6 +355,22 @@ func (s *Server) firstPlayableEpisode(
|
||||
return &summary, nil
|
||||
}
|
||||
|
||||
// nextAiringFieldsFor answers the current episode's own show's next airing, never the
|
||||
// episode being played itself. It only ever asks Sonarr about a series that is actually
|
||||
// known — a hinted playback response that skipped the Emby lookup and so carries no
|
||||
// SeriesName simply gets nothing, the same silent degradation every other availability
|
||||
// flag here takes.
|
||||
func (s *Server) nextAiringFieldsFor(ctx context.Context, item emby.Summary) (available bool, label, dayLabel, code string) {
|
||||
if !strings.EqualFold(item.Type, "Episode") {
|
||||
return false, "", "", ""
|
||||
}
|
||||
info, ok := s.nextAiringInfoFor(ctx, item.SeriesName)
|
||||
if !ok {
|
||||
return false, "", "", ""
|
||||
}
|
||||
return true, info.Label, info.DayLabel, info.EpisodeCode
|
||||
}
|
||||
|
||||
func episodeCode(item emby.Summary) string {
|
||||
if !strings.EqualFold(item.Type, "Episode") || item.ParentIndexNumber < 0 || item.IndexNumber <= 0 {
|
||||
return ""
|
||||
@@ -435,20 +470,26 @@ func (s *Server) handleNextEpisode(w http.ResponseWriter, r *http.Request, sess
|
||||
|
||||
// The metadata-only shape. Everything below this point is a PlaybackInfo negotiation,
|
||||
// and a client that said it does not want one yet must not be given one anyway.
|
||||
nextAiringAvailable, nextAiringLabel, nextAiringDayLabel, nextAiringCode :=
|
||||
s.nextAiringFieldsFor(ctx, next)
|
||||
if !nextEpisodeWantsStream(r) {
|
||||
s.playbackTitles.remember(next.ID, title)
|
||||
s.loggerFor(ctx).Debug("next episode identified",
|
||||
"title", title, "item", next.ID, "after_item", itemID)
|
||||
writeJSON(w, http.StatusOK, nextEpisodeResponse{
|
||||
Item: raw,
|
||||
Title: title,
|
||||
StreamReady: false,
|
||||
ResumePositionMs: max64(next.UserData.PlaybackPositionTicks/ticksPerMillisecond, 0),
|
||||
Subtitles: []playableSubtitle{},
|
||||
SubtitlesEnabled: true,
|
||||
TrickplayAvailable: s.trickplayEnabled(ctx),
|
||||
SkipIntroAvailable: s.skipIntroEnabled(ctx),
|
||||
EndCreditsAvailable: s.endCreditsEnabled(ctx),
|
||||
Item: raw,
|
||||
Title: title,
|
||||
StreamReady: false,
|
||||
ResumePositionMs: max64(next.UserData.PlaybackPositionTicks/ticksPerMillisecond, 0),
|
||||
Subtitles: []playableSubtitle{},
|
||||
SubtitlesEnabled: true,
|
||||
TrickplayAvailable: s.trickplayEnabled(ctx),
|
||||
SkipIntroAvailable: s.skipIntroEnabled(ctx),
|
||||
EndCreditsAvailable: s.endCreditsEnabled(ctx),
|
||||
NextAiringAvailable: nextAiringAvailable,
|
||||
NextAiringLabel: nextAiringLabel,
|
||||
NextAiringDayLabel: nextAiringDayLabel,
|
||||
NextAiringEpisodeCode: nextAiringCode,
|
||||
})
|
||||
return
|
||||
}
|
||||
@@ -491,6 +532,10 @@ func (s *Server) handleNextEpisode(w http.ResponseWriter, r *http.Request, sess
|
||||
TrickplayAvailable: s.trickplayEnabled(ctx),
|
||||
SkipIntroAvailable: s.skipIntroEnabled(ctx),
|
||||
EndCreditsAvailable: s.endCreditsEnabled(ctx),
|
||||
NextAiringAvailable: nextAiringAvailable,
|
||||
NextAiringLabel: nextAiringLabel,
|
||||
NextAiringDayLabel: nextAiringDayLabel,
|
||||
NextAiringEpisodeCode: nextAiringCode,
|
||||
})
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user