Allow multiple library folders
Build Plugin / build (push) Successful in 2m21s

This commit is contained in:
2025-12-19 23:29:25 +01:00
parent c02469c6d0
commit d3fbaef417
4 changed files with 340 additions and 36 deletions
@@ -1,10 +1,16 @@
using System;
using System.Collections.Generic;
using System.ComponentModel.DataAnnotations;
using System.Linq;
using System.Net.Mime;
using System.Threading.Tasks;
using Jellyfin.Data.Enums;
using Jellyfin.Plugin.JellyLMS.Models;
using Jellyfin.Plugin.JellyLMS.Services;
using MediaBrowser.Controller.Entities;
using MediaBrowser.Controller.Entities.Audio;
using MediaBrowser.Controller.Library;
using MediaBrowser.Model.Entities;
using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Mvc;
@@ -23,6 +29,7 @@ public class JellyLmsController : ControllerBase
private readonly ILmsApiClient _lmsClient;
private readonly LmsPlayerManager _playerManager;
private readonly LmsSessionManager _sessionManager;
private readonly ILibraryManager _libraryManager;
/// <summary>
/// Initializes a new instance of the <see cref="JellyLmsController"/> class.
@@ -30,14 +37,17 @@ public class JellyLmsController : ControllerBase
/// <param name="lmsClient">The LMS API client.</param>
/// <param name="playerManager">The player manager.</param>
/// <param name="sessionManager">The session manager.</param>
/// <param name="libraryManager">The library manager.</param>
public JellyLmsController(
ILmsApiClient lmsClient,
LmsPlayerManager playerManager,
LmsSessionManager sessionManager)
LmsSessionManager sessionManager,
ILibraryManager libraryManager)
{
_lmsClient = lmsClient;
_playerManager = playerManager;
_sessionManager = sessionManager;
_libraryManager = libraryManager;
}
/// <summary>
@@ -285,6 +295,87 @@ public class JellyLmsController : ControllerBase
var success = await _sessionManager.SetVolumeAsync(sessionId, request.Volume).ConfigureAwait(false);
return success ? Ok() : NotFound();
}
/// <summary>
/// Discovers file paths used by Jellyfin's music libraries.
/// Helps users configure path mappings for direct file access.
/// </summary>
/// <returns>Sample file paths from each music library.</returns>
[HttpGet("DiscoverPaths")]
[ProducesResponseType(StatusCodes.Status200OK)]
public ActionResult<DiscoveredPathsResponse> DiscoverPaths()
{
var response = new DiscoveredPathsResponse();
// Get sample audio files from the library
var query = new InternalItemsQuery
{
IncludeItemTypes = [BaseItemKind.Audio],
Limit = 50,
Recursive = true
};
var items = _libraryManager.GetItemsResult(query).Items;
// Extract unique path prefixes
var pathPrefixes = new HashSet<string>();
foreach (var item in items)
{
if (string.IsNullOrEmpty(item.Path))
{
continue;
}
// Add sample paths
if (response.SamplePaths.Count < 5)
{
response.SamplePaths.Add(item.Path);
}
// Try to find common path prefixes
var path = item.Path.Replace('\\', '/');
var parts = path.Split('/');
// Build prefix from first few directory levels
if (parts.Length > 2)
{
// Try different prefix lengths to find common ones
for (var i = 2; i <= Math.Min(4, parts.Length - 1); i++)
{
var prefix = string.Join('/', parts.Take(i));
if (!string.IsNullOrEmpty(prefix) && !prefix.Contains('.', StringComparison.Ordinal))
{
pathPrefixes.Add(prefix);
}
}
}
}
// Sort prefixes by length (shorter = more general)
response.DetectedPrefixes = pathPrefixes
.OrderBy(p => p.Length)
.Take(10)
.ToList();
return Ok(response);
}
}
/// <summary>
/// Response containing discovered file paths from Jellyfin libraries.
/// </summary>
public class DiscoveredPathsResponse
{
/// <summary>
/// Gets or sets sample file paths from the music library.
/// </summary>
public List<string> SamplePaths { get; set; } = [];
/// <summary>
/// Gets or sets detected common path prefixes.
/// </summary>
public List<string> DetectedPrefixes { get; set; } = [];
}
/// <summary>