Merge pull request #6793 from Bond-009/rootedpath
Add some docs and tests
This commit is contained in:
commit
3906343c91
|
@ -1,5 +1,3 @@
|
|||
#pragma warning disable CS1591
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Globalization;
|
||||
|
@ -23,6 +21,11 @@ namespace Emby.Server.Implementations.IO
|
|||
private readonly string _tempPath;
|
||||
private static readonly bool _isEnvironmentCaseInsensitive = OperatingSystem.IsWindows();
|
||||
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="ManagedFileSystem"/> class.
|
||||
/// </summary>
|
||||
/// <param name="logger">The <see cref="ILogger"/> instance to use.</param>
|
||||
/// <param name="applicationPaths">The <see cref="IApplicationPaths"/> instance to use.</param>
|
||||
public ManagedFileSystem(
|
||||
ILogger<ManagedFileSystem> logger,
|
||||
IApplicationPaths applicationPaths)
|
||||
|
@ -31,6 +34,7 @@ namespace Emby.Server.Implementations.IO
|
|||
_tempPath = applicationPaths.TempDirectory;
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public virtual void AddShortcutHandler(IShortcutHandler handler)
|
||||
{
|
||||
_shortcutHandlers.Add(handler);
|
||||
|
@ -72,6 +76,7 @@ namespace Emby.Server.Implementations.IO
|
|||
return handler?.Resolve(filename);
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public virtual string MakeAbsolutePath(string folderPath, string filePath)
|
||||
{
|
||||
// path is actually a stream
|
||||
|
@ -358,11 +363,13 @@ namespace Emby.Server.Implementations.IO
|
|||
return GetCreationTimeUtc(GetFileSystemInfo(path));
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public virtual DateTime GetCreationTimeUtc(FileSystemMetadata info)
|
||||
{
|
||||
return info.CreationTimeUtc;
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public virtual DateTime GetLastWriteTimeUtc(FileSystemMetadata info)
|
||||
{
|
||||
return info.LastWriteTimeUtc;
|
||||
|
@ -397,6 +404,7 @@ namespace Emby.Server.Implementations.IO
|
|||
return GetLastWriteTimeUtc(GetFileSystemInfo(path));
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public virtual void SetHidden(string path, bool isHidden)
|
||||
{
|
||||
if (!OperatingSystem.IsWindows())
|
||||
|
@ -421,6 +429,7 @@ namespace Emby.Server.Implementations.IO
|
|||
}
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public virtual void SetAttributes(string path, bool isHidden, bool readOnly)
|
||||
{
|
||||
if (!OperatingSystem.IsWindows())
|
||||
|
@ -444,7 +453,7 @@ namespace Emby.Server.Implementations.IO
|
|||
|
||||
if (readOnly)
|
||||
{
|
||||
attributes = attributes | FileAttributes.ReadOnly;
|
||||
attributes |= FileAttributes.ReadOnly;
|
||||
}
|
||||
else
|
||||
{
|
||||
|
@ -453,7 +462,7 @@ namespace Emby.Server.Implementations.IO
|
|||
|
||||
if (isHidden)
|
||||
{
|
||||
attributes = attributes | FileAttributes.Hidden;
|
||||
attributes |= FileAttributes.Hidden;
|
||||
}
|
||||
else
|
||||
{
|
||||
|
@ -498,6 +507,7 @@ namespace Emby.Server.Implementations.IO
|
|||
File.Copy(temp1, file2, true);
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public virtual bool ContainsSubPath(string parentPath, string path)
|
||||
{
|
||||
if (string.IsNullOrEmpty(parentPath))
|
||||
|
@ -515,6 +525,7 @@ namespace Emby.Server.Implementations.IO
|
|||
_isEnvironmentCaseInsensitive ? StringComparison.OrdinalIgnoreCase : StringComparison.Ordinal);
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public virtual string NormalizePath(string path)
|
||||
{
|
||||
if (string.IsNullOrEmpty(path))
|
||||
|
@ -530,6 +541,7 @@ namespace Emby.Server.Implementations.IO
|
|||
return Path.TrimEndingDirectorySeparator(path);
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public virtual bool AreEqual(string path1, string path2)
|
||||
{
|
||||
if (path1 == null && path2 == null)
|
||||
|
@ -548,6 +560,7 @@ namespace Emby.Server.Implementations.IO
|
|||
_isEnvironmentCaseInsensitive ? StringComparison.OrdinalIgnoreCase : StringComparison.Ordinal);
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public virtual string GetFileNameWithoutExtension(FileSystemMetadata info)
|
||||
{
|
||||
if (info.IsDirectory)
|
||||
|
@ -558,11 +571,11 @@ namespace Emby.Server.Implementations.IO
|
|||
return Path.GetFileNameWithoutExtension(info.FullName);
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public virtual bool IsPathFile(string path)
|
||||
{
|
||||
// Cannot use Path.IsPathRooted because it returns false under mono when using windows-based paths, e.g. C:\\
|
||||
if (path.IndexOf("://", StringComparison.OrdinalIgnoreCase) != -1 &&
|
||||
!path.StartsWith("file://", StringComparison.OrdinalIgnoreCase))
|
||||
if (path.Contains("://", StringComparison.OrdinalIgnoreCase)
|
||||
&& !path.StartsWith("file://", StringComparison.OrdinalIgnoreCase))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
@ -570,12 +583,14 @@ namespace Emby.Server.Implementations.IO
|
|||
return true;
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public virtual void DeleteFile(string path)
|
||||
{
|
||||
SetAttributes(path, false, false);
|
||||
File.Delete(path);
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public virtual List<FileSystemMetadata> GetDrives()
|
||||
{
|
||||
// check for ready state to avoid waiting for drives to timeout
|
||||
|
@ -593,16 +608,19 @@ namespace Emby.Server.Implementations.IO
|
|||
}).ToList();
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public virtual IEnumerable<FileSystemMetadata> GetDirectories(string path, bool recursive = false)
|
||||
{
|
||||
return ToMetadata(new DirectoryInfo(path).EnumerateDirectories("*", GetEnumerationOptions(recursive)));
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public virtual IEnumerable<FileSystemMetadata> GetFiles(string path, bool recursive = false)
|
||||
{
|
||||
return GetFiles(path, null, false, recursive);
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public virtual IEnumerable<FileSystemMetadata> GetFiles(string path, IReadOnlyList<string>? extensions, bool enableCaseSensitiveExtensions, bool recursive = false)
|
||||
{
|
||||
var enumerationOptions = GetEnumerationOptions(recursive);
|
||||
|
@ -633,6 +651,7 @@ namespace Emby.Server.Implementations.IO
|
|||
return ToMetadata(files);
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public virtual IEnumerable<FileSystemMetadata> GetFileSystemEntries(string path, bool recursive = false)
|
||||
{
|
||||
var directoryInfo = new DirectoryInfo(path);
|
||||
|
@ -646,16 +665,19 @@ namespace Emby.Server.Implementations.IO
|
|||
return infos.Select(GetFileSystemMetadata);
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public virtual IEnumerable<string> GetDirectoryPaths(string path, bool recursive = false)
|
||||
{
|
||||
return Directory.EnumerateDirectories(path, "*", GetEnumerationOptions(recursive));
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public virtual IEnumerable<string> GetFilePaths(string path, bool recursive = false)
|
||||
{
|
||||
return GetFilePaths(path, null, false, recursive);
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public virtual IEnumerable<string> GetFilePaths(string path, string[]? extensions, bool enableCaseSensitiveExtensions, bool recursive = false)
|
||||
{
|
||||
var enumerationOptions = GetEnumerationOptions(recursive);
|
||||
|
@ -686,6 +708,7 @@ namespace Emby.Server.Implementations.IO
|
|||
return files;
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public virtual IEnumerable<string> GetFileSystemEntryPaths(string path, bool recursive = false)
|
||||
{
|
||||
return Directory.EnumerateFileSystemEntries(path, "*", GetEnumerationOptions(recursive));
|
||||
|
|
|
@ -45,6 +45,7 @@ namespace Emby.Server.Implementations.Library
|
|||
private readonly IMediaEncoder _mediaEncoder;
|
||||
private readonly ILocalizationManager _localizationManager;
|
||||
private readonly IApplicationPaths _appPaths;
|
||||
private readonly IDirectoryService _directoryService;
|
||||
|
||||
private readonly ConcurrentDictionary<string, ILiveStream> _openStreams = new ConcurrentDictionary<string, ILiveStream>(StringComparer.OrdinalIgnoreCase);
|
||||
private readonly SemaphoreSlim _liveStreamSemaphore = new SemaphoreSlim(1, 1);
|
||||
|
@ -61,7 +62,8 @@ namespace Emby.Server.Implementations.Library
|
|||
ILogger<MediaSourceManager> logger,
|
||||
IFileSystem fileSystem,
|
||||
IUserDataManager userDataManager,
|
||||
IMediaEncoder mediaEncoder)
|
||||
IMediaEncoder mediaEncoder,
|
||||
IDirectoryService directoryService)
|
||||
{
|
||||
_itemRepo = itemRepo;
|
||||
_userManager = userManager;
|
||||
|
@ -72,6 +74,7 @@ namespace Emby.Server.Implementations.Library
|
|||
_mediaEncoder = mediaEncoder;
|
||||
_localizationManager = localizationManager;
|
||||
_appPaths = applicationPaths;
|
||||
_directoryService = directoryService;
|
||||
}
|
||||
|
||||
public void AddParts(IEnumerable<IMediaSourceProvider> providers)
|
||||
|
@ -106,16 +109,6 @@ namespace Emby.Server.Implementations.Library
|
|||
return false;
|
||||
}
|
||||
|
||||
public List<MediaStream> GetMediaStreams(string mediaSourceId)
|
||||
{
|
||||
var list = GetMediaStreams(new MediaStreamQuery
|
||||
{
|
||||
ItemId = new Guid(mediaSourceId)
|
||||
});
|
||||
|
||||
return GetMediaStreamsForItem(list);
|
||||
}
|
||||
|
||||
public List<MediaStream> GetMediaStreams(Guid itemId)
|
||||
{
|
||||
var list = GetMediaStreams(new MediaStreamQuery
|
||||
|
@ -161,7 +154,7 @@ namespace Emby.Server.Implementations.Library
|
|||
if (allowMediaProbe && mediaSources[0].Type != MediaSourceType.Placeholder && !mediaSources[0].MediaStreams.Any(i => i.Type == MediaStreamType.Audio || i.Type == MediaStreamType.Video))
|
||||
{
|
||||
await item.RefreshMetadata(
|
||||
new MetadataRefreshOptions(new DirectoryService(_fileSystem))
|
||||
new MetadataRefreshOptions(_directoryService)
|
||||
{
|
||||
EnableRemoteContentProbe = true,
|
||||
MetadataRefreshMode = MetadataRefreshMode.FullRefresh
|
||||
|
@ -212,6 +205,7 @@ namespace Emby.Server.Implementations.Library
|
|||
return SortMediaSources(list);
|
||||
}
|
||||
|
||||
/// <inheritdoc />>
|
||||
public MediaProtocol GetPathProtocol(string path)
|
||||
{
|
||||
if (path.StartsWith("Rtsp", StringComparison.OrdinalIgnoreCase))
|
||||
|
@ -258,7 +252,7 @@ namespace Emby.Server.Implementations.Library
|
|||
{
|
||||
if (path != null)
|
||||
{
|
||||
if (path.IndexOf(".m3u", StringComparison.OrdinalIgnoreCase) != -1)
|
||||
if (path.Contains(".m3u", StringComparison.OrdinalIgnoreCase))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
@ -297,7 +291,7 @@ namespace Emby.Server.Implementations.Library
|
|||
catch (Exception ex)
|
||||
{
|
||||
_logger.LogError(ex, "Error getting media sources");
|
||||
return new List<MediaSourceInfo>();
|
||||
return Enumerable.Empty<MediaSourceInfo>();
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -494,14 +488,11 @@ namespace Emby.Server.Implementations.Library
|
|||
_liveStreamSemaphore.Release();
|
||||
}
|
||||
|
||||
// TODO: Don't hardcode this
|
||||
const bool isAudio = false;
|
||||
|
||||
try
|
||||
{
|
||||
if (mediaSource.MediaStreams.Any(i => i.Index != -1) || !mediaSource.SupportsProbing)
|
||||
{
|
||||
AddMediaInfo(mediaSource, isAudio);
|
||||
AddMediaInfo(mediaSource);
|
||||
}
|
||||
else
|
||||
{
|
||||
|
@ -509,14 +500,14 @@ namespace Emby.Server.Implementations.Library
|
|||
string cacheKey = request.OpenToken;
|
||||
|
||||
await new LiveStreamHelper(_mediaEncoder, _logger, _appPaths)
|
||||
.AddMediaInfoWithProbe(mediaSource, isAudio, cacheKey, true, cancellationToken)
|
||||
.AddMediaInfoWithProbe(mediaSource, false, cacheKey, true, cancellationToken)
|
||||
.ConfigureAwait(false);
|
||||
}
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
_logger.LogError(ex, "Error probing live tv stream");
|
||||
AddMediaInfo(mediaSource, isAudio);
|
||||
AddMediaInfo(mediaSource);
|
||||
}
|
||||
|
||||
// TODO: @bond Fix
|
||||
|
@ -536,7 +527,7 @@ namespace Emby.Server.Implementations.Library
|
|||
return new Tuple<LiveStreamResponse, IDirectStreamProvider>(new LiveStreamResponse(clone), liveStream as IDirectStreamProvider);
|
||||
}
|
||||
|
||||
private static void AddMediaInfo(MediaSourceInfo mediaSource, bool isAudio)
|
||||
private static void AddMediaInfo(MediaSourceInfo mediaSource)
|
||||
{
|
||||
mediaSource.DefaultSubtitleStreamIndex = null;
|
||||
|
||||
|
@ -855,9 +846,7 @@ namespace Emby.Server.Implementations.Library
|
|||
return (provider, keyId);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Performs application-defined tasks associated with freeing, releasing, or resetting unmanaged resources.
|
||||
/// </summary>
|
||||
/// <inheritdoc />
|
||||
public void Dispose()
|
||||
{
|
||||
Dispose(true);
|
||||
|
|
|
@ -30,13 +30,6 @@ namespace MediaBrowser.Controller.Library
|
|||
/// <returns>IEnumerable<MediaStream>.</returns>
|
||||
List<MediaStream> GetMediaStreams(Guid itemId);
|
||||
|
||||
/// <summary>
|
||||
/// Gets the media streams.
|
||||
/// </summary>
|
||||
/// <param name="mediaSourceId">The media source identifier.</param>
|
||||
/// <returns>IEnumerable<MediaStream>.</returns>
|
||||
List<MediaStream> GetMediaStreams(string mediaSourceId);
|
||||
|
||||
/// <summary>
|
||||
/// Gets the media streams.
|
||||
/// </summary>
|
||||
|
|
|
@ -0,0 +1,32 @@
|
|||
using AutoFixture;
|
||||
using AutoFixture.AutoMoq;
|
||||
using Emby.Server.Implementations.IO;
|
||||
using Emby.Server.Implementations.Library;
|
||||
using MediaBrowser.Model.IO;
|
||||
using MediaBrowser.Model.MediaInfo;
|
||||
using Xunit;
|
||||
|
||||
namespace Jellyfin.Server.Implementations.Tests.Library
|
||||
{
|
||||
public class MediaSourceManagerTests
|
||||
{
|
||||
private readonly MediaSourceManager _mediaSourceManager;
|
||||
|
||||
public MediaSourceManagerTests()
|
||||
{
|
||||
IFixture fixture = new Fixture().Customize(new AutoMoqCustomization { ConfigureMembers = true });
|
||||
fixture.Inject<IFileSystem>(fixture.Create<ManagedFileSystem>());
|
||||
_mediaSourceManager = fixture.Create<MediaSourceManager>();
|
||||
}
|
||||
|
||||
[Theory]
|
||||
[InlineData(@"C:\mydir\myfile.ext", MediaProtocol.File)]
|
||||
[InlineData("/mydir/myfile.ext", MediaProtocol.File)]
|
||||
[InlineData("file:///mydir/myfile.ext", MediaProtocol.File)]
|
||||
[InlineData("http://example.com/stream.m3u8", MediaProtocol.Http)]
|
||||
[InlineData("https://example.com/stream.m3u8", MediaProtocol.Http)]
|
||||
[InlineData("rtsp://media.example.com:554/twister/audiotrack", MediaProtocol.Rtsp)]
|
||||
public void GetPathProtocol_ValidArg_Correct(string path, MediaProtocol expected)
|
||||
=> Assert.Equal(expected, _mediaSourceManager.GetPathProtocol(path));
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue
Block a user