Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add some docs and tests #6793

Merged
merged 1 commit into from
Nov 8, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
37 changes: 30 additions & 7 deletions Emby.Server.Implementations/IO/ManagedFileSystem.cs
Original file line number Diff line number Diff line change
@@ -1,5 +1,3 @@
#pragma warning disable CS1591

using System;
using System.Collections.Generic;
using System.Globalization;
Expand All @@ -23,6 +21,11 @@ public class ManagedFileSystem : IFileSystem
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)
Expand All @@ -31,6 +34,7 @@ public class ManagedFileSystem : IFileSystem
_tempPath = applicationPaths.TempDirectory;
}

/// <inheritdoc />
public virtual void AddShortcutHandler(IShortcutHandler handler)
{
_shortcutHandlers.Add(handler);
Expand Down Expand Up @@ -72,6 +76,7 @@ public virtual bool IsShortcut(string filename)
return handler?.Resolve(filename);
}

/// <inheritdoc />
public virtual string MakeAbsolutePath(string folderPath, string filePath)
{
// path is actually a stream
Expand Down Expand Up @@ -358,11 +363,13 @@ public virtual DateTime GetCreationTimeUtc(string path)
return GetCreationTimeUtc(GetFileSystemInfo(path));
}

/// <inheritdoc />
public virtual DateTime GetCreationTimeUtc(FileSystemMetadata info)
{
return info.CreationTimeUtc;
}

/// <inheritdoc />
public virtual DateTime GetLastWriteTimeUtc(FileSystemMetadata info)
{
return info.LastWriteTimeUtc;
Expand Down Expand Up @@ -397,6 +404,7 @@ public virtual DateTime GetLastWriteTimeUtc(string path)
return GetLastWriteTimeUtc(GetFileSystemInfo(path));
}

/// <inheritdoc />
public virtual void SetHidden(string path, bool isHidden)
{
if (!OperatingSystem.IsWindows())
Expand All @@ -421,6 +429,7 @@ public virtual void SetHidden(string path, bool isHidden)
}
}

/// <inheritdoc />
public virtual void SetAttributes(string path, bool isHidden, bool readOnly)
{
if (!OperatingSystem.IsWindows())
Expand All @@ -444,7 +453,7 @@ public virtual void SetAttributes(string path, bool isHidden, bool readOnly)

if (readOnly)
{
attributes = attributes | FileAttributes.ReadOnly;
attributes |= FileAttributes.ReadOnly;
}
else
{
Expand All @@ -453,7 +462,7 @@ public virtual void SetAttributes(string path, bool isHidden, bool readOnly)

if (isHidden)
{
attributes = attributes | FileAttributes.Hidden;
attributes |= FileAttributes.Hidden;
}
else
{
Expand Down Expand Up @@ -498,6 +507,7 @@ public virtual void SwapFiles(string file1, string file2)
File.Copy(temp1, file2, true);
}

/// <inheritdoc />
public virtual bool ContainsSubPath(string parentPath, string path)
{
if (string.IsNullOrEmpty(parentPath))
Expand All @@ -515,6 +525,7 @@ public virtual bool ContainsSubPath(string parentPath, string path)
_isEnvironmentCaseInsensitive ? StringComparison.OrdinalIgnoreCase : StringComparison.Ordinal);
}

/// <inheritdoc />
public virtual string NormalizePath(string path)
{
if (string.IsNullOrEmpty(path))
Expand All @@ -530,6 +541,7 @@ public virtual string NormalizePath(string path)
return Path.TrimEndingDirectorySeparator(path);
}

/// <inheritdoc />
public virtual bool AreEqual(string path1, string path2)
{
if (path1 == null && path2 == null)
Expand All @@ -548,6 +560,7 @@ public virtual bool AreEqual(string path1, string path2)
_isEnvironmentCaseInsensitive ? StringComparison.OrdinalIgnoreCase : StringComparison.Ordinal);
}

/// <inheritdoc />
public virtual string GetFileNameWithoutExtension(FileSystemMetadata info)
{
if (info.IsDirectory)
Expand All @@ -558,24 +571,26 @@ public virtual string GetFileNameWithoutExtension(FileSystemMetadata info)
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;
}

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
Expand All @@ -593,16 +608,19 @@ public virtual List<FileSystemMetadata> GetDrives()
}).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);
Expand Down Expand Up @@ -633,6 +651,7 @@ public virtual IEnumerable<FileSystemMetadata> GetFiles(string path, IReadOnlyLi
return ToMetadata(files);
}

/// <inheritdoc />
public virtual IEnumerable<FileSystemMetadata> GetFileSystemEntries(string path, bool recursive = false)
{
var directoryInfo = new DirectoryInfo(path);
Expand All @@ -646,16 +665,19 @@ private IEnumerable<FileSystemMetadata> ToMetadata(IEnumerable<FileSystemInfo> i
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);
Expand Down Expand Up @@ -686,6 +708,7 @@ public virtual IEnumerable<string> GetFilePaths(string path, string[]? extension
return files;
}

/// <inheritdoc />
public virtual IEnumerable<string> GetFileSystemEntryPaths(string path, bool recursive = false)
{
return Directory.EnumerateFileSystemEntries(path, "*", GetEnumerationOptions(recursive));
Expand Down
37 changes: 13 additions & 24 deletions Emby.Server.Implementations/Library/MediaSourceManager.cs
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,7 @@ public class MediaSourceManager : IMediaSourceManager, IDisposable
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);
Expand All @@ -61,7 +62,8 @@ public class MediaSourceManager : IMediaSourceManager, IDisposable
ILogger<MediaSourceManager> logger,
IFileSystem fileSystem,
IUserDataManager userDataManager,
IMediaEncoder mediaEncoder)
IMediaEncoder mediaEncoder,
IDirectoryService directoryService)
{
_itemRepo = itemRepo;
_userManager = userManager;
Expand All @@ -72,6 +74,7 @@ public class MediaSourceManager : IMediaSourceManager, IDisposable
_mediaEncoder = mediaEncoder;
_localizationManager = localizationManager;
_appPaths = applicationPaths;
_directoryService = directoryService;
}

public void AddParts(IEnumerable<IMediaSourceProvider> providers)
Expand Down Expand Up @@ -106,16 +109,6 @@ private static bool StreamSupportsExternalStream(MediaStream stream)
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
Expand Down Expand Up @@ -161,7 +154,7 @@ public async Task<List<MediaSourceInfo>> GetPlaybackMediaSources(BaseItem item,
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
Expand Down Expand Up @@ -212,6 +205,7 @@ public async Task<List<MediaSourceInfo>> GetPlaybackMediaSources(BaseItem item,
return SortMediaSources(list);
}

/// <inheritdoc />>
public MediaProtocol GetPathProtocol(string path)
{
if (path.StartsWith("Rtsp", StringComparison.OrdinalIgnoreCase))
Expand Down Expand Up @@ -258,7 +252,7 @@ public bool SupportsDirectStream(string path, MediaProtocol protocol)
{
if (path != null)
{
if (path.IndexOf(".m3u", StringComparison.OrdinalIgnoreCase) != -1)
if (path.Contains(".m3u", StringComparison.OrdinalIgnoreCase))
{
return false;
}
Expand Down Expand Up @@ -297,7 +291,7 @@ private async Task<IEnumerable<MediaSourceInfo>> GetDynamicMediaSources(BaseItem
catch (Exception ex)
{
_logger.LogError(ex, "Error getting media sources");
return new List<MediaSourceInfo>();
return Enumerable.Empty<MediaSourceInfo>();
}
}

Expand Down Expand Up @@ -494,29 +488,26 @@ private static List<MediaSourceInfo> SortMediaSources(IEnumerable<MediaSourceInf
_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
{
// hack - these two values were taken from LiveTVMediaSourceProvider
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
Expand All @@ -536,7 +527,7 @@ private static List<MediaSourceInfo> SortMediaSources(IEnumerable<MediaSourceInf
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;

Expand Down Expand Up @@ -855,9 +846,7 @@ public async Task CloseLiveStream(string id)
return (provider, keyId);
}

/// <summary>
/// Performs application-defined tasks associated with freeing, releasing, or resetting unmanaged resources.
/// </summary>
/// <inheritdoc />
public void Dispose()
{
Dispose(true);
Expand Down
7 changes: 0 additions & 7 deletions MediaBrowser.Controller/Library/IMediaSourceManager.cs
Original file line number Diff line number Diff line change
Expand Up @@ -30,13 +30,6 @@ public interface IMediaSourceManager
/// <returns>IEnumerable&lt;MediaStream&gt;.</returns>
List<MediaStream> GetMediaStreams(Guid itemId);

/// <summary>
/// Gets the media streams.
/// </summary>
/// <param name="mediaSourceId">The media source identifier.</param>
/// <returns>IEnumerable&lt;MediaStream&gt;.</returns>
List<MediaStream> GetMediaStreams(string mediaSourceId);

/// <summary>
/// Gets the media streams.
/// </summary>
Expand Down
Original file line number Diff line number Diff line change
@@ -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));
}
}