diff --git a/Emby.Server.Implementations/IO/ManagedFileSystem.cs b/Emby.Server.Implementations/IO/ManagedFileSystem.cs
index 3aefb841e5..777cd2cd46 100644
--- a/Emby.Server.Implementations/IO/ManagedFileSystem.cs
+++ b/Emby.Server.Implementations/IO/ManagedFileSystem.cs
@@ -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();
+ ///
+ /// Initializes a new instance of the class.
+ ///
+ /// The instance to use.
+ /// The instance to use.
public ManagedFileSystem(
ILogger logger,
IApplicationPaths applicationPaths)
@@ -31,6 +34,7 @@ namespace Emby.Server.Implementations.IO
_tempPath = applicationPaths.TempDirectory;
}
+ ///
public virtual void AddShortcutHandler(IShortcutHandler handler)
{
_shortcutHandlers.Add(handler);
@@ -72,6 +76,7 @@ namespace Emby.Server.Implementations.IO
return handler?.Resolve(filename);
}
+ ///
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));
}
+ ///
public virtual DateTime GetCreationTimeUtc(FileSystemMetadata info)
{
return info.CreationTimeUtc;
}
+ ///
public virtual DateTime GetLastWriteTimeUtc(FileSystemMetadata info)
{
return info.LastWriteTimeUtc;
@@ -397,6 +404,7 @@ namespace Emby.Server.Implementations.IO
return GetLastWriteTimeUtc(GetFileSystemInfo(path));
}
+ ///
public virtual void SetHidden(string path, bool isHidden)
{
if (!OperatingSystem.IsWindows())
@@ -421,6 +429,7 @@ namespace Emby.Server.Implementations.IO
}
}
+ ///
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);
}
+ ///
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);
}
+ ///
public virtual string NormalizePath(string path)
{
if (string.IsNullOrEmpty(path))
@@ -530,6 +541,7 @@ namespace Emby.Server.Implementations.IO
return Path.TrimEndingDirectorySeparator(path);
}
+ ///
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);
}
+ ///
public virtual string GetFileNameWithoutExtension(FileSystemMetadata info)
{
if (info.IsDirectory)
@@ -558,11 +571,11 @@ namespace Emby.Server.Implementations.IO
return Path.GetFileNameWithoutExtension(info.FullName);
}
+ ///
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;
}
+ ///
public virtual void DeleteFile(string path)
{
SetAttributes(path, false, false);
File.Delete(path);
}
+ ///
public virtual List GetDrives()
{
// check for ready state to avoid waiting for drives to timeout
@@ -593,16 +608,19 @@ namespace Emby.Server.Implementations.IO
}).ToList();
}
+ ///
public virtual IEnumerable GetDirectories(string path, bool recursive = false)
{
return ToMetadata(new DirectoryInfo(path).EnumerateDirectories("*", GetEnumerationOptions(recursive)));
}
+ ///
public virtual IEnumerable GetFiles(string path, bool recursive = false)
{
return GetFiles(path, null, false, recursive);
}
+ ///
public virtual IEnumerable GetFiles(string path, IReadOnlyList? extensions, bool enableCaseSensitiveExtensions, bool recursive = false)
{
var enumerationOptions = GetEnumerationOptions(recursive);
@@ -633,6 +651,7 @@ namespace Emby.Server.Implementations.IO
return ToMetadata(files);
}
+ ///
public virtual IEnumerable GetFileSystemEntries(string path, bool recursive = false)
{
var directoryInfo = new DirectoryInfo(path);
@@ -646,16 +665,19 @@ namespace Emby.Server.Implementations.IO
return infos.Select(GetFileSystemMetadata);
}
+ ///
public virtual IEnumerable GetDirectoryPaths(string path, bool recursive = false)
{
return Directory.EnumerateDirectories(path, "*", GetEnumerationOptions(recursive));
}
+ ///
public virtual IEnumerable GetFilePaths(string path, bool recursive = false)
{
return GetFilePaths(path, null, false, recursive);
}
+ ///
public virtual IEnumerable 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;
}
+ ///
public virtual IEnumerable GetFileSystemEntryPaths(string path, bool recursive = false)
{
return Directory.EnumerateFileSystemEntries(path, "*", GetEnumerationOptions(recursive));
diff --git a/Emby.Server.Implementations/Library/MediaSourceManager.cs b/Emby.Server.Implementations/Library/MediaSourceManager.cs
index 351fced348..972d4ebbbf 100644
--- a/Emby.Server.Implementations/Library/MediaSourceManager.cs
+++ b/Emby.Server.Implementations/Library/MediaSourceManager.cs
@@ -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 _openStreams = new ConcurrentDictionary(StringComparer.OrdinalIgnoreCase);
private readonly SemaphoreSlim _liveStreamSemaphore = new SemaphoreSlim(1, 1);
@@ -61,7 +62,8 @@ namespace Emby.Server.Implementations.Library
ILogger 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 providers)
@@ -106,16 +109,6 @@ namespace Emby.Server.Implementations.Library
return false;
}
- public List GetMediaStreams(string mediaSourceId)
- {
- var list = GetMediaStreams(new MediaStreamQuery
- {
- ItemId = new Guid(mediaSourceId)
- });
-
- return GetMediaStreamsForItem(list);
- }
-
public List 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);
}
+ /// >
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();
+ return Enumerable.Empty();
}
}
@@ -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(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);
}
- ///
- /// Performs application-defined tasks associated with freeing, releasing, or resetting unmanaged resources.
- ///
+ ///
public void Dispose()
{
Dispose(true);
diff --git a/MediaBrowser.Controller/Library/IMediaSourceManager.cs b/MediaBrowser.Controller/Library/IMediaSourceManager.cs
index e802796d34..f1758a9d80 100644
--- a/MediaBrowser.Controller/Library/IMediaSourceManager.cs
+++ b/MediaBrowser.Controller/Library/IMediaSourceManager.cs
@@ -30,13 +30,6 @@ namespace MediaBrowser.Controller.Library
/// IEnumerable<MediaStream>.
List GetMediaStreams(Guid itemId);
- ///
- /// Gets the media streams.
- ///
- /// The media source identifier.
- /// IEnumerable<MediaStream>.
- List GetMediaStreams(string mediaSourceId);
-
///
/// Gets the media streams.
///
diff --git a/tests/Jellyfin.Server.Implementations.Tests/Library/MediaSourceManagerTests.cs b/tests/Jellyfin.Server.Implementations.Tests/Library/MediaSourceManagerTests.cs
new file mode 100644
index 0000000000..8ed3d8b944
--- /dev/null
+++ b/tests/Jellyfin.Server.Implementations.Tests/Library/MediaSourceManagerTests.cs
@@ -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(fixture.Create());
+ _mediaSourceManager = fixture.Create();
+ }
+
+ [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));
+ }
+}