Keep the queried item's media source as the playback default

This commit is contained in:
Shadowghost
2026-06-05 19:41:08 +02:00
parent 4459147788
commit 6c931dcdda
4 changed files with 112 additions and 4 deletions

View File

@@ -0,0 +1,99 @@
using System;
using System.Globalization;
using Jellyfin.Api.Helpers;
using MediaBrowser.Common.Net;
using MediaBrowser.Controller.Configuration;
using MediaBrowser.Controller.Devices;
using MediaBrowser.Controller.Library;
using MediaBrowser.Controller.MediaEncoding;
using MediaBrowser.Model.Dto;
using MediaBrowser.Model.MediaInfo;
using Microsoft.Extensions.Logging;
using Moq;
using Xunit;
namespace Jellyfin.Api.Tests.Helpers
{
public class MediaInfoHelperTests
{
private static MediaInfoHelper CreateHelper()
{
return new MediaInfoHelper(
Mock.Of<IUserManager>(),
Mock.Of<ILibraryManager>(),
Mock.Of<IMediaSourceManager>(),
Mock.Of<IMediaEncoder>(),
Mock.Of<IServerConfigurationManager>(),
Mock.Of<ILogger<MediaInfoHelper>>(),
Mock.Of<INetworkManager>(),
Mock.Of<IDeviceManager>());
}
private static MediaSourceInfo CreateSource(Guid itemId, int bitrate, bool supportsDirectPlay = true)
{
return new MediaSourceInfo
{
Id = itemId.ToString("N", CultureInfo.InvariantCulture),
Protocol = MediaProtocol.File,
Bitrate = bitrate,
SupportsDirectPlay = supportsDirectPlay,
SupportsDirectStream = true,
SupportsTranscoding = true
};
}
[Fact]
public void SortMediaSources_PreferredItemExceedsBitrate_StaysDefault()
{
// The version the user was watching (the queried item) must stay the default
// even when a sibling version fits the bitrate limit better, since the resume
// position belongs to that exact version.
var preferredItemId = Guid.NewGuid();
var preferredSource = CreateSource(preferredItemId, bitrate: 80_000_000, supportsDirectPlay: false);
var siblingSource = CreateSource(Guid.NewGuid(), bitrate: 8_000_000);
var result = new PlaybackInfoResponse
{
MediaSources = [siblingSource, preferredSource]
};
CreateHelper().SortMediaSources(result, maxBitrate: 20_000_000, preferredItemId);
Assert.Equal(preferredSource.Id, result.MediaSources[0].Id);
}
[Fact]
public void SortMediaSources_NoPreferredItem_OrdersByPlayability()
{
var directPlay = CreateSource(Guid.NewGuid(), bitrate: 8_000_000);
var transcodeOnly = CreateSource(Guid.NewGuid(), bitrate: 8_000_000, supportsDirectPlay: false);
transcodeOnly.SupportsDirectStream = false;
var result = new PlaybackInfoResponse
{
MediaSources = [transcodeOnly, directPlay]
};
CreateHelper().SortMediaSources(result, maxBitrate: 20_000_000);
Assert.Equal(directPlay.Id, result.MediaSources[0].Id);
}
[Fact]
public void SortMediaSources_PreferredIdNotInSources_KeepsPlayabilityOrder()
{
var directPlay = CreateSource(Guid.NewGuid(), bitrate: 8_000_000);
var transcodeOnly = CreateSource(Guid.NewGuid(), bitrate: 8_000_000, supportsDirectPlay: false);
transcodeOnly.SupportsDirectStream = false;
var result = new PlaybackInfoResponse
{
MediaSources = [transcodeOnly, directPlay]
};
CreateHelper().SortMediaSources(result, maxBitrate: 20_000_000, Guid.NewGuid());
Assert.Equal(directPlay.Id, result.MediaSources[0].Id);
}
}
}