aboutsummaryrefslogtreecommitdiff
path: root/MediaBrowser.Api
diff options
context:
space:
mode:
Diffstat (limited to 'MediaBrowser.Api')
-rw-r--r--MediaBrowser.Api/AppThemeService.cs100
-rw-r--r--MediaBrowser.Api/Devices/DeviceService.cs37
-rw-r--r--MediaBrowser.Api/Dlna/DlnaServerService.cs1
-rw-r--r--MediaBrowser.Api/EnvironmentService.cs20
-rw-r--r--MediaBrowser.Api/Images/ImageByNameService.cs21
-rw-r--r--MediaBrowser.Api/Images/RemoteImageService.cs6
-rw-r--r--MediaBrowser.Api/ItemLookupService.cs8
-rw-r--r--MediaBrowser.Api/ItemRefreshService.cs7
-rw-r--r--MediaBrowser.Api/Library/LibraryHelpers.cs6
-rw-r--r--MediaBrowser.Api/Library/LibraryService.cs7
-rw-r--r--MediaBrowser.Api/Library/LibraryStructureService.cs19
-rw-r--r--MediaBrowser.Api/MediaBrowser.Api.csproj15
-rw-r--r--MediaBrowser.Api/Playback/BaseStreamingService.cs57
-rw-r--r--MediaBrowser.Api/Playback/Dash/MpegDashService.cs13
-rw-r--r--MediaBrowser.Api/Playback/Hls/BaseHlsService.cs29
-rw-r--r--MediaBrowser.Api/Playback/Hls/DynamicHlsService.cs59
-rw-r--r--MediaBrowser.Api/Playback/MediaInfoService.cs16
-rw-r--r--MediaBrowser.Api/Playback/Progressive/BaseProgressiveStreamingService.cs4
-rw-r--r--MediaBrowser.Api/Playback/Progressive/VideoService.cs1
-rw-r--r--MediaBrowser.Api/Playback/StreamState.cs2
-rw-r--r--MediaBrowser.Api/Reports/Stat/ReportStatBuilder.cs2
-rw-r--r--MediaBrowser.Api/StartupWizardService.cs2
-rw-r--r--MediaBrowser.Api/Subtitles/SubtitleService.cs7
-rw-r--r--MediaBrowser.Api/System/SystemService.cs6
-rw-r--r--MediaBrowser.Api/UserLibrary/UserViewsService.cs34
-rw-r--r--MediaBrowser.Api/packages.config2
26 files changed, 244 insertions, 237 deletions
diff --git a/MediaBrowser.Api/AppThemeService.cs b/MediaBrowser.Api/AppThemeService.cs
deleted file mode 100644
index 87084e415..000000000
--- a/MediaBrowser.Api/AppThemeService.cs
+++ /dev/null
@@ -1,100 +0,0 @@
-using MediaBrowser.Common.IO;
-using MediaBrowser.Controller.Net;
-using MediaBrowser.Controller.Themes;
-using MediaBrowser.Model.Themes;
-using ServiceStack;
-using System;
-using System.Collections.Generic;
-using System.IO;
-using System.Linq;
-
-namespace MediaBrowser.Api
-{
- [Route("/Themes", "GET", Summary = "Gets a list of available themes for an app")]
- public class GetAppThemes : IReturn<List<AppThemeInfo>>
- {
- [ApiMember(Name = "App", IsRequired = true, DataType = "string", ParameterType = "query", Verb = "GET")]
- public string App { get; set; }
- }
-
- [Route("/Themes/Info", "GET", Summary = "Gets an app theme")]
- public class GetAppTheme : IReturn<AppTheme>
- {
- [ApiMember(Name = "App", IsRequired = true, DataType = "string", ParameterType = "query", Verb = "GET")]
- public string App { get; set; }
-
- [ApiMember(Name = "Name", IsRequired = true, DataType = "string", ParameterType = "query", Verb = "GET")]
- public string Name { get; set; }
- }
-
- [Route("/Themes/Images", "GET", Summary = "Gets an app theme")]
- public class GetAppThemeImage
- {
- [ApiMember(Name = "App", IsRequired = true, DataType = "string", ParameterType = "query", Verb = "GET")]
- public string App { get; set; }
-
- [ApiMember(Name = "Theme", IsRequired = true, DataType = "string", ParameterType = "query", Verb = "GET")]
- public string Theme { get; set; }
-
- [ApiMember(Name = "Name", IsRequired = true, DataType = "string", ParameterType = "query", Verb = "GET")]
- public string Name { get; set; }
-
- [ApiMember(Name = "CacheTag", IsRequired = false, DataType = "string", ParameterType = "query", Verb = "GET")]
- public string CacheTag { get; set; }
- }
-
- [Route("/Themes", "POST", Summary = "Saves a theme")]
- public class SaveTheme : AppTheme, IReturnVoid
- {
- }
-
- [Authenticated]
- public class AppThemeService : BaseApiService
- {
- private readonly IAppThemeManager _themeManager;
- private readonly IFileSystem _fileSystem;
-
- public AppThemeService(IAppThemeManager themeManager, IFileSystem fileSystem)
- {
- _themeManager = themeManager;
- _fileSystem = fileSystem;
- }
-
- public object Get(GetAppThemes request)
- {
- var result = _themeManager.GetThemes(request.App).ToList();
-
- return ToOptimizedResult(result);
- }
-
- public object Get(GetAppTheme request)
- {
- var result = _themeManager.GetTheme(request.App, request.Name);
-
- return ToOptimizedResult(result);
- }
-
- public void Post(SaveTheme request)
- {
- _themeManager.SaveTheme(request);
- }
-
- public object Get(GetAppThemeImage request)
- {
- var info = _themeManager.GetImageImageInfo(request.App, request.Theme, request.Name);
-
- var cacheGuid = new Guid(info.CacheTag);
-
- TimeSpan? cacheDuration = null;
-
- if (!string.IsNullOrEmpty(request.CacheTag) && cacheGuid == new Guid(request.CacheTag))
- {
- cacheDuration = TimeSpan.FromDays(365);
- }
-
- var contentType = MimeTypes.GetMimeType(info.Path);
-
- return ResultFactory.GetCachedResult(Request, cacheGuid, null, cacheDuration, () => _fileSystem.GetFileStream(info.Path, FileMode.Open, FileAccess.Read, FileShare.Read), contentType);
- }
- }
-}
diff --git a/MediaBrowser.Api/Devices/DeviceService.cs b/MediaBrowser.Api/Devices/DeviceService.cs
index ab0a4a4b2..759eea353 100644
--- a/MediaBrowser.Api/Devices/DeviceService.cs
+++ b/MediaBrowser.Api/Devices/DeviceService.cs
@@ -1,4 +1,6 @@
-using MediaBrowser.Controller.Devices;
+using System;
+using System.Linq;
+using MediaBrowser.Controller.Devices;
using MediaBrowser.Controller.Net;
using MediaBrowser.Model.Devices;
using MediaBrowser.Model.Querying;
@@ -128,15 +130,32 @@ namespace MediaBrowser.Api.Devices
var id = Request.QueryString["Id"];
var name = Request.QueryString["Name"];
- var task = _deviceManager.AcceptCameraUpload(deviceId, request.RequestStream, new LocalFileInfo
+ if (Request.ContentType.IndexOf("multi", StringComparison.OrdinalIgnoreCase) == -1)
{
- MimeType = Request.ContentType,
- Album = album,
- Name = name,
- Id = id
- });
-
- Task.WaitAll(task);
+ var task = _deviceManager.AcceptCameraUpload(deviceId, request.RequestStream, new LocalFileInfo
+ {
+ MimeType = Request.ContentType,
+ Album = album,
+ Name = name,
+ Id = id
+ });
+
+ Task.WaitAll(task);
+ }
+ else
+ {
+ var file = Request.Files.First();
+
+ var task = _deviceManager.AcceptCameraUpload(deviceId, file.InputStream, new LocalFileInfo
+ {
+ MimeType = file.ContentType,
+ Album = album,
+ Name = name,
+ Id = id
+ });
+
+ Task.WaitAll(task);
+ }
}
}
}
diff --git a/MediaBrowser.Api/Dlna/DlnaServerService.cs b/MediaBrowser.Api/Dlna/DlnaServerService.cs
index 4f5e2ab25..4e7b1a7d5 100644
--- a/MediaBrowser.Api/Dlna/DlnaServerService.cs
+++ b/MediaBrowser.Api/Dlna/DlnaServerService.cs
@@ -108,7 +108,6 @@ namespace MediaBrowser.Api.Dlna
private readonly IConnectionManager _connectionManager;
private readonly IMediaReceiverRegistrar _mediaReceiverRegistrar;
- // TODO: Add utf-8
private const string XMLContentType = "text/xml; charset=UTF-8";
public DlnaServerService(IDlnaManager dlnaManager, IContentDirectory contentDirectory, IConnectionManager connectionManager, IMediaReceiverRegistrar mediaReceiverRegistrar)
diff --git a/MediaBrowser.Api/EnvironmentService.cs b/MediaBrowser.Api/EnvironmentService.cs
index 457b4709b..11a0eec23 100644
--- a/MediaBrowser.Api/EnvironmentService.cs
+++ b/MediaBrowser.Api/EnvironmentService.cs
@@ -1,4 +1,5 @@
-using MediaBrowser.Common.Net;
+using MediaBrowser.Common.IO;
+using MediaBrowser.Common.Net;
using MediaBrowser.Controller.Net;
using MediaBrowser.Model.IO;
using MediaBrowser.Model.Net;
@@ -96,13 +97,14 @@ namespace MediaBrowser.Api
/// The _network manager
/// </summary>
private readonly INetworkManager _networkManager;
+ private IFileSystem _fileSystem;
/// <summary>
/// Initializes a new instance of the <see cref="EnvironmentService" /> class.
/// </summary>
/// <param name="networkManager">The network manager.</param>
/// <exception cref="System.ArgumentNullException">networkManager</exception>
- public EnvironmentService(INetworkManager networkManager)
+ public EnvironmentService(INetworkManager networkManager, IFileSystem fileSystem)
{
if (networkManager == null)
{
@@ -110,6 +112,7 @@ namespace MediaBrowser.Api
}
_networkManager = networkManager;
+ _fileSystem = fileSystem;
}
/// <summary>
@@ -135,7 +138,15 @@ namespace MediaBrowser.Api
return ToOptimizedSerializedResultUsingCache(GetNetworkShares(path).OrderBy(i => i.Path).ToList());
}
- return ToOptimizedSerializedResultUsingCache(GetFileSystemEntries(request).OrderBy(i => i.Path).ToList());
+ try
+ {
+ return ToOptimizedSerializedResultUsingCache(GetFileSystemEntries(request).OrderBy(i => i.Path).ToList());
+ }
+ catch (UnauthorizedAccessException)
+ {
+ // Don't throw the original UnauthorizedAccessException because it will cause a 401 response
+ throw new ApplicationException("Access to the path " + request.Path + " is denied.");
+ }
}
public object Get(GetNetworkShares request)
@@ -222,8 +233,7 @@ namespace MediaBrowser.Api
private IEnumerable<FileSystemEntryInfo> GetFileSystemEntries(GetDirectoryContents request)
{
// using EnumerateFileSystemInfos doesn't handle reparse points (symlinks)
- var entries = new DirectoryInfo(request.Path).EnumerateDirectories("*", SearchOption.TopDirectoryOnly)
- .Concat<FileSystemInfo>(new DirectoryInfo(request.Path).EnumerateFiles("*", SearchOption.TopDirectoryOnly)).Where(i =>
+ var entries = _fileSystem.GetFileSystemEntries(request.Path).Where(i =>
{
if (!request.IncludeHidden && i.Attributes.HasFlag(FileAttributes.Hidden))
{
diff --git a/MediaBrowser.Api/Images/ImageByNameService.cs b/MediaBrowser.Api/Images/ImageByNameService.cs
index b4d5a9949..a6e1af516 100644
--- a/MediaBrowser.Api/Images/ImageByNameService.cs
+++ b/MediaBrowser.Api/Images/ImageByNameService.cs
@@ -130,8 +130,7 @@ namespace MediaBrowser.Api.Images
{
try
{
- return new DirectoryInfo(path)
- .GetFiles("*", SearchOption.AllDirectories)
+ return _fileSystem.GetFiles(path)
.Where(i => BaseItem.SupportedImageExtensions.Contains(i.Extension, StringComparer.Ordinal))
.Select(i => new ImageByNameInfo
{
@@ -184,7 +183,7 @@ namespace MediaBrowser.Api.Images
var paths = BaseItem.SupportedImageExtensions.Select(i => Path.Combine(_appPaths.GeneralPath, request.Name, filename + i)).ToList();
- var path = paths.FirstOrDefault(File.Exists) ?? paths.FirstOrDefault();
+ var path = paths.FirstOrDefault(_fileSystem.FileExists) ?? paths.FirstOrDefault();
return ToStaticFileResult(path);
}
@@ -198,11 +197,11 @@ namespace MediaBrowser.Api.Images
{
var themeFolder = Path.Combine(_appPaths.RatingsPath, request.Theme);
- if (Directory.Exists(themeFolder))
+ if (_fileSystem.DirectoryExists(themeFolder))
{
var path = BaseItem.SupportedImageExtensions
.Select(i => Path.Combine(themeFolder, request.Name + i))
- .FirstOrDefault(File.Exists);
+ .FirstOrDefault(_fileSystem.FileExists);
if (!string.IsNullOrEmpty(path))
{
@@ -212,14 +211,14 @@ namespace MediaBrowser.Api.Images
var allFolder = Path.Combine(_appPaths.RatingsPath, "all");
- if (Directory.Exists(allFolder))
+ if (_fileSystem.DirectoryExists(allFolder))
{
// Avoid implicitly captured closure
var currentRequest = request;
var path = BaseItem.SupportedImageExtensions
.Select(i => Path.Combine(allFolder, currentRequest.Name + i))
- .FirstOrDefault(File.Exists);
+ .FirstOrDefault(_fileSystem.FileExists);
if (!string.IsNullOrEmpty(path))
{
@@ -239,10 +238,10 @@ namespace MediaBrowser.Api.Images
{
var themeFolder = Path.Combine(_appPaths.MediaInfoImagesPath, request.Theme);
- if (Directory.Exists(themeFolder))
+ if (_fileSystem.DirectoryExists(themeFolder))
{
var path = BaseItem.SupportedImageExtensions.Select(i => Path.Combine(themeFolder, request.Name + i))
- .FirstOrDefault(File.Exists);
+ .FirstOrDefault(_fileSystem.FileExists);
if (!string.IsNullOrEmpty(path))
{
@@ -252,13 +251,13 @@ namespace MediaBrowser.Api.Images
var allFolder = Path.Combine(_appPaths.MediaInfoImagesPath, "all");
- if (Directory.Exists(allFolder))
+ if (_fileSystem.DirectoryExists(allFolder))
{
// Avoid implicitly captured closure
var currentRequest = request;
var path = BaseItem.SupportedImageExtensions.Select(i => Path.Combine(allFolder, currentRequest.Name + i))
- .FirstOrDefault(File.Exists);
+ .FirstOrDefault(_fileSystem.FileExists);
if (!string.IsNullOrEmpty(path))
{
diff --git a/MediaBrowser.Api/Images/RemoteImageService.cs b/MediaBrowser.Api/Images/RemoteImageService.cs
index 6d2579ea9..c67ef96c9 100644
--- a/MediaBrowser.Api/Images/RemoteImageService.cs
+++ b/MediaBrowser.Api/Images/RemoteImageService.cs
@@ -237,7 +237,7 @@ namespace MediaBrowser.Api.Images
contentPath = await reader.ReadToEndAsync().ConfigureAwait(false);
}
- if (File.Exists(contentPath))
+ if (_fileSystem.FileExists(contentPath))
{
return ToStaticFileResult(contentPath);
}
@@ -281,7 +281,7 @@ namespace MediaBrowser.Api.Images
var fullCachePath = GetFullCachePath(urlHash + "." + ext);
- Directory.CreateDirectory(Path.GetDirectoryName(fullCachePath));
+ _fileSystem.CreateDirectory(Path.GetDirectoryName(fullCachePath));
using (var stream = result.Content)
{
using (var filestream = _fileSystem.GetFileStream(fullCachePath, FileMode.Create, FileAccess.Write, FileShare.Read, true))
@@ -290,7 +290,7 @@ namespace MediaBrowser.Api.Images
}
}
- Directory.CreateDirectory(Path.GetDirectoryName(pointerCachePath));
+ _fileSystem.CreateDirectory(Path.GetDirectoryName(pointerCachePath));
using (var writer = new StreamWriter(pointerCachePath))
{
await writer.WriteAsync(fullCachePath).ConfigureAwait(false);
diff --git a/MediaBrowser.Api/ItemLookupService.cs b/MediaBrowser.Api/ItemLookupService.cs
index a0ba6e61f..9f7f57155 100644
--- a/MediaBrowser.Api/ItemLookupService.cs
+++ b/MediaBrowser.Api/ItemLookupService.cs
@@ -200,7 +200,7 @@ namespace MediaBrowser.Api
//}
item.ProviderIds = request.ProviderIds;
- var task = _providerManager.RefreshFullItem(item, new MetadataRefreshOptions
+ var task = _providerManager.RefreshFullItem(item, new MetadataRefreshOptions(_fileSystem)
{
MetadataRefreshMode = MetadataRefreshMode.FullRefresh,
ImageRefreshMode = ImageRefreshMode.FullRefresh,
@@ -230,7 +230,7 @@ namespace MediaBrowser.Api
contentPath = await reader.ReadToEndAsync().ConfigureAwait(false);
}
- if (File.Exists(contentPath))
+ if (_fileSystem.FileExists(contentPath))
{
return ToStaticFileResult(contentPath);
}
@@ -271,7 +271,7 @@ namespace MediaBrowser.Api
var fullCachePath = GetFullCachePath(urlHash + "." + ext);
- Directory.CreateDirectory(Path.GetDirectoryName(fullCachePath));
+ _fileSystem.CreateDirectory(Path.GetDirectoryName(fullCachePath));
using (var stream = result.Content)
{
using (var filestream = _fileSystem.GetFileStream(fullCachePath, FileMode.Create, FileAccess.Write, FileShare.Read, true))
@@ -280,7 +280,7 @@ namespace MediaBrowser.Api
}
}
- Directory.CreateDirectory(Path.GetDirectoryName(pointerCachePath));
+ _fileSystem.CreateDirectory(Path.GetDirectoryName(pointerCachePath));
using (var writer = new StreamWriter(pointerCachePath))
{
await writer.WriteAsync(fullCachePath).ConfigureAwait(false);
diff --git a/MediaBrowser.Api/ItemRefreshService.cs b/MediaBrowser.Api/ItemRefreshService.cs
index f56fd3282..1e74b3692 100644
--- a/MediaBrowser.Api/ItemRefreshService.cs
+++ b/MediaBrowser.Api/ItemRefreshService.cs
@@ -4,6 +4,7 @@ using MediaBrowser.Controller.Net;
using MediaBrowser.Controller.Providers;
using ServiceStack;
using System.Threading;
+using MediaBrowser.Common.IO;
namespace MediaBrowser.Api
{
@@ -37,11 +38,13 @@ namespace MediaBrowser.Api
{
private readonly ILibraryManager _libraryManager;
private readonly IProviderManager _providerManager;
+ private readonly IFileSystem _fileSystem;
- public ItemRefreshService(ILibraryManager libraryManager, IProviderManager providerManager)
+ public ItemRefreshService(ILibraryManager libraryManager, IProviderManager providerManager, IFileSystem fileSystem)
{
_libraryManager = libraryManager;
_providerManager = providerManager;
+ _fileSystem = fileSystem;
}
/// <summary>
@@ -66,7 +69,7 @@ namespace MediaBrowser.Api
private MetadataRefreshOptions GetRefreshOptions(BaseRefreshRequest request)
{
- return new MetadataRefreshOptions(new DirectoryService())
+ return new MetadataRefreshOptions(new DirectoryService(_fileSystem))
{
MetadataRefreshMode = request.MetadataRefreshMode,
ImageRefreshMode = request.ImageRefreshMode,
diff --git a/MediaBrowser.Api/Library/LibraryHelpers.cs b/MediaBrowser.Api/Library/LibraryHelpers.cs
index 0ee28d6fe..5e40ac635 100644
--- a/MediaBrowser.Api/Library/LibraryHelpers.cs
+++ b/MediaBrowser.Api/Library/LibraryHelpers.cs
@@ -33,7 +33,7 @@ namespace MediaBrowser.Api.Library
var rootFolderPath = appPaths.DefaultUserViewsPath;
var path = Path.Combine(rootFolderPath, virtualFolderName);
- if (!Directory.Exists(path))
+ if (!fileSystem.DirectoryExists(path))
{
throw new DirectoryNotFoundException(string.Format("The media collection {0} does not exist", virtualFolderName));
}
@@ -57,7 +57,7 @@ namespace MediaBrowser.Api.Library
/// <exception cref="System.ArgumentException">The path is not valid.</exception>
public static void AddMediaPath(IFileSystem fileSystem, string virtualFolderName, string path, IServerApplicationPaths appPaths)
{
- if (!Directory.Exists(path))
+ if (!fileSystem.DirectoryExists(path))
{
throw new DirectoryNotFoundException("The path does not exist.");
}
@@ -69,7 +69,7 @@ namespace MediaBrowser.Api.Library
var lnk = Path.Combine(virtualFolderPath, shortcutFilename + ShortcutFileExtension);
- while (File.Exists(lnk))
+ while (fileSystem.FileExists(lnk))
{
shortcutFilename += "1";
lnk = Path.Combine(virtualFolderPath, shortcutFilename + ShortcutFileExtension);
diff --git a/MediaBrowser.Api/Library/LibraryService.cs b/MediaBrowser.Api/Library/LibraryService.cs
index 49dd121ba..eb1cd6084 100644
--- a/MediaBrowser.Api/Library/LibraryService.cs
+++ b/MediaBrowser.Api/Library/LibraryService.cs
@@ -27,6 +27,7 @@ using System.IO;
using System.Linq;
using System.Threading;
using System.Threading.Tasks;
+using MediaBrowser.Common.IO;
namespace MediaBrowser.Api.Library
{
@@ -282,12 +283,13 @@ namespace MediaBrowser.Api.Library
private readonly IChannelManager _channelManager;
private readonly ITVSeriesManager _tvManager;
private readonly ILibraryMonitor _libraryMonitor;
+ private readonly IFileSystem _fileSystem;
/// <summary>
/// Initializes a new instance of the <see cref="LibraryService" /> class.
/// </summary>
public LibraryService(IItemRepository itemRepo, ILibraryManager libraryManager, IUserManager userManager,
- IDtoService dtoService, IUserDataManager userDataManager, IAuthorizationContext authContext, IActivityManager activityManager, ILocalizationManager localization, ILiveTvManager liveTv, IChannelManager channelManager, ITVSeriesManager tvManager, ILibraryMonitor libraryMonitor)
+ IDtoService dtoService, IUserDataManager userDataManager, IAuthorizationContext authContext, IActivityManager activityManager, ILocalizationManager localization, ILiveTvManager liveTv, IChannelManager channelManager, ITVSeriesManager tvManager, ILibraryMonitor libraryMonitor, IFileSystem fileSystem)
{
_itemRepo = itemRepo;
_libraryManager = libraryManager;
@@ -301,6 +303,7 @@ namespace MediaBrowser.Api.Library
_channelManager = channelManager;
_tvManager = tvManager;
_libraryMonitor = libraryMonitor;
+ _fileSystem = fileSystem;
}
public object Get(GetSimilarItems request)
@@ -557,7 +560,7 @@ namespace MediaBrowser.Api.Library
{
throw new ArgumentException("This command cannot be used for remote or virtual items.");
}
- if (Directory.Exists(item.Path))
+ if (_fileSystem.DirectoryExists(item.Path))
{
throw new ArgumentException("This command cannot be used for directories.");
}
diff --git a/MediaBrowser.Api/Library/LibraryStructureService.cs b/MediaBrowser.Api/Library/LibraryStructureService.cs
index f5fe921ce..c8731637c 100644
--- a/MediaBrowser.Api/Library/LibraryStructureService.cs
+++ b/MediaBrowser.Api/Library/LibraryStructureService.cs
@@ -195,7 +195,7 @@ namespace MediaBrowser.Api.Library
var virtualFolderPath = Path.Combine(rootFolderPath, name);
- if (Directory.Exists(virtualFolderPath))
+ if (_fileSystem.DirectoryExists(virtualFolderPath))
{
throw new ArgumentException("There is already a media collection with the name " + name + ".");
}
@@ -204,13 +204,16 @@ namespace MediaBrowser.Api.Library
try
{
- Directory.CreateDirectory(virtualFolderPath);
+ _fileSystem.CreateDirectory(virtualFolderPath);
if (!string.IsNullOrEmpty(request.CollectionType))
{
var path = Path.Combine(virtualFolderPath, request.CollectionType + ".collection");
- File.Create(path);
+ using (File.Create(path))
+ {
+
+ }
}
}
finally
@@ -256,12 +259,12 @@ namespace MediaBrowser.Api.Library
var currentPath = Path.Combine(rootFolderPath, request.Name);
var newPath = Path.Combine(rootFolderPath, request.NewName);
- if (!Directory.Exists(currentPath))
+ if (!_fileSystem.DirectoryExists(currentPath))
{
throw new DirectoryNotFoundException("The media collection does not exist");
}
- if (!string.Equals(currentPath, newPath, StringComparison.OrdinalIgnoreCase) && Directory.Exists(newPath))
+ if (!string.Equals(currentPath, newPath, StringComparison.OrdinalIgnoreCase) && _fileSystem.DirectoryExists(newPath))
{
throw new ArgumentException("There is already a media collection with the name " + newPath + ".");
}
@@ -276,11 +279,11 @@ namespace MediaBrowser.Api.Library
//Create an unique name
var temporaryName = Guid.NewGuid().ToString();
var temporaryPath = Path.Combine(rootFolderPath, temporaryName);
- Directory.Move(currentPath, temporaryPath);
+ _fileSystem.MoveDirectory(currentPath, temporaryPath);
currentPath = temporaryPath;
}
- Directory.Move(currentPath, newPath);
+ _fileSystem.MoveDirectory(currentPath, newPath);
}
finally
{
@@ -319,7 +322,7 @@ namespace MediaBrowser.Api.Library
var path = Path.Combine(rootFolderPath, request.Name);
- if (!Directory.Exists(path))
+ if (!_fileSystem.DirectoryExists(path))
{
throw new DirectoryNotFoundException("The media folder does not exist");
}
diff --git a/MediaBrowser.Api/MediaBrowser.Api.csproj b/MediaBrowser.Api/MediaBrowser.Api.csproj
index 295cc78e9..901dd11e2 100644
--- a/MediaBrowser.Api/MediaBrowser.Api.csproj
+++ b/MediaBrowser.Api/MediaBrowser.Api.csproj
@@ -11,10 +11,10 @@
<AssemblyName>MediaBrowser.Api</AssemblyName>
<FileAlignment>512</FileAlignment>
<SolutionDir Condition="$(SolutionDir) == '' Or $(SolutionDir) == '*Undefined*'">..\</SolutionDir>
- <ProductVersion>10.0.0</ProductVersion>
- <SchemaVersion>2.0</SchemaVersion>
<TargetFrameworkVersion>v4.5</TargetFrameworkVersion>
<RestorePackages>true</RestorePackages>
+ <ReleaseVersion>
+ </ReleaseVersion>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
<DebugSymbols>true</DebugSymbols>
@@ -25,7 +25,6 @@
<ErrorReport>prompt</ErrorReport>
<WarningLevel>4</WarningLevel>
<PlatformTarget>AnyCPU</PlatformTarget>
- <TargetFrameworkVersion>v4.5</TargetFrameworkVersion>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
<DebugType>none</DebugType>
@@ -34,7 +33,6 @@
<DefineConstants>TRACE</DefineConstants>
<ErrorReport>prompt</ErrorReport>
<WarningLevel>4</WarningLevel>
- <TargetFrameworkVersion>v4.5</TargetFrameworkVersion>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release Mono|AnyCPU' ">
<DebugType>none</DebugType>
@@ -43,16 +41,11 @@
<DefineConstants>TRACE</DefineConstants>
<ErrorReport>prompt</ErrorReport>
<WarningLevel>4</WarningLevel>
- <TargetFrameworkVersion>v4.5</TargetFrameworkVersion>
</PropertyGroup>
<PropertyGroup>
<RunPostBuildEvent>Always</RunPostBuildEvent>
</PropertyGroup>
<ItemGroup>
- <Reference Include="MoreLinq, Version=1.1.17511.0, Culture=neutral, PublicKeyToken=384d532d7e88985d, processorArchitecture=MSIL">
- <SpecificVersion>False</SpecificVersion>
- <HintPath>..\packages\morelinq.1.1.0\lib\net35\MoreLinq.dll</HintPath>
- </Reference>
<Reference Include="System" />
<Reference Include="System.Core" />
<Reference Include="Microsoft.CSharp" />
@@ -64,12 +57,14 @@
<Reference Include="ServiceStack.Text">
<HintPath>..\ThirdParty\ServiceStack.Text\ServiceStack.Text.dll</HintPath>
</Reference>
+ <Reference Include="MoreLinq">
+ <HintPath>..\packages\morelinq.1.1.1\lib\net35\MoreLinq.dll</HintPath>
+ </Reference>
</ItemGroup>
<ItemGroup>
<Compile Include="..\SharedVersion.cs">
<Link>Properties\SharedVersion.cs</Link>
</Compile>
- <Compile Include="AppThemeService.cs" />
<Compile Include="BrandingService.cs" />
<Compile Include="ChannelService.cs" />
<Compile Include="ConnectService.cs" />
diff --git a/MediaBrowser.Api/Playback/BaseStreamingService.cs b/MediaBrowser.Api/Playback/BaseStreamingService.cs
index 531d67eed..86f06213c 100644
--- a/MediaBrowser.Api/Playback/BaseStreamingService.cs
+++ b/MediaBrowser.Api/Playback/BaseStreamingService.cs
@@ -290,13 +290,6 @@ namespace MediaBrowser.Api.Playback
{
get
{
- var lib = ApiEntryPoint.Instance.GetEncodingOptions().H264Encoder;
-
- if (!string.IsNullOrWhiteSpace(lib))
- {
- return lib;
- }
-
return "libx264";
}
}
@@ -810,13 +803,53 @@ namespace MediaBrowser.Api.Playback
}
/// <summary>
+ /// Gets the name of the output video codec
+ /// </summary>
+ /// <param name="state">The state.</param>
+ /// <returns>System.String.</returns>
+ protected string GetVideoDecoder(StreamState state)
+ {
+ if (string.Equals(ApiEntryPoint.Instance.GetEncodingOptions().HardwareVideoDecoder, "qsv", StringComparison.OrdinalIgnoreCase))
+ {
+ if (state.VideoStream != null && !string.IsNullOrWhiteSpace(state.VideoStream.Codec))
+ {
+ switch (state.MediaSource.VideoStream.Codec.ToLower())
+ {
+ case "avc":
+ case "h264":
+ if (MediaEncoder.SupportsDecoder("h264_qsv"))
+ {
+ return "-c:v h264_qsv ";
+ }
+ break;
+ case "mpeg2video":
+ if (MediaEncoder.SupportsDecoder("mpeg2_qsv"))
+ {
+ return "-c:v mpeg2_qsv ";
+ }
+ break;
+ case "vc1":
+ if (MediaEncoder.SupportsDecoder("vc1_qsv"))
+ {
+ return "-c:v vc1_qsv ";
+ }
+ break;
+ }
+ }
+ }
+
+ // leave blank so ffmpeg will decide
+ return string.Empty;
+ }
+
+ /// <summary>
/// Gets the input argument.
/// </summary>
/// <param name="state">The state.</param>
/// <returns>System.String.</returns>
protected string GetInputArgument(StreamState state)
{
- var arg = "-i " + GetInputPathArgument(state);
+ var arg = string.Format("{1}-i {0}", GetInputPathArgument(state), GetVideoDecoder(state));
if (state.SubtitleStream != null)
{
@@ -826,7 +859,7 @@ namespace MediaBrowser.Api.Playback
}
}
- return arg;
+ return arg.Trim();
}
private string GetInputPathArgument(StreamState state)
@@ -889,7 +922,7 @@ namespace MediaBrowser.Api.Playback
CancellationTokenSource cancellationTokenSource,
string workingDirectory = null)
{
- Directory.CreateDirectory(Path.GetDirectoryName(outputPath));
+ FileSystem.CreateDirectory(Path.GetDirectoryName(outputPath));
await AcquireResources(state, cancellationTokenSource).ConfigureAwait(false);
@@ -942,7 +975,7 @@ namespace MediaBrowser.Api.Playback
Logger.Info(commandLineLogMessage);
var logFilePath = Path.Combine(ServerConfigurationManager.ApplicationPaths.LogDirectoryPath, "transcode-" + Guid.NewGuid() + ".txt");
- Directory.CreateDirectory(Path.GetDirectoryName(logFilePath));
+ FileSystem.CreateDirectory(Path.GetDirectoryName(logFilePath));
// FFMpeg writes debug/error info to stderr. This is useful when debugging so let's put it in the log directory.
state.LogFileStream = FileSystem.GetFileStream(logFilePath, FileMode.Create, FileAccess.Write, FileShare.Read, true);
@@ -972,7 +1005,7 @@ namespace MediaBrowser.Api.Playback
StartStreamingLog(transcodingJob, state, process.StandardError.BaseStream, state.LogFileStream);
// Wait for the file to exist before proceeeding
- while (!File.Exists(state.WaitForPath ?? outputPath) && !transcodingJob.HasExited)
+ while (!FileSystem.FileExists(state.WaitForPath ?? outputPath) && !transcodingJob.HasExited)
{
await Task.Delay(100, cancellationTokenSource.Token).ConfigureAwait(false);
}
diff --git a/MediaBrowser.Api/Playback/Dash/MpegDashService.cs b/MediaBrowser.Api/Playback/Dash/MpegDashService.cs
index c201ffd58..cbee821d2 100644
--- a/MediaBrowser.Api/Playback/Dash/MpegDashService.cs
+++ b/MediaBrowser.Api/Playback/Dash/MpegDashService.cs
@@ -174,7 +174,7 @@ namespace MediaBrowser.Api.Playback.Dash
var workingDirectory = Path.Combine(Path.GetDirectoryName(playlistPath), (startNumber == -1 ? 0 : startNumber).ToString(CultureInfo.InvariantCulture));
state.WaitForPath = Path.Combine(workingDirectory, Path.GetFileName(playlistPath));
- Directory.CreateDirectory(workingDirectory);
+ FileSystem.CreateDirectory(workingDirectory);
job = await StartFfMpeg(state, playlistPath, cancellationTokenSource, workingDirectory).ConfigureAwait(false);
await WaitForMinimumDashSegmentCount(Path.Combine(workingDirectory, Path.GetFileName(playlistPath)), 1, cancellationTokenSource.Token).ConfigureAwait(false);
}
@@ -328,8 +328,7 @@ namespace MediaBrowser.Api.Playback.Dash
try
{
- return new DirectoryInfo(folder)
- .EnumerateFiles("*", SearchOption.AllDirectories)
+ return fileSystem.GetFiles(folder)
.Where(i => string.Equals(i.Extension, segmentExtension, StringComparison.OrdinalIgnoreCase))
.OrderByDescending(fileSystem.GetLastWriteTimeUtc)
.Take(count)
@@ -348,20 +347,20 @@ namespace MediaBrowser.Api.Playback.Dash
if (requestedIndex == -1)
{
var path = Path.Combine(folder, "0", "stream" + representationId + "-" + "init" + segmentExtension);
- return File.Exists(path) ? path : null;
+ return FileSystem.FileExists(path) ? path : null;
}
try
{
- foreach (var subfolder in new DirectoryInfo(folder).EnumerateDirectories().ToList())
+ foreach (var subfolder in FileSystem.GetDirectoryPaths(folder).ToList())
{
- var subfolderName = Path.GetFileNameWithoutExtension(subfolder.FullName);
+ var subfolderName = Path.GetFileNameWithoutExtension(subfolder);
int startNumber;
if (int.TryParse(subfolderName, NumberStyles.Any, UsCulture, out startNumber))
{
var segmentIndex = requestedIndex - startNumber + 1;
var path = Path.Combine(folder, subfolderName, "stream" + representationId + "-" + segmentIndex.ToString("00000", CultureInfo.InvariantCulture) + segmentExtension);
- if (File.Exists(path))
+ if (FileSystem.FileExists(path))
{
return path;
}
diff --git a/MediaBrowser.Api/Playback/Hls/BaseHlsService.cs b/MediaBrowser.Api/Playback/Hls/BaseHlsService.cs
index 5d377366a..036397b4f 100644
--- a/MediaBrowser.Api/Playback/Hls/BaseHlsService.cs
+++ b/MediaBrowser.Api/Playback/Hls/BaseHlsService.cs
@@ -90,12 +90,12 @@ namespace MediaBrowser.Api.Playback.Hls
TranscodingJob job = null;
var playlist = state.OutputFilePath;
- if (!File.Exists(playlist))
+ if (!FileSystem.FileExists(playlist))
{
await ApiEntryPoint.Instance.TranscodingStartLock.WaitAsync(cancellationTokenSource.Token).ConfigureAwait(false);
try
{
- if (!File.Exists(playlist))
+ if (!FileSystem.FileExists(playlist))
{
// If the playlist doesn't already exist, startup ffmpeg
try
@@ -312,31 +312,6 @@ namespace MediaBrowser.Api.Playback.Hls
return 0;
}
- protected override bool CanStreamCopyVideo(VideoStreamRequest request, MediaStream videoStream)
- {
- if (videoStream.KeyFrames == null || videoStream.KeyFrames.Count == 0)
- {
- Logger.Debug("Cannot stream copy video due to missing keyframe info");
- return false;
- }
-
- var previousSegment = 0;
- foreach (var frame in videoStream.KeyFrames)
- {
- var length = frame - previousSegment;
-
- // Don't allow really long segments because this could result in long download times
- if (length > 10000)
- {
- Logger.Debug("Cannot stream copy video due to long segment length of {0}ms", length);
- return false;
- }
- previousSegment = frame;
- }
-
- return base.CanStreamCopyVideo(request, videoStream);
- }
-
protected override bool CanStreamCopyAudio(VideoStreamRequest request, MediaStream audioStream, List<string> supportedAudioCodecs)
{
return false;
diff --git a/MediaBrowser.Api/Playback/Hls/DynamicHlsService.cs b/MediaBrowser.Api/Playback/Hls/DynamicHlsService.cs
index cbea1ca0c..9359c65f2 100644
--- a/MediaBrowser.Api/Playback/Hls/DynamicHlsService.cs
+++ b/MediaBrowser.Api/Playback/Hls/DynamicHlsService.cs
@@ -165,7 +165,7 @@ namespace MediaBrowser.Api.Playback.Hls
TranscodingJob job = null;
- if (File.Exists(segmentPath))
+ if (FileSystem.FileExists(segmentPath))
{
job = ApiEntryPoint.Instance.OnTranscodeBeginRequest(playlistPath, TranscodingJobType);
return await GetSegmentResult(state, playlistPath, segmentPath, requestedIndex, job, cancellationToken).ConfigureAwait(false);
@@ -174,7 +174,7 @@ namespace MediaBrowser.Api.Playback.Hls
await ApiEntryPoint.Instance.TranscodingStartLock.WaitAsync(cancellationTokenSource.Token).ConfigureAwait(false);
try
{
- if (File.Exists(segmentPath))
+ if (FileSystem.FileExists(segmentPath))
{
job = ApiEntryPoint.Instance.OnTranscodeBeginRequest(playlistPath, TranscodingJobType);
return await GetSegmentResult(state, playlistPath, segmentPath, requestedIndex, job, cancellationToken).ConfigureAwait(false);
@@ -285,20 +285,23 @@ namespace MediaBrowser.Api.Playback.Hls
private double[] GetSegmentLengths(StreamState state)
{
var result = new List<double>();
- var encoder = GetVideoEncoder(state);
-
- if (string.Equals(encoder, "copy", StringComparison.OrdinalIgnoreCase))
+ if (state.VideoRequest != null)
{
- var videoStream = state.VideoStream;
- if (videoStream.KeyFrames != null && videoStream.KeyFrames.Count > 0)
+ var encoder = GetVideoEncoder(state);
+
+ if (string.Equals(encoder, "copy", StringComparison.OrdinalIgnoreCase))
{
- foreach (var frame in videoStream.KeyFrames)
+ var videoStream = state.VideoStream;
+ if (videoStream.KeyFrames != null && videoStream.KeyFrames.Count > 0)
{
- var seconds = TimeSpan.FromMilliseconds(frame).TotalSeconds;
- seconds -= result.Sum();
- result.Add(seconds);
+ foreach (var frame in videoStream.KeyFrames)
+ {
+ var seconds = TimeSpan.FromMilliseconds(frame).TotalSeconds;
+ seconds -= result.Sum();
+ result.Add(seconds);
+ }
+ return result.ToArray();
}
- return result.ToArray();
}
}
@@ -383,8 +386,7 @@ namespace MediaBrowser.Api.Playback.Hls
try
{
- return new DirectoryInfo(folder)
- .EnumerateFiles("*", SearchOption.TopDirectoryOnly)
+ return fileSystem.GetFiles(folder)
.Where(i => string.Equals(i.Extension, segmentExtension, StringComparison.OrdinalIgnoreCase) && Path.GetFileNameWithoutExtension(i.Name).StartsWith(filePrefix, StringComparison.OrdinalIgnoreCase))
.OrderByDescending(fileSystem.GetLastWriteTimeUtc)
.FirstOrDefault();
@@ -429,7 +431,7 @@ namespace MediaBrowser.Api.Playback.Hls
CancellationToken cancellationToken)
{
// If all transcoding has completed, just return immediately
- if (transcodingJob != null && transcodingJob.HasExited && File.Exists(segmentPath))
+ if (transcodingJob != null && transcodingJob.HasExited && FileSystem.FileExists(segmentPath))
{
return GetSegmentResult(state, segmentPath, segmentIndex, transcodingJob);
}
@@ -449,7 +451,7 @@ namespace MediaBrowser.Api.Playback.Hls
// If it appears in the playlist, it's done
if (text.IndexOf(segmentFilename, StringComparison.OrdinalIgnoreCase) != -1)
{
- if (File.Exists(segmentPath))
+ if (FileSystem.FileExists(segmentPath))
{
return GetSegmentResult(state, segmentPath, segmentIndex, transcodingJob);
}
@@ -960,5 +962,30 @@ namespace MediaBrowser.Api.Playback.Hls
{
return isOutputVideo ? ".ts" : ".ts";
}
+
+ protected override bool CanStreamCopyVideo(VideoStreamRequest request, MediaStream videoStream)
+ {
+ if (videoStream.KeyFrames == null || videoStream.KeyFrames.Count == 0)
+ {
+ Logger.Debug("Cannot stream copy video due to missing keyframe info");
+ return false;
+ }
+
+ var previousSegment = 0;
+ foreach (var frame in videoStream.KeyFrames)
+ {
+ var length = frame - previousSegment;
+
+ // Don't allow really long segments because this could result in long download times
+ if (length > 10000)
+ {
+ Logger.Debug("Cannot stream copy video due to long segment length of {0}ms", length);
+ return false;
+ }
+ previousSegment = frame;
+ }
+
+ return base.CanStreamCopyVideo(request, videoStream);
+ }
}
}
diff --git a/MediaBrowser.Api/Playback/MediaInfoService.cs b/MediaBrowser.Api/Playback/MediaInfoService.cs
index 0b7b50134..2ab2d11f6 100644
--- a/MediaBrowser.Api/Playback/MediaInfoService.cs
+++ b/MediaBrowser.Api/Playback/MediaInfoService.cs
@@ -57,7 +57,7 @@ namespace MediaBrowser.Api.Playback
Size = 102400;
}
}
-
+
[Authenticated]
public class MediaInfoService : BaseApiService
{
@@ -289,7 +289,7 @@ namespace MediaBrowser.Api.Playback
if (mediaSource.SupportsDirectStream)
{
options.MaxBitrate = GetMaxBitrate(maxBitrate);
-
+
// The MediaSource supports direct stream, now test to see if the client supports it
var streamInfo = string.Equals(item.MediaType, MediaType.Audio, StringComparison.OrdinalIgnoreCase) ?
streamBuilder.BuildAudioItem(options) :
@@ -309,7 +309,7 @@ namespace MediaBrowser.Api.Playback
if (mediaSource.SupportsTranscoding)
{
options.MaxBitrate = GetMaxBitrate(maxBitrate);
-
+
// The MediaSource supports direct stream, now test to see if the client supports it
var streamInfo = string.Equals(item.MediaType, MediaType.Audio, StringComparison.OrdinalIgnoreCase) ?
streamBuilder.BuildAudioItem(options) :
@@ -336,9 +336,15 @@ namespace MediaBrowser.Api.Playback
var maxBitrate = clientMaxBitrate;
var remoteClientMaxBitrate = _config.Configuration.RemoteClientBitrateLimit;
- if (remoteClientMaxBitrate > 0 && !_networkManager.IsInLocalNetwork(Request.RemoteIp))
+ if (remoteClientMaxBitrate > 0)
{
- maxBitrate = Math.Min(maxBitrate ?? remoteClientMaxBitrate, remoteClientMaxBitrate);
+ var isInLocalNetwork = _networkManager.IsInLocalNetwork(Request.RemoteIp);
+
+ Logger.Info("RemoteClientBitrateLimit: {0}, RemoteIp: {1}, IsInLocalNetwork: {2}", remoteClientMaxBitrate, Request.RemoteIp, isInLocalNetwork);
+ if (!isInLocalNetwork)
+ {
+ maxBitrate = Math.Min(maxBitrate ?? remoteClientMaxBitrate, remoteClientMaxBitrate);
+ }
}
return maxBitrate;
diff --git a/MediaBrowser.Api/Playback/Progressive/BaseProgressiveStreamingService.cs b/MediaBrowser.Api/Playback/Progressive/BaseProgressiveStreamingService.cs
index 910ac18e7..aa0cda133 100644
--- a/MediaBrowser.Api/Playback/Progressive/BaseProgressiveStreamingService.cs
+++ b/MediaBrowser.Api/Playback/Progressive/BaseProgressiveStreamingService.cs
@@ -139,7 +139,7 @@ namespace MediaBrowser.Api.Playback.Progressive
}
var outputPath = state.OutputFilePath;
- var outputPathExists = File.Exists(outputPath);
+ var outputPathExists = FileSystem.FileExists(outputPath);
var isTranscodeCached = outputPathExists && !ApiEntryPoint.Instance.HasActiveTranscodingJob(outputPath, TranscodingJobType.Progressive);
@@ -325,7 +325,7 @@ namespace MediaBrowser.Api.Playback.Progressive
{
TranscodingJob job;
- if (!File.Exists(outputPath))
+ if (!FileSystem.FileExists(outputPath))
{
job = await StartFfMpeg(state, outputPath, cancellationTokenSource).ConfigureAwait(false);
}
diff --git a/MediaBrowser.Api/Playback/Progressive/VideoService.cs b/MediaBrowser.Api/Playback/Progressive/VideoService.cs
index 84ae26248..1dfb43387 100644
--- a/MediaBrowser.Api/Playback/Progressive/VideoService.cs
+++ b/MediaBrowser.Api/Playback/Progressive/VideoService.cs
@@ -17,6 +17,7 @@ namespace MediaBrowser.Api.Playback.Progressive
/// <summary>
/// Class GetVideoStream
/// </summary>
+ [Route("/Videos/{Id}/stream.mpegts", "GET")]
[Route("/Videos/{Id}/stream.ts", "GET")]
[Route("/Videos/{Id}/stream.webm", "GET")]
[Route("/Videos/{Id}/stream.asf", "GET")]
diff --git a/MediaBrowser.Api/Playback/StreamState.cs b/MediaBrowser.Api/Playback/StreamState.cs
index 34dc5ea12..fdbe5835e 100644
--- a/MediaBrowser.Api/Playback/StreamState.cs
+++ b/MediaBrowser.Api/Playback/StreamState.cs
@@ -74,7 +74,7 @@ namespace MediaBrowser.Api.Playback
{
get
{
- return ReadInputAtNativeFramerate ? 1000 : 0;
+ return 0;
}
}
diff --git a/MediaBrowser.Api/Reports/Stat/ReportStatBuilder.cs b/MediaBrowser.Api/Reports/Stat/ReportStatBuilder.cs
index c9ee6337f..fb694d6e1 100644
--- a/MediaBrowser.Api/Reports/Stat/ReportStatBuilder.cs
+++ b/MediaBrowser.Api/Reports/Stat/ReportStatBuilder.cs
@@ -213,7 +213,7 @@ namespace MediaBrowser.Api.Reports
};
foreach (var item in t)
{
- var ps = items.Where(x => x.People != null && x.SupportsPeople).SelectMany(x => x.People)
+ var ps = items.SelectMany(x => _libraryManager.GetPeople(x))
.Where(n => n.Type == item.ToString())
.GroupBy(x => x.Name)
.OrderByDescending(x => x.Count())
diff --git a/MediaBrowser.Api/StartupWizardService.cs b/MediaBrowser.Api/StartupWizardService.cs
index e9ac45fa2..962334cdc 100644
--- a/MediaBrowser.Api/StartupWizardService.cs
+++ b/MediaBrowser.Api/StartupWizardService.cs
@@ -69,10 +69,10 @@ namespace MediaBrowser.Api
_config.Configuration.MergeMetadataAndImagesByName = true;
_config.Configuration.EnableStandaloneMetadata = true;
_config.Configuration.EnableLibraryMetadataSubFolder = true;
- _config.Configuration.EnableUserSpecificUserViews = true;
_config.Configuration.EnableCustomPathSubFolders = true;
_config.Configuration.DisableXmlSavers = true;
_config.Configuration.DisableStartupScan = true;
+ _config.Configuration.EnableUserViews = true;
_config.SaveConfiguration();
}
diff --git a/MediaBrowser.Api/Subtitles/SubtitleService.cs b/MediaBrowser.Api/Subtitles/SubtitleService.cs
index c9280b6f6..0bfe7354d 100644
--- a/MediaBrowser.Api/Subtitles/SubtitleService.cs
+++ b/MediaBrowser.Api/Subtitles/SubtitleService.cs
@@ -16,6 +16,7 @@ using System.Text;
using System.Threading;
using System.Threading.Tasks;
using MimeTypes = MediaBrowser.Model.Net.MimeTypes;
+using MediaBrowser.Common.IO;
namespace MediaBrowser.Api.Subtitles
{
@@ -127,14 +128,16 @@ namespace MediaBrowser.Api.Subtitles
private readonly ISubtitleEncoder _subtitleEncoder;
private readonly IMediaSourceManager _mediaSourceManager;
private readonly IProviderManager _providerManager;
+ private readonly IFileSystem _fileSystem;
- public SubtitleService(ILibraryManager libraryManager, ISubtitleManager subtitleManager, ISubtitleEncoder subtitleEncoder, IMediaSourceManager mediaSourceManager, IProviderManager providerManager)
+ public SubtitleService(ILibraryManager libraryManager, ISubtitleManager subtitleManager, ISubtitleEncoder subtitleEncoder, IMediaSourceManager mediaSourceManager, IProviderManager providerManager, IFileSystem fileSystem)
{
_libraryManager = libraryManager;
_subtitleManager = subtitleManager;
_subtitleEncoder = subtitleEncoder;
_mediaSourceManager = mediaSourceManager;
_providerManager = providerManager;
+ _fileSystem = fileSystem;
}
public async Task<object> Get(GetSubtitlePlaylist request)
@@ -259,7 +262,7 @@ namespace MediaBrowser.Api.Subtitles
await _subtitleManager.DownloadSubtitles(video, request.SubtitleId, CancellationToken.None)
.ConfigureAwait(false);
- _providerManager.QueueRefresh(video.Id, new MetadataRefreshOptions());
+ _providerManager.QueueRefresh(video.Id, new MetadataRefreshOptions(_fileSystem));
}
catch (Exception ex)
{
diff --git a/MediaBrowser.Api/System/SystemService.cs b/MediaBrowser.Api/System/SystemService.cs
index aa1226901..00935dd1e 100644
--- a/MediaBrowser.Api/System/SystemService.cs
+++ b/MediaBrowser.Api/System/SystemService.cs
@@ -122,8 +122,7 @@ namespace MediaBrowser.Api.System
try
{
- files = new DirectoryInfo(_appPaths.LogDirectoryPath)
- .EnumerateFiles("*", SearchOption.AllDirectories)
+ files = _fileSystem.GetFiles(_appPaths.LogDirectoryPath)
.Where(i => string.Equals(i.Extension, ".txt", StringComparison.OrdinalIgnoreCase))
.ToList();
}
@@ -149,8 +148,7 @@ namespace MediaBrowser.Api.System
public object Get(GetLogFile request)
{
- var file = new DirectoryInfo(_appPaths.LogDirectoryPath)
- .EnumerateFiles("*", SearchOption.AllDirectories)
+ var file = _fileSystem.GetFiles(_appPaths.LogDirectoryPath)
.First(i => string.Equals(i.Name, request.Name, StringComparison.OrdinalIgnoreCase));
return ResultFactory.GetStaticFileResult(Request, file.FullName, FileShare.ReadWrite);
diff --git a/MediaBrowser.Api/UserLibrary/UserViewsService.cs b/MediaBrowser.Api/UserLibrary/UserViewsService.cs
index a49ab8556..9d7c38d6f 100644
--- a/MediaBrowser.Api/UserLibrary/UserViewsService.cs
+++ b/MediaBrowser.Api/UserLibrary/UserViewsService.cs
@@ -39,6 +39,17 @@ namespace MediaBrowser.Api.UserLibrary
public string UserId { get; set; }
}
+ [Route("/Users/{UserId}/GroupingOptions", "GET")]
+ public class GetGroupingOptions : IReturn<List<SpecialViewOption>>
+ {
+ /// <summary>
+ /// Gets or sets the user id.
+ /// </summary>
+ /// <value>The user id.</value>
+ [ApiMember(Name = "UserId", Description = "User Id", IsRequired = true, DataType = "string", ParameterType = "path", Verb = "GET")]
+ public string UserId { get; set; }
+ }
+
public class UserViewsService : BaseApiService
{
private readonly IUserManager _userManager;
@@ -105,6 +116,29 @@ namespace MediaBrowser.Api.UserLibrary
return ToOptimizedResult(list);
}
+ public async Task<object> Get(GetGroupingOptions request)
+ {
+ var user = _userManager.GetUserById(request.UserId);
+
+ var views = user.RootFolder
+ .GetChildren(user, true)
+ .OfType<Folder>()
+ .Where(i => !UserView.IsExcludedFromGrouping(i))
+ .ToList();
+
+ var list = views
+ .Select(i => new SpecialViewOption
+ {
+ Name = i.Name,
+ Id = i.Id.ToString("N")
+
+ })
+ .OrderBy(i => i.Name)
+ .ToList();
+
+ return ToOptimizedResult(list);
+ }
+
private bool IsEligibleForSpecialView(ICollectionFolder view)
{
var types = new[] { CollectionType.Movies, CollectionType.TvShows, CollectionType.Games, CollectionType.Music, CollectionType.Photos };
diff --git a/MediaBrowser.Api/packages.config b/MediaBrowser.Api/packages.config
index 6df166204..0cdb26bd5 100644
--- a/MediaBrowser.Api/packages.config
+++ b/MediaBrowser.Api/packages.config
@@ -1,4 +1,4 @@
<?xml version="1.0" encoding="utf-8"?>
<packages>
- <package id="morelinq" version="1.1.0" targetFramework="net45" />
+ <package id="morelinq" version="1.1.1" targetFramework="net45" />
</packages> \ No newline at end of file