Skip to content

Commit

Permalink
Fix Bigscreen compatibility issues (#83)
Browse files Browse the repository at this point in the history
  • Loading branch information
Nullcaller authored Nov 3, 2024
1 parent 298a221 commit 29e9e6d
Show file tree
Hide file tree
Showing 3 changed files with 64 additions and 18 deletions.
18 changes: 17 additions & 1 deletion src/Jellyfin.Plugin.Dlna/Api/DlnaServerController.cs
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
using System.IO;
using System.Net.Mime;
using System.Threading.Tasks;
using Jellyfin.Extensions;
using Jellyfin.Plugin.Dlna.Model;
using MediaBrowser.Common.Api;
using MediaBrowser.Model.Net;
Expand All @@ -21,6 +22,8 @@ namespace Jellyfin.Plugin.Dlna.Api;
[Authorize(Policy = Policies.AnonymousLanAccessPolicy)]
public class DlnaServerController : ControllerBase
{
private static readonly string[] _relativePathUserAgents = { "Bigscreen" };

private readonly IDlnaManager _dlnaManager;
private readonly IContentDirectory _contentDirectory;
private readonly IConnectionManager _connectionManager;
Expand Down Expand Up @@ -59,7 +62,15 @@ public DlnaServerController(
[Produces(MediaTypeNames.Text.Xml)]
public ActionResult<string> GetDescriptionXml([FromRoute, Required] string serverId)
{
var url = GetAbsoluteUri();
var useRelativePath = false;
string? userAgent = Request.Headers.UserAgent;
if (userAgent is not null)
{
userAgent = userAgent.Substring(0, userAgent.IndexOf('/'));
useRelativePath = _relativePathUserAgents.Contains(userAgent, StringComparison.Ordinal);
}

var url = useRelativePath ? GetRelativePath() : GetAbsoluteUri();
var serverAddress = url.Substring(0, url.IndexOf("/dlna/", StringComparison.OrdinalIgnoreCase));
var xml = _dlnaManager.GetServerDescriptionXml(Request.Headers, serverId, serverAddress);
return Ok(xml);
Expand Down Expand Up @@ -279,6 +290,11 @@ private string GetAbsoluteUri()
return $"{Request.Scheme}://{Request.Host}{Request.PathBase}{Request.Path}";
}

private string GetRelativePath()
{
return $"{Request.PathBase}{Request.Path}";
}

private Task<ControlResponse> ProcessControlRequestInternalAsync(string id, Stream requestStream, IUpnpService service)
{
return service.ProcessControlRequestAsync(new ControlRequest(Request.Headers)
Expand Down
63 changes: 47 additions & 16 deletions src/Jellyfin.Plugin.Dlna/ContentDirectory/ControlHandler.cs
Original file line number Diff line number Diff line change
Expand Up @@ -681,11 +681,7 @@ private QueryResult<ServerItem> GetMusicFolders(BaseItem item, User user, StubTy
new(item, StubType.FavoriteSongs)
};

if (limit < serverItems.Length)
{
serverItems = serverItems[..limit.Value];
}

serverItems = GetTrimmedServerItemsArray(serverItems, startIndex, limit);
return new QueryResult<ServerItem>(
startIndex,
serverItems.Length,
Expand Down Expand Up @@ -737,11 +733,7 @@ private QueryResult<ServerItem> GetMovieFolders(BaseItem item, User user, StubTy
new(item, StubType.Genres)
};

if (limit < array.Length)
{
array = array[..limit.Value];
}

array = GetTrimmedServerItemsArray(array, startIndex, limit);
return new QueryResult<ServerItem>(
startIndex,
array.Length,
Expand Down Expand Up @@ -821,11 +813,7 @@ private QueryResult<ServerItem> GetTvFolders(BaseItem item, User user, StubType?
new(item, StubType.Genres)
};

if (limit < serverItems.Length)
{
serverItems = serverItems[..limit.Value];
}

serverItems = GetTrimmedServerItemsArray(serverItems, startIndex, limit);
return new QueryResult<ServerItem>(
startIndex,
serverItems.Length,
Expand Down Expand Up @@ -1023,18 +1011,34 @@ private QueryResult<ServerItem> GetLatest(BaseItem parent, InternalItemsQuery qu
{
query.OrderBy = Array.Empty<(ItemSortBy, SortOrder)>();

int limit;

if (query.StartIndex > 0)
{
limit = (query.Limit <= 0) ? int.MaxValue : (query.StartIndex.Value + (query.Limit ?? 50));
}
else
{
limit = query.Limit ?? 50;
}

var items = _userViewManager.GetLatestItems(
new LatestItemsQuery
{
// User cannot be null here as the caller has set it
User = query.User!,
Limit = query.Limit ?? 50,
Limit = limit,
IncludeItemTypes = new[] { itemType },
ParentId = parent?.Id ?? Guid.Empty,
GroupItems = true
},
query.DtoOptions).Select(i => i.Item1 ?? i.Item2.FirstOrDefault()).Where(i => i is not null).ToArray();

if (query.StartIndex > 0)
{
items = (items.Length <= query.StartIndex) ? Array.Empty<BaseItem>() : items[query.StartIndex.Value..];
}

return ToResult(query.StartIndex, items);
}

Expand Down Expand Up @@ -1243,4 +1247,31 @@ private ServerItem ParseItemId(string id)

return new ServerItem(_libraryManager.GetUserRootFolder(), null);
}

/// <summary>
/// Discards elements before startIndex and elements after startIndex+limit from an array of <see cref="ServerItem"/>.
/// </summary>
/// <param name="serverItems">An array of <see cref="ServerItem"/>.</param>
/// <param name="startIndex">The start index.</param>
/// <param name="limit">The maximum number to return.</param>
/// <returns>The corresponding trimmed array of <see cref="ServerItem"/></returns>
private static ServerItem[] GetTrimmedServerItemsArray(ServerItem[] serverItems, int? startIndex, int? limit)
{
if (startIndex >= serverItems.Length)
{
return Array.Empty<ServerItem>();
}

if (startIndex > 0)
{
serverItems = serverItems[startIndex.Value..];
}

if (limit < serverItems.Length)
{
serverItems = serverItems[..limit.Value];
}

return serverItems;
}
}
1 change: 0 additions & 1 deletion src/Jellyfin.Plugin.Dlna/Server/DescriptionXmlBuilder.cs
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,6 @@ public class DescriptionXmlBuilder
public DescriptionXmlBuilder(DlnaDeviceProfile profile, string serverUdn, string serverAddress, string serverName, string serverId)
{
ArgumentException.ThrowIfNullOrEmpty(serverUdn);
ArgumentException.ThrowIfNullOrEmpty(serverAddress);

_profile = profile;
_serverUdn = serverUdn;
Expand Down

0 comments on commit 29e9e6d

Please sign in to comment.