aboutsummaryrefslogtreecommitdiff
path: root/MediaBrowser.Api
diff options
context:
space:
mode:
Diffstat (limited to 'MediaBrowser.Api')
-rw-r--r--MediaBrowser.Api/ApiEntryPoint.cs15
-rw-r--r--MediaBrowser.Api/Devices/DeviceService.cs15
-rw-r--r--MediaBrowser.Api/Images/ImageService.cs11
-rw-r--r--MediaBrowser.Api/ItemUpdateService.cs4
-rw-r--r--MediaBrowser.Api/Library/LibraryService.cs31
-rw-r--r--MediaBrowser.Api/Library/LibraryStructureService.cs3
-rw-r--r--MediaBrowser.Api/LiveTv/LiveTvService.cs19
-rw-r--r--MediaBrowser.Api/LocalizationService.cs5
-rw-r--r--MediaBrowser.Api/MediaBrowser.Api.csproj1
-rw-r--r--MediaBrowser.Api/Movies/MoviesService.cs6
-rw-r--r--MediaBrowser.Api/PackageService.cs10
-rw-r--r--MediaBrowser.Api/Playback/BaseStreamingService.cs191
-rw-r--r--MediaBrowser.Api/Playback/Hls/BaseHlsService.cs19
-rw-r--r--MediaBrowser.Api/Playback/Hls/DynamicHlsService.cs40
-rw-r--r--MediaBrowser.Api/Playback/Hls/VideoHlsService.cs7
-rw-r--r--MediaBrowser.Api/Playback/MediaInfoService.cs3
-rw-r--r--MediaBrowser.Api/Playback/StreamState.cs94
-rw-r--r--MediaBrowser.Api/ScheduledTasks/ScheduledTasksWebSocketListener.cs1
-rw-r--r--MediaBrowser.Api/SearchService.cs5
-rw-r--r--MediaBrowser.Api/Session/SessionInfoWebSocketListener.cs1
-rw-r--r--MediaBrowser.Api/Session/SessionsService.cs3
-rw-r--r--MediaBrowser.Api/Subtitles/SubtitleService.cs4
-rw-r--r--MediaBrowser.Api/TvShowsService.cs3
-rw-r--r--MediaBrowser.Api/UserLibrary/ItemsService.cs16
-rw-r--r--MediaBrowser.Api/UserLibrary/UserViewsService.cs3
-rw-r--r--MediaBrowser.Api/UserService.cs21
-rw-r--r--MediaBrowser.Api/VideosService.cs3
27 files changed, 231 insertions, 303 deletions
diff --git a/MediaBrowser.Api/ApiEntryPoint.cs b/MediaBrowser.Api/ApiEntryPoint.cs
index 700cbb943..a223a4fe3 100644
--- a/MediaBrowser.Api/ApiEntryPoint.cs
+++ b/MediaBrowser.Api/ApiEntryPoint.cs
@@ -415,7 +415,7 @@ namespace MediaBrowser.Api
public void OnTranscodeEndRequest(TranscodingJob job)
{
job.ActiveRequestCount--;
- //Logger.LogDebug("OnTranscodeEndRequest job.ActiveRequestCount={0}", job.ActiveRequestCount);
+ Logger.LogDebug("OnTranscodeEndRequest job.ActiveRequestCount={0}", job.ActiveRequestCount);
if (job.ActiveRequestCount <= 0)
{
PingTimer(job, false);
@@ -428,7 +428,7 @@ namespace MediaBrowser.Api
throw new ArgumentNullException(nameof(playSessionId));
}
- //Logger.LogDebug("PingTranscodingJob PlaySessionId={0} isUsedPaused: {1}", playSessionId, isUserPaused);
+ Logger.LogDebug("PingTranscodingJob PlaySessionId={0} isUsedPaused: {1}", playSessionId, isUserPaused);
List<TranscodingJob> jobs;
@@ -443,7 +443,7 @@ namespace MediaBrowser.Api
{
if (isUserPaused.HasValue)
{
- //Logger.LogDebug("Setting job.IsUserPaused to {0}. jobId: {1}", isUserPaused, job.Id);
+ Logger.LogDebug("Setting job.IsUserPaused to {0}. jobId: {1}", isUserPaused, job.Id);
job.IsUserPaused = isUserPaused.Value;
}
PingTimer(job, true);
@@ -601,7 +601,6 @@ namespace MediaBrowser.Api
{
Logger.LogInformation("Stopping ffmpeg process with q command for {Path}", job.Path);
- //process.Kill();
process.StandardInput.WriteLine("q");
// Need to wait because killing is asynchronous
@@ -701,7 +700,7 @@ namespace MediaBrowser.Api
{
try
{
- //Logger.LogDebug("Deleting HLS file {0}", file);
+ Logger.LogDebug("Deleting HLS file {0}", file);
_fileSystem.DeleteFile(file);
}
catch (FileNotFoundException)
@@ -840,12 +839,12 @@ namespace MediaBrowser.Api
{
if (KillTimer == null)
{
- //Logger.LogDebug("Starting kill timer at {0}ms. JobId {1} PlaySessionId {2}", intervalMs, Id, PlaySessionId);
+ Logger.LogDebug("Starting kill timer at {0}ms. JobId {1} PlaySessionId {2}", intervalMs, Id, PlaySessionId);
KillTimer = new Timer(new TimerCallback(callback), this, intervalMs, Timeout.Infinite);
}
else
{
- //Logger.LogDebug("Changing kill timer to {0}ms. JobId {1} PlaySessionId {2}", intervalMs, Id, PlaySessionId);
+ Logger.LogDebug("Changing kill timer to {0}ms. JobId {1} PlaySessionId {2}", intervalMs, Id, PlaySessionId);
KillTimer.Change(intervalMs, Timeout.Infinite);
}
}
@@ -864,7 +863,7 @@ namespace MediaBrowser.Api
{
var intervalMs = PingTimeout;
- //Logger.LogDebug("Changing kill timer to {0}ms. JobId {1} PlaySessionId {2}", intervalMs, Id, PlaySessionId);
+ Logger.LogDebug("Changing kill timer to {0}ms. JobId {1} PlaySessionId {2}", intervalMs, Id, PlaySessionId);
KillTimer.Change(intervalMs, Timeout.Infinite);
}
}
diff --git a/MediaBrowser.Api/Devices/DeviceService.cs b/MediaBrowser.Api/Devices/DeviceService.cs
index dc211af6b..697a84f5c 100644
--- a/MediaBrowser.Api/Devices/DeviceService.cs
+++ b/MediaBrowser.Api/Devices/DeviceService.cs
@@ -133,12 +133,15 @@ namespace MediaBrowser.Api.Devices
var album = Request.QueryString["Album"];
var id = Request.QueryString["Id"];
var name = Request.QueryString["Name"];
+ var req = Request.Response.HttpContext.Request;
- if (Request.ContentType.IndexOf("multi", StringComparison.OrdinalIgnoreCase) == -1)
+ if (req.HasFormContentType)
{
- return _deviceManager.AcceptCameraUpload(deviceId, request.RequestStream, new LocalFileInfo
+ var file = req.Form.Files.Count == 0 ? null : req.Form.Files[0];
+
+ return _deviceManager.AcceptCameraUpload(deviceId, file.OpenReadStream(), new LocalFileInfo
{
- MimeType = Request.ContentType,
+ MimeType = file.ContentType,
Album = album,
Name = name,
Id = id
@@ -146,11 +149,9 @@ namespace MediaBrowser.Api.Devices
}
else
{
- var file = Request.Files.Length == 0 ? null : Request.Files[0];
-
- return _deviceManager.AcceptCameraUpload(deviceId, file.InputStream, new LocalFileInfo
+ return _deviceManager.AcceptCameraUpload(deviceId, request.RequestStream, new LocalFileInfo
{
- MimeType = file.ContentType,
+ MimeType = Request.ContentType,
Album = album,
Name = name,
Id = id
diff --git a/MediaBrowser.Api/Images/ImageService.cs b/MediaBrowser.Api/Images/ImageService.cs
index 10bbc9e5d..6d3037b24 100644
--- a/MediaBrowser.Api/Images/ImageService.cs
+++ b/MediaBrowser.Api/Images/ImageService.cs
@@ -1,5 +1,6 @@
using System;
using System.Collections.Generic;
+using System.Globalization;
using System.IO;
using System.Linq;
using System.Threading;
@@ -537,7 +538,7 @@ namespace MediaBrowser.Api.Images
if (item == null)
{
- throw new ResourceNotFoundException(string.Format("Item {0} not found.", itemId.ToString("N")));
+ throw new ResourceNotFoundException(string.Format("Item {0} not found.", itemId.ToString("N", CultureInfo.InvariantCulture)));
}
}
@@ -549,14 +550,14 @@ namespace MediaBrowser.Api.Images
}
IImageEnhancer[] supportedImageEnhancers;
- if (_imageProcessor.ImageEnhancers.Length > 0)
+ if (_imageProcessor.ImageEnhancers.Count > 0)
{
if (item == null)
{
item = _libraryManager.GetItemById(itemId);
}
- supportedImageEnhancers = request.EnableImageEnhancers ? _imageProcessor.GetSupportedEnhancers(item, request.Type) : Array.Empty<IImageEnhancer>();
+ supportedImageEnhancers = request.EnableImageEnhancers ? _imageProcessor.GetSupportedEnhancers(item, request.Type).ToArray() : Array.Empty<IImageEnhancer>();
}
else
{
@@ -605,8 +606,8 @@ namespace MediaBrowser.Api.Images
ImageRequest request,
ItemImageInfo image,
bool cropwhitespace,
- ImageFormat[] supportedFormats,
- IImageEnhancer[] enhancers,
+ IReadOnlyCollection<ImageFormat> supportedFormats,
+ IReadOnlyCollection<IImageEnhancer> enhancers,
TimeSpan? cacheDuration,
IDictionary<string, string> headers,
bool isHeadRequest)
diff --git a/MediaBrowser.Api/ItemUpdateService.cs b/MediaBrowser.Api/ItemUpdateService.cs
index 825732888..d6514d62e 100644
--- a/MediaBrowser.Api/ItemUpdateService.cs
+++ b/MediaBrowser.Api/ItemUpdateService.cs
@@ -69,8 +69,8 @@ namespace MediaBrowser.Api
{
ParentalRatingOptions = _localizationManager.GetParentalRatings().ToArray(),
ExternalIdInfos = _providerManager.GetExternalIdInfos(item).ToArray(),
- Countries = await _localizationManager.GetCountries(),
- Cultures = _localizationManager.GetCultures()
+ Countries = _localizationManager.GetCountries().ToArray(),
+ Cultures = _localizationManager.GetCultures().ToArray()
};
if (!item.IsVirtualItem && !(item is ICollectionFolder) && !(item is UserView) && !(item is AggregateFolder) && !(item is LiveTvChannel) && !(item is IItemByName) &&
diff --git a/MediaBrowser.Api/Library/LibraryService.cs b/MediaBrowser.Api/Library/LibraryService.cs
index 9f8da9c16..cee96f7ab 100644
--- a/MediaBrowser.Api/Library/LibraryService.cs
+++ b/MediaBrowser.Api/Library/LibraryService.cs
@@ -490,18 +490,6 @@ namespace MediaBrowser.Api.Library
{
return false;
}
- else if (string.Equals(name, "FanArt", StringComparison.OrdinalIgnoreCase))
- {
- if (string.Equals(type, "Season", StringComparison.OrdinalIgnoreCase))
- {
- return false;
- }
- if (string.Equals(type, "MusicVideo", StringComparison.OrdinalIgnoreCase))
- {
- return false;
- }
- return true;
- }
else if (string.Equals(name, "TheAudioDB", StringComparison.OrdinalIgnoreCase))
{
return true;
@@ -999,19 +987,16 @@ namespace MediaBrowser.Api.Library
/// Posts the specified request.
/// </summary>
/// <param name="request">The request.</param>
- public void Post(RefreshLibrary request)
+ public async Task Post(RefreshLibrary request)
{
- Task.Run(() =>
+ try
{
- try
- {
- _libraryManager.ValidateMediaLibrary(new SimpleProgress<double>(), CancellationToken.None);
- }
- catch (Exception ex)
- {
- Logger.LogError(ex, "Error refreshing library");
- }
- });
+ await _libraryManager.ValidateMediaLibrary(new SimpleProgress<double>(), CancellationToken.None).ConfigureAwait(false);
+ }
+ catch (Exception ex)
+ {
+ Logger.LogError(ex, "Error refreshing library");
+ }
}
/// <summary>
diff --git a/MediaBrowser.Api/Library/LibraryStructureService.cs b/MediaBrowser.Api/Library/LibraryStructureService.cs
index d6bcf7878..7266bf9f9 100644
--- a/MediaBrowser.Api/Library/LibraryStructureService.cs
+++ b/MediaBrowser.Api/Library/LibraryStructureService.cs
@@ -1,5 +1,6 @@
using System;
using System.Collections.Generic;
+using System.Globalization;
using System.IO;
using System.Linq;
using System.Threading;
@@ -272,7 +273,7 @@ namespace MediaBrowser.Api.Library
// Changing capitalization. Handle windows case insensitivity
if (string.Equals(currentPath, newPath, StringComparison.OrdinalIgnoreCase))
{
- var tempPath = Path.Combine(rootFolderPath, Guid.NewGuid().ToString("N"));
+ var tempPath = Path.Combine(rootFolderPath, Guid.NewGuid().ToString("N", CultureInfo.InvariantCulture));
Directory.Move(currentPath, tempPath);
currentPath = tempPath;
}
diff --git a/MediaBrowser.Api/LiveTv/LiveTvService.cs b/MediaBrowser.Api/LiveTv/LiveTvService.cs
index e41ad540a..8a4d6e216 100644
--- a/MediaBrowser.Api/LiveTv/LiveTvService.cs
+++ b/MediaBrowser.Api/LiveTv/LiveTvService.cs
@@ -599,7 +599,6 @@ namespace MediaBrowser.Api.LiveTv
{
public bool ValidateLogin { get; set; }
public bool ValidateListings { get; set; }
- public string Pw { get; set; }
}
[Route("/LiveTv/ListingProviders", "DELETE", Summary = "Deletes a listing provider")]
@@ -867,28 +866,10 @@ namespace MediaBrowser.Api.LiveTv
public async Task<object> Post(AddListingProvider request)
{
- if (request.Pw != null)
- {
- request.Password = GetHashedString(request.Pw);
- }
-
- request.Pw = null;
-
var result = await _liveTvManager.SaveListingProvider(request, request.ValidateLogin, request.ValidateListings).ConfigureAwait(false);
return ToOptimizedResult(result);
}
- /// <summary>
- /// Gets the hashed string.
- /// </summary>
- private string GetHashedString(string str)
- {
- // legacy
- return BitConverter.ToString(
- _cryptographyProvider.ComputeSHA1(Encoding.UTF8.GetBytes(str)))
- .Replace("-", string.Empty).ToLowerInvariant();
- }
-
public void Delete(DeleteListingProvider request)
{
_liveTvManager.DeleteListingsProvider(request.Id);
diff --git a/MediaBrowser.Api/LocalizationService.cs b/MediaBrowser.Api/LocalizationService.cs
index eeff67e13..3b2e18852 100644
--- a/MediaBrowser.Api/LocalizationService.cs
+++ b/MediaBrowser.Api/LocalizationService.cs
@@ -1,4 +1,3 @@
-using System.Threading.Tasks;
using MediaBrowser.Controller.Net;
using MediaBrowser.Model.Entities;
using MediaBrowser.Model.Globalization;
@@ -82,9 +81,9 @@ namespace MediaBrowser.Api
/// </summary>
/// <param name="request">The request.</param>
/// <returns>System.Object.</returns>
- public async Task<object> Get(GetCountries request)
+ public object Get(GetCountries request)
{
- var result = await _localization.GetCountries();
+ var result = _localization.GetCountries();
return ToOptimizedResult(result);
}
diff --git a/MediaBrowser.Api/MediaBrowser.Api.csproj b/MediaBrowser.Api/MediaBrowser.Api.csproj
index ba29c656b..f653270a6 100644
--- a/MediaBrowser.Api/MediaBrowser.Api.csproj
+++ b/MediaBrowser.Api/MediaBrowser.Api.csproj
@@ -12,6 +12,7 @@
<PropertyGroup>
<TargetFramework>netstandard2.0</TargetFramework>
<GenerateAssemblyInfo>false</GenerateAssemblyInfo>
+ <GenerateDocumentationFile>true</GenerateDocumentationFile>
</PropertyGroup>
</Project>
diff --git a/MediaBrowser.Api/Movies/MoviesService.cs b/MediaBrowser.Api/Movies/MoviesService.cs
index 91766255f..d601fb500 100644
--- a/MediaBrowser.Api/Movies/MoviesService.cs
+++ b/MediaBrowser.Api/Movies/MoviesService.cs
@@ -1,5 +1,6 @@
using System;
using System.Collections.Generic;
+using System.Globalization;
using System.Linq;
using MediaBrowser.Common.Extensions;
using MediaBrowser.Controller.Configuration;
@@ -11,7 +12,6 @@ using MediaBrowser.Controller.LiveTv;
using MediaBrowser.Controller.Net;
using MediaBrowser.Model.Dto;
using MediaBrowser.Model.Entities;
-using MediaBrowser.Model.Extensions;
using MediaBrowser.Model.Querying;
using MediaBrowser.Model.Services;
@@ -268,7 +268,7 @@ namespace MediaBrowser.Api.Movies
EnableGroupByMetadataKey = true,
DtoOptions = dtoOptions
- }).GroupBy(i => i.GetProviderId(MetadataProviders.Imdb) ?? Guid.NewGuid().ToString("N"))
+ }).GroupBy(i => i.GetProviderId(MetadataProviders.Imdb) ?? Guid.NewGuid().ToString("N", CultureInfo.InvariantCulture))
.Select(x => x.First())
.Take(itemLimit)
.ToList();
@@ -309,7 +309,7 @@ namespace MediaBrowser.Api.Movies
EnableGroupByMetadataKey = true,
DtoOptions = dtoOptions
- }).GroupBy(i => i.GetProviderId(MetadataProviders.Imdb) ?? Guid.NewGuid().ToString("N"))
+ }).GroupBy(i => i.GetProviderId(MetadataProviders.Imdb) ?? Guid.NewGuid().ToString("N", CultureInfo.InvariantCulture))
.Select(x => x.First())
.Take(itemLimit)
.ToList();
diff --git a/MediaBrowser.Api/PackageService.cs b/MediaBrowser.Api/PackageService.cs
index fbb876dea..baa6f7bb9 100644
--- a/MediaBrowser.Api/PackageService.cs
+++ b/MediaBrowser.Api/PackageService.cs
@@ -197,7 +197,7 @@ namespace MediaBrowser.Api
throw new ResourceNotFoundException(string.Format("Package not found: {0}", request.Name));
}
- await _installationManager.InstallPackage(package, true, new SimpleProgress<double>(), CancellationToken.None);
+ await _installationManager.InstallPackage(package);
}
/// <summary>
@@ -206,13 +206,7 @@ namespace MediaBrowser.Api
/// <param name="request">The request.</param>
public void Delete(CancelPackageInstallation request)
{
- var info = _installationManager.CurrentInstallations.FirstOrDefault(i => i.Item1.Id.Equals(request.Id));
-
- if (info != null)
- {
- info.Item2.Cancel();
- }
+ _installationManager.CancelInstallation(new Guid(request.Id));
}
}
-
}
diff --git a/MediaBrowser.Api/Playback/BaseStreamingService.cs b/MediaBrowser.Api/Playback/BaseStreamingService.cs
index 4865f3088..1054badd9 100644
--- a/MediaBrowser.Api/Playback/BaseStreamingService.cs
+++ b/MediaBrowser.Api/Playback/BaseStreamingService.cs
@@ -8,7 +8,6 @@ using System.Text;
using System.Threading;
using System.Threading.Tasks;
using MediaBrowser.Common.Extensions;
-using MediaBrowser.Controller;
using MediaBrowser.Controller.Configuration;
using MediaBrowser.Controller.Devices;
using MediaBrowser.Controller.Dlna;
@@ -16,7 +15,6 @@ using MediaBrowser.Controller.Library;
using MediaBrowser.Controller.MediaEncoding;
using MediaBrowser.Controller.Net;
using MediaBrowser.Model.Configuration;
-using MediaBrowser.Model.Diagnostics;
using MediaBrowser.Model.Dlna;
using MediaBrowser.Model.Dto;
using MediaBrowser.Model.Entities;
@@ -32,6 +30,8 @@ namespace MediaBrowser.Api.Playback
/// </summary>
public abstract class BaseStreamingService : BaseApiService
{
+ protected virtual bool EnableOutputInSubFolder => false;
+
/// <summary>
/// Gets or sets the application paths.
/// </summary>
@@ -65,9 +65,13 @@ namespace MediaBrowser.Api.Playback
protected IFileSystem FileSystem { get; private set; }
protected IDlnaManager DlnaManager { get; private set; }
+
protected IDeviceManager DeviceManager { get; private set; }
+
protected ISubtitleEncoder SubtitleEncoder { get; private set; }
+
protected IMediaSourceManager MediaSourceManager { get; private set; }
+
protected IJsonSerializer JsonSerializer { get; private set; }
protected IAuthorizationContext AuthorizationContext { get; private set; }
@@ -75,6 +79,12 @@ namespace MediaBrowser.Api.Playback
protected EncodingHelper EncodingHelper { get; set; }
/// <summary>
+ /// Gets the type of the transcoding job.
+ /// </summary>
+ /// <value>The type of the transcoding job.</value>
+ protected abstract TranscodingJobType TranscodingJobType { get; }
+
+ /// <summary>
/// Initializes a new instance of the <see cref="BaseStreamingService" /> class.
/// </summary>
protected BaseStreamingService(
@@ -113,12 +123,6 @@ namespace MediaBrowser.Api.Playback
protected abstract string GetCommandLineArguments(string outputPath, EncodingOptions encodingOptions, StreamState state, bool isEncoding);
/// <summary>
- /// Gets the type of the transcoding job.
- /// </summary>
- /// <value>The type of the transcoding job.</value>
- protected abstract TranscodingJobType TranscodingJobType { get; }
-
- /// <summary>
/// Gets the output file extension.
/// </summary>
/// <param name="state">The state.</param>
@@ -133,25 +137,23 @@ namespace MediaBrowser.Api.Playback
/// </summary>
private string GetOutputFilePath(StreamState state, EncodingOptions encodingOptions, string outputFileExtension)
{
- var folder = ServerConfigurationManager.ApplicationPaths.TranscodingTempPath;
-
var data = GetCommandLineArguments("dummy\\dummy", encodingOptions, state, false);
- data += "-" + (state.Request.DeviceId ?? string.Empty);
- data += "-" + (state.Request.PlaySessionId ?? string.Empty);
+ data += "-" + (state.Request.DeviceId ?? string.Empty)
+ + "-" + (state.Request.PlaySessionId ?? string.Empty);
- var dataHash = data.GetMD5().ToString("N");
+ var filename = data.GetMD5().ToString("N", CultureInfo.InvariantCulture);
+ var ext = outputFileExtension.ToLowerInvariant();
+ var folder = ServerConfigurationManager.ApplicationPaths.TranscodingTempPath;
if (EnableOutputInSubFolder)
{
- return Path.Combine(folder, dataHash, dataHash + (outputFileExtension ?? string.Empty).ToLowerInvariant());
+ return Path.Combine(folder, filename, filename + ext);
}
- return Path.Combine(folder, dataHash + (outputFileExtension ?? string.Empty).ToLowerInvariant());
+ return Path.Combine(folder, filename + ext);
}
- protected virtual bool EnableOutputInSubFolder => false;
-
protected readonly CultureInfo UsCulture = new CultureInfo("en-US");
protected virtual string GetDefaultEncoderPreset()
@@ -171,7 +173,6 @@ namespace MediaBrowser.Api.Playback
var liveStreamResponse = await MediaSourceManager.OpenLiveStream(new LiveStreamRequest
{
OpenToken = state.MediaSource.OpenToken
-
}, cancellationTokenSource.Token).ConfigureAwait(false);
EncodingHelper.AttachMediaSourceInfo(state, liveStreamResponse.MediaSource, state.RequestedUrl);
@@ -209,22 +210,16 @@ namespace MediaBrowser.Api.Playback
if (state.VideoRequest != null && !string.Equals(state.OutputVideoCodec, "copy", StringComparison.OrdinalIgnoreCase))
{
var auth = AuthorizationContext.GetAuthorizationInfo(Request);
- if (auth.User != null)
+ if (auth.User != null && !auth.User.Policy.EnableVideoPlaybackTranscoding)
{
- if (!auth.User.Policy.EnableVideoPlaybackTranscoding)
- {
- ApiEntryPoint.Instance.OnTranscodeFailedToStart(outputPath, TranscodingJobType, state);
+ ApiEntryPoint.Instance.OnTranscodeFailedToStart(outputPath, TranscodingJobType, state);
- throw new ArgumentException("User does not have access to video transcoding");
- }
+ throw new ArgumentException("User does not have access to video transcoding");
}
}
var encodingOptions = ApiEntryPoint.Instance.GetEncodingOptions();
- var transcodingId = Guid.NewGuid().ToString("N");
- var commandLineArgs = GetCommandLineArguments(outputPath, encodingOptions, state, true);
-
var process = new Process()
{
StartInfo = new ProcessStartInfo()
@@ -239,7 +234,7 @@ namespace MediaBrowser.Api.Playback
RedirectStandardInput = true,
FileName = MediaEncoder.EncoderPath,
- Arguments = commandLineArgs,
+ Arguments = GetCommandLineArguments(outputPath, encodingOptions, state, true),
WorkingDirectory = string.IsNullOrWhiteSpace(workingDirectory) ? null : workingDirectory,
ErrorDialog = false
@@ -250,7 +245,7 @@ namespace MediaBrowser.Api.Playback
var transcodingJob = ApiEntryPoint.Instance.OnTranscodeBeginning(outputPath,
state.Request.PlaySessionId,
state.MediaSource.LiveStreamId,
- transcodingId,
+ Guid.NewGuid().ToString("N", CultureInfo.InvariantCulture),
TranscodingJobType,
process,
state.Request.DeviceId,
@@ -261,27 +256,26 @@ namespace MediaBrowser.Api.Playback
Logger.LogInformation(commandLineLogMessage);
var logFilePrefix = "ffmpeg-transcode";
- if (state.VideoRequest != null)
+ if (state.VideoRequest != null
+ && string.Equals(state.OutputVideoCodec, "copy", StringComparison.OrdinalIgnoreCase))
{
- if (string.Equals(state.OutputVideoCodec, "copy", StringComparison.OrdinalIgnoreCase)
- && string.Equals(state.OutputAudioCodec, "copy", StringComparison.OrdinalIgnoreCase))
+ if (string.Equals(state.OutputAudioCodec, "copy", StringComparison.OrdinalIgnoreCase))
{
logFilePrefix = "ffmpeg-directstream";
}
- else if (string.Equals(state.OutputVideoCodec, "copy", StringComparison.OrdinalIgnoreCase))
+ else
{
logFilePrefix = "ffmpeg-remux";
}
}
var logFilePath = Path.Combine(ServerConfigurationManager.ApplicationPaths.LogDirectoryPath, logFilePrefix + "-" + Guid.NewGuid() + ".txt");
- Directory.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, FileOpenMode.Create, FileAccessMode.Write, FileShareMode.Read, true);
+ Stream logStream = FileSystem.GetFileStream(logFilePath, FileOpenMode.Create, FileAccessMode.Write, FileShareMode.Read, true);
var commandLineLogMessageBytes = Encoding.UTF8.GetBytes(Request.AbsoluteUri + Environment.NewLine + Environment.NewLine + JsonSerializer.SerializeToString(state.MediaSource) + Environment.NewLine + Environment.NewLine + commandLineLogMessage + Environment.NewLine + Environment.NewLine);
- await state.LogFileStream.WriteAsync(commandLineLogMessageBytes, 0, commandLineLogMessageBytes.Length, cancellationTokenSource.Token).ConfigureAwait(false);
+ await logStream.WriteAsync(commandLineLogMessageBytes, 0, commandLineLogMessageBytes.Length, cancellationTokenSource.Token).ConfigureAwait(false);
process.Exited += (sender, args) => OnFfMpegProcessExited(process, transcodingJob, state);
@@ -298,13 +292,10 @@ namespace MediaBrowser.Api.Playback
throw;
}
- // MUST read both stdout and stderr asynchronously or a deadlock may occurr
- //process.BeginOutputReadLine();
-
state.TranscodingJob = transcodingJob;
// Important - don't await the log task or we won't be able to kill ffmpeg when the user stops playback
- new JobLogger(Logger).StartStreamingLog(state, process.StandardError.BaseStream, state.LogFileStream);
+ _ = new JobLogger(Logger).StartStreamingLog(state, process.StandardError.BaseStream, logStream);
// Wait for the file to exist before proceeeding
while (!File.Exists(state.WaitForPath ?? outputPath) && !transcodingJob.HasExited)
@@ -368,25 +359,16 @@ namespace MediaBrowser.Api.Playback
Logger.LogDebug("Disposing stream resources");
state.Dispose();
- try
+ if (process.ExitCode == 0)
{
- Logger.LogInformation("FFMpeg exited with code {0}", process.ExitCode);
+ Logger.LogInformation("FFMpeg exited with code 0");
}
- catch
+ else
{
- Logger.LogError("FFMpeg exited with an error.");
+ Logger.LogError("FFMpeg exited with code {0}", process.ExitCode);
}
- // This causes on exited to be called twice:
- //try
- //{
- // // Dispose the process
- // process.Dispose();
- //}
- //catch (Exception ex)
- //{
- // Logger.LogError(ex, "Error disposing ffmpeg.");
- //}
+ process.Dispose();
}
/// <summary>
@@ -439,55 +421,55 @@ namespace MediaBrowser.Api.Playback
{
if (videoRequest != null)
{
- videoRequest.AudioStreamIndex = int.Parse(val, UsCulture);
+ videoRequest.AudioStreamIndex = int.Parse(val, CultureInfo.InvariantCulture);
}
}
else if (i == 7)
{
if (videoRequest != null)
{
- videoRequest.SubtitleStreamIndex = int.Parse(val, UsCulture);
+ videoRequest.SubtitleStreamIndex = int.Parse(val, CultureInfo.InvariantCulture);
}
}
else if (i == 8)
{
if (videoRequest != null)
{
- videoRequest.VideoBitRate = int.Parse(val, UsCulture);
+ videoRequest.VideoBitRate = int.Parse(val, CultureInfo.InvariantCulture);
}
}
else if (i == 9)
{
- request.AudioBitRate = int.Parse(val, UsCulture);
+ request.AudioBitRate = int.Parse(val, CultureInfo.InvariantCulture);
}
else if (i == 10)
{
- request.MaxAudioChannels = int.Parse(val, UsCulture);
+ request.MaxAudioChannels = int.Parse(val, CultureInfo.InvariantCulture);
}
else if (i == 11)
{
if (videoRequest != null)
{
- videoRequest.MaxFramerate = float.Parse(val, UsCulture);
+ videoRequest.MaxFramerate = float.Parse(val, CultureInfo.InvariantCulture);
}
}
else if (i == 12)
{
if (videoRequest != null)
{
- videoRequest.MaxWidth = int.Parse(val, UsCulture);
+ videoRequest.MaxWidth = int.Parse(val, CultureInfo.InvariantCulture);
}
}
else if (i == 13)
{
if (videoRequest != null)
{
- videoRequest.MaxHeight = int.Parse(val, UsCulture);
+ videoRequest.MaxHeight = int.Parse(val, CultureInfo.InvariantCulture);
}
}
else if (i == 14)
{
- request.StartTimeTicks = long.Parse(val, UsCulture);
+ request.StartTimeTicks = long.Parse(val, CultureInfo.InvariantCulture);
}
else if (i == 15)
{
@@ -500,14 +482,14 @@ namespace MediaBrowser.Api.Playback
{
if (videoRequest != null)
{
- videoRequest.MaxRefFrames = int.Parse(val, UsCulture);
+ videoRequest.MaxRefFrames = int.Parse(val, CultureInfo.InvariantCulture);
}
}
else if (i == 17)
{
if (videoRequest != null)
{
- videoRequest.MaxVideoBitDepth = int.Parse(val, UsCulture);
+ videoRequest.MaxVideoBitDepth = int.Parse(val, CultureInfo.InvariantCulture);
}
}
else if (i == 18)
@@ -556,7 +538,7 @@ namespace MediaBrowser.Api.Playback
}
else if (i == 26)
{
- request.TranscodingMaxAudioChannels = int.Parse(val, UsCulture);
+ request.TranscodingMaxAudioChannels = int.Parse(val, CultureInfo.InvariantCulture);
}
else if (i == 27)
{
@@ -643,16 +625,25 @@ namespace MediaBrowser.Api.Playback
return null;
}
- if (value.IndexOf("npt=", StringComparison.OrdinalIgnoreCase) != 0)
+ const string Npt = "npt=";
+ if (!value.StartsWith(Npt, StringComparison.OrdinalIgnoreCase))
{
throw new ArgumentException("Invalid timeseek header");
}
- value = value.Substring(4).Split(new[] { '-' }, 2)[0];
+ int index = value.IndexOf('-');
+ if (index == -1)
+ {
+ value = value.Substring(Npt.Length);
+ }
+ else
+ {
+ value = value.Substring(Npt.Length, index);
+ }
if (value.IndexOf(':') == -1)
{
// Parses npt times in the format of '417.33'
- if (double.TryParse(value, NumberStyles.Any, UsCulture, out var seconds))
+ if (double.TryParse(value, NumberStyles.Any, CultureInfo.InvariantCulture, out var seconds))
{
return TimeSpan.FromSeconds(seconds).Ticks;
}
@@ -667,7 +658,7 @@ namespace MediaBrowser.Api.Playback
foreach (var time in tokens)
{
- if (double.TryParse(time, NumberStyles.Any, UsCulture, out var digit))
+ if (double.TryParse(time, NumberStyles.Any, CultureInfo.InvariantCulture, out var digit))
{
secondsSum += digit * timeFactor;
}
@@ -704,10 +695,10 @@ namespace MediaBrowser.Api.Playback
request.AudioCodec = EncodingHelper.InferAudioCodec(url);
}
- var enableDlnaHeaders = !string.IsNullOrWhiteSpace(request.Params) /*||
- string.Equals(Request.Headers.Get("GetContentFeatures.DLNA.ORG"), "1", StringComparison.OrdinalIgnoreCase)*/;
+ var enableDlnaHeaders = !string.IsNullOrWhiteSpace(request.Params) ||
+ string.Equals(GetHeader("GetContentFeatures.DLNA.ORG"), "1", StringComparison.OrdinalIgnoreCase);
- var state = new StreamState(MediaSourceManager, Logger, TranscodingJobType)
+ var state = new StreamState(MediaSourceManager, TranscodingJobType)
{
Request = request,
RequestedUrl = url,
@@ -728,13 +719,10 @@ namespace MediaBrowser.Api.Playback
// state.SegmentLength = 6;
//}
- if (state.VideoRequest != null)
+ if (state.VideoRequest != null && !string.IsNullOrWhiteSpace(state.VideoRequest.VideoCodec))
{
- if (!string.IsNullOrWhiteSpace(state.VideoRequest.VideoCodec))
- {
- state.SupportedVideoCodecs = state.VideoRequest.VideoCodec.Split(',').Where(i => !string.IsNullOrWhiteSpace(i)).ToArray();
- state.VideoRequest.VideoCodec = state.SupportedVideoCodecs.FirstOrDefault();
- }
+ state.SupportedVideoCodecs = state.VideoRequest.VideoCodec.Split(',').Where(i => !string.IsNullOrWhiteSpace(i)).ToArray();
+ state.VideoRequest.VideoCodec = state.SupportedVideoCodecs.FirstOrDefault();
}
if (!string.IsNullOrWhiteSpace(request.AudioCodec))
@@ -779,12 +767,12 @@ namespace MediaBrowser.Api.Playback
var mediaSources = (await MediaSourceManager.GetPlayackMediaSources(LibraryManager.GetItemById(request.Id), null, false, false, cancellationToken).ConfigureAwait(false)).ToList();
mediaSource = string.IsNullOrEmpty(request.MediaSourceId)
- ? mediaSources.First()
- : mediaSources.FirstOrDefault(i => string.Equals(i.Id, request.MediaSourceId));
+ ? mediaSources[0]
+ : mediaSources.Find(i => string.Equals(i.Id, request.MediaSourceId));
if (mediaSource == null && request.MediaSourceId.Equals(request.Id))
{
- mediaSource = mediaSources.First();
+ mediaSource = mediaSources[0];
}
}
}
@@ -834,11 +822,11 @@ namespace MediaBrowser.Api.Playback
if (state.OutputVideoBitrate.HasValue && !string.Equals(state.OutputVideoCodec, "copy", StringComparison.OrdinalIgnoreCase))
{
var resolution = ResolutionNormalizer.Normalize(
- state.VideoStream == null ? (int?)null : state.VideoStream.BitRate,
- state.VideoStream == null ? (int?)null : state.VideoStream.Width,
- state.VideoStream == null ? (int?)null : state.VideoStream.Height,
+ state.VideoStream?.BitRate,
+ state.VideoStream?.Width,
+ state.VideoStream?.Height,
state.OutputVideoBitrate.Value,
- state.VideoStream == null ? null : state.VideoStream.Codec,
+ state.VideoStream?.Codec,
state.OutputVideoCodec,
videoRequest.MaxWidth,
videoRequest.MaxHeight);
@@ -846,17 +834,13 @@ namespace MediaBrowser.Api.Playback
videoRequest.MaxWidth = resolution.MaxWidth;
videoRequest.MaxHeight = resolution.MaxHeight;
}
-
- ApplyDeviceProfileSettings(state);
- }
- else
- {
- ApplyDeviceProfileSettings(state);
}
+ ApplyDeviceProfileSettings(state);
+
var ext = string.IsNullOrWhiteSpace(state.OutputContainer)
? GetOutputFileExtension(state)
- : ("." + state.OutputContainer);
+ : ('.' + state.OutputContainer);
var encodingOptions = ApiEntryPoint.Instance.GetEncodingOptions();
@@ -970,18 +954,18 @@ namespace MediaBrowser.Api.Playback
responseHeaders["transferMode.dlna.org"] = string.IsNullOrEmpty(transferMode) ? "Streaming" : transferMode;
responseHeaders["realTimeInfo.dlna.org"] = "DLNA.ORG_TLAG=*";
- if (string.Equals(GetHeader("getMediaInfo.sec"), "1", StringComparison.OrdinalIgnoreCase))
+ if (state.RunTimeTicks.HasValue)
{
- if (state.RunTimeTicks.HasValue)
+ if (string.Equals(GetHeader("getMediaInfo.sec"), "1", StringComparison.OrdinalIgnoreCase))
{
var ms = TimeSpan.FromTicks(state.RunTimeTicks.Value).TotalMilliseconds;
responseHeaders["MediaInfo.sec"] = string.Format("SEC_Duration={0};", Convert.ToInt32(ms).ToString(CultureInfo.InvariantCulture));
}
- }
- if (state.RunTimeTicks.HasValue && !isStaticallyStreamed && profile != null)
- {
- AddTimeSeekResponseHeaders(state, responseHeaders);
+ if (!isStaticallyStreamed && profile != null)
+ {
+ AddTimeSeekResponseHeaders(state, responseHeaders);
+ }
}
if (profile == null)
@@ -1037,17 +1021,12 @@ namespace MediaBrowser.Api.Playback
).FirstOrDefault() ?? string.Empty;
}
-
- foreach (var item in responseHeaders)
- {
- Request.Response.AddHeader(item.Key, item.Value);
- }
}
private void AddTimeSeekResponseHeaders(StreamState state, IDictionary<string, string> responseHeaders)
{
- var runtimeSeconds = TimeSpan.FromTicks(state.RunTimeTicks.Value).TotalSeconds.ToString(UsCulture);
- var startSeconds = TimeSpan.FromTicks(state.Request.StartTimeTicks ?? 0).TotalSeconds.ToString(UsCulture);
+ var runtimeSeconds = TimeSpan.FromTicks(state.RunTimeTicks.Value).TotalSeconds.ToString(CultureInfo.InvariantCulture);
+ var startSeconds = TimeSpan.FromTicks(state.Request.StartTimeTicks ?? 0).TotalSeconds.ToString(CultureInfo.InvariantCulture);
responseHeaders["TimeSeekRange.dlna.org"] = string.Format("npt={0}-{1}/{1}", startSeconds, runtimeSeconds);
responseHeaders["X-AvailableSeekRange"] = string.Format("1 npt={0}-{1}", startSeconds, runtimeSeconds);
diff --git a/MediaBrowser.Api/Playback/Hls/BaseHlsService.cs b/MediaBrowser.Api/Playback/Hls/BaseHlsService.cs
index 836e47dad..27eb67ee6 100644
--- a/MediaBrowser.Api/Playback/Hls/BaseHlsService.cs
+++ b/MediaBrowser.Api/Playback/Hls/BaseHlsService.cs
@@ -1,5 +1,6 @@
using System;
using System.Collections.Generic;
+using System.Globalization;
using System.IO;
using System.Text;
using System.Threading;
@@ -143,10 +144,10 @@ namespace MediaBrowser.Api.Playback.Hls
text = text.Replace("#EXTM3U", "#EXTM3U\n#EXT-X-PLAYLIST-TYPE:EVENT");
- var newDuration = "#EXT-X-TARGETDURATION:" + segmentLength.ToString(UsCulture);
+ var newDuration = "#EXT-X-TARGETDURATION:" + segmentLength.ToString(CultureInfo.InvariantCulture);
- text = text.Replace("#EXT-X-TARGETDURATION:" + (segmentLength - 1).ToString(UsCulture), newDuration, StringComparison.OrdinalIgnoreCase);
- //text = text.Replace("#EXT-X-TARGETDURATION:" + (segmentLength + 1).ToString(UsCulture), newDuration, StringComparison.OrdinalIgnoreCase);
+ text = text.Replace("#EXT-X-TARGETDURATION:" + (segmentLength - 1).ToString(CultureInfo.InvariantCulture), newDuration, StringComparison.OrdinalIgnoreCase);
+ //text = text.Replace("#EXT-X-TARGETDURATION:" + (segmentLength + 1).ToString(CultureInfo.InvariantCulture), newDuration, StringComparison.OrdinalIgnoreCase);
return text;
}
@@ -163,7 +164,7 @@ namespace MediaBrowser.Api.Playback.Hls
var paddedBitrate = Convert.ToInt32(bitrate * 1.15);
// Main stream
- builder.AppendLine("#EXT-X-STREAM-INF:PROGRAM-ID=1,BANDWIDTH=" + paddedBitrate.ToString(UsCulture));
+ builder.AppendLine("#EXT-X-STREAM-INF:PROGRAM-ID=1,BANDWIDTH=" + paddedBitrate.ToString(CultureInfo.InvariantCulture));
var playlistUrl = "hls/" + Path.GetFileName(firstPlaylist).Replace(".m3u8", "/stream.m3u8");
builder.AppendLine(playlistUrl);
@@ -231,7 +232,7 @@ namespace MediaBrowser.Api.Playback.Hls
{
var itsOffsetMs = 0;
- var itsOffset = itsOffsetMs == 0 ? string.Empty : string.Format("-itsoffset {0} ", TimeSpan.FromMilliseconds(itsOffsetMs).TotalSeconds.ToString(UsCulture));
+ var itsOffset = itsOffsetMs == 0 ? string.Empty : string.Format("-itsoffset {0} ", TimeSpan.FromMilliseconds(itsOffsetMs).TotalSeconds.ToString(CultureInfo.InvariantCulture));
var videoCodec = EncodingHelper.GetVideoEncoder(state, encodingOptions);
@@ -240,7 +241,7 @@ namespace MediaBrowser.Api.Playback.Hls
var inputModifier = EncodingHelper.GetInputModifier(state, encodingOptions);
// If isEncoding is true we're actually starting ffmpeg
- var startNumberParam = isEncoding ? GetStartNumber(state).ToString(UsCulture) : "0";
+ var startNumberParam = isEncoding ? GetStartNumber(state).ToString(CultureInfo.InvariantCulture) : "0";
var baseUrlParam = string.Empty;
@@ -272,7 +273,7 @@ namespace MediaBrowser.Api.Playback.Hls
EncodingHelper.GetMapArgs(state),
GetVideoArguments(state, encodingOptions),
GetAudioArguments(state, encodingOptions),
- state.SegmentLength.ToString(UsCulture),
+ state.SegmentLength.ToString(CultureInfo.InvariantCulture),
startNumberParam,
outputPath,
outputTsArg,
@@ -293,9 +294,9 @@ namespace MediaBrowser.Api.Playback.Hls
EncodingHelper.GetMapArgs(state),
GetVideoArguments(state, encodingOptions),
GetAudioArguments(state, encodingOptions),
- state.SegmentLength.ToString(UsCulture),
+ state.SegmentLength.ToString(CultureInfo.InvariantCulture),
startNumberParam,
- state.HlsListSize.ToString(UsCulture),
+ state.HlsListSize.ToString(CultureInfo.InvariantCulture),
baseUrlParam,
outputPath
).Trim();
diff --git a/MediaBrowser.Api/Playback/Hls/DynamicHlsService.cs b/MediaBrowser.Api/Playback/Hls/DynamicHlsService.cs
index 1d6cbb822..1f24ae881 100644
--- a/MediaBrowser.Api/Playback/Hls/DynamicHlsService.cs
+++ b/MediaBrowser.Api/Playback/Hls/DynamicHlsService.cs
@@ -177,7 +177,7 @@ namespace MediaBrowser.Api.Playback.Hls
var cancellationTokenSource = new CancellationTokenSource();
var cancellationToken = cancellationTokenSource.Token;
- var requestedIndex = int.Parse(segmentId, NumberStyles.Integer, UsCulture);
+ var requestedIndex = int.Parse(segmentId, NumberStyles.Integer, CultureInfo.InvariantCulture);
var state = await GetState(request, cancellationToken).ConfigureAwait(false);
@@ -364,7 +364,7 @@ namespace MediaBrowser.Api.Playback.Hls
var indexString = Path.GetFileNameWithoutExtension(file.Name).Substring(playlistFilename.Length);
- return int.Parse(indexString, NumberStyles.Integer, UsCulture);
+ return int.Parse(indexString, NumberStyles.Integer, CultureInfo.InvariantCulture);
}
private void DeleteLastFile(string playlistPath, string segmentExtension, int retryCount)
@@ -438,7 +438,7 @@ namespace MediaBrowser.Api.Playback.Hls
segmentId = segmentRequest.SegmentId;
}
- return int.Parse(segmentId, NumberStyles.Integer, UsCulture);
+ return int.Parse(segmentId, NumberStyles.Integer, CultureInfo.InvariantCulture);
}
private string GetSegmentPath(StreamState state, string playlist, int index)
@@ -447,7 +447,7 @@ namespace MediaBrowser.Api.Playback.Hls
var filename = Path.GetFileNameWithoutExtension(playlist);
- return Path.Combine(folder, filename + index.ToString(UsCulture) + GetSegmentFileExtension(state.Request));
+ return Path.Combine(folder, filename + index.ToString(CultureInfo.InvariantCulture) + GetSegmentFileExtension(state.Request));
}
private async Task<object> GetSegmentResult(StreamState state,
@@ -628,8 +628,8 @@ namespace MediaBrowser.Api.Playback.Hls
private string ReplaceBitrate(string url, int oldValue, int newValue)
{
return url.Replace(
- "videobitrate=" + oldValue.ToString(UsCulture),
- "videobitrate=" + newValue.ToString(UsCulture),
+ "videobitrate=" + oldValue.ToString(CultureInfo.InvariantCulture),
+ "videobitrate=" + newValue.ToString(CultureInfo.InvariantCulture),
StringComparison.OrdinalIgnoreCase);
}
@@ -648,8 +648,8 @@ namespace MediaBrowser.Api.Playback.Hls
var url = string.Format("{0}/Subtitles/{1}/subtitles.m3u8?SegmentLength={2}&api_key={3}",
state.Request.MediaSourceId,
- stream.Index.ToString(UsCulture),
- 30.ToString(UsCulture),
+ stream.Index.ToString(CultureInfo.InvariantCulture),
+ 30.ToString(CultureInfo.InvariantCulture),
AuthorizationContext.GetAuthorizationInfo(Request).Token);
var line = string.Format(format,
@@ -705,7 +705,7 @@ namespace MediaBrowser.Api.Playback.Hls
private void AppendPlaylist(StringBuilder builder, StreamState state, string url, int bitrate, string subtitleGroup)
{
- var header = "#EXT-X-STREAM-INF:BANDWIDTH=" + bitrate.ToString(UsCulture) + ",AVERAGE-BANDWIDTH=" + bitrate.ToString(UsCulture);
+ var header = "#EXT-X-STREAM-INF:BANDWIDTH=" + bitrate.ToString(CultureInfo.InvariantCulture) + ",AVERAGE-BANDWIDTH=" + bitrate.ToString(CultureInfo.InvariantCulture);
// tvos wants resolution, codecs, framerate
//if (state.TargetFramerate.HasValue)
@@ -770,7 +770,7 @@ namespace MediaBrowser.Api.Playback.Hls
builder.AppendLine("#EXTM3U");
builder.AppendLine("#EXT-X-PLAYLIST-TYPE:VOD");
builder.AppendLine("#EXT-X-VERSION:3");
- builder.AppendLine("#EXT-X-TARGETDURATION:" + Math.Ceiling(segmentLengths.Length > 0 ? segmentLengths.Max() : state.SegmentLength).ToString(UsCulture));
+ builder.AppendLine("#EXT-X-TARGETDURATION:" + Math.Ceiling(segmentLengths.Length > 0 ? segmentLengths.Max() : state.SegmentLength).ToString(CultureInfo.InvariantCulture));
builder.AppendLine("#EXT-X-MEDIA-SEQUENCE:0");
var queryStringIndex = Request.RawUrl.IndexOf('?');
@@ -785,12 +785,12 @@ namespace MediaBrowser.Api.Playback.Hls
foreach (var length in segmentLengths)
{
- builder.AppendLine("#EXTINF:" + length.ToString("0.0000", UsCulture) + ", nodesc");
+ builder.AppendLine("#EXTINF:" + length.ToString("0.0000", CultureInfo.InvariantCulture) + ", nodesc");
builder.AppendLine(string.Format("hls1/{0}/{1}{2}{3}",
name,
- index.ToString(UsCulture),
+ index.ToString(CultureInfo.InvariantCulture),
GetSegmentFileExtension(request),
queryString));
@@ -821,17 +821,17 @@ namespace MediaBrowser.Api.Playback.Hls
if (state.OutputAudioBitrate.HasValue)
{
- audioTranscodeParams.Add("-ab " + state.OutputAudioBitrate.Value.ToString(UsCulture));
+ audioTranscodeParams.Add("-ab " + state.OutputAudioBitrate.Value.ToString(CultureInfo.InvariantCulture));
}
if (state.OutputAudioChannels.HasValue)
{
- audioTranscodeParams.Add("-ac " + state.OutputAudioChannels.Value.ToString(UsCulture));
+ audioTranscodeParams.Add("-ac " + state.OutputAudioChannels.Value.ToString(CultureInfo.InvariantCulture));
}
if (state.OutputAudioSampleRate.HasValue)
{
- audioTranscodeParams.Add("-ar " + state.OutputAudioSampleRate.Value.ToString(UsCulture));
+ audioTranscodeParams.Add("-ar " + state.OutputAudioSampleRate.Value.ToString(CultureInfo.InvariantCulture));
}
audioTranscodeParams.Add("-vn");
@@ -863,12 +863,12 @@ namespace MediaBrowser.Api.Playback.Hls
if (bitrate.HasValue)
{
- args += " -ab " + bitrate.Value.ToString(UsCulture);
+ args += " -ab " + bitrate.Value.ToString(CultureInfo.InvariantCulture);
}
if (state.OutputAudioSampleRate.HasValue)
{
- args += " -ar " + state.OutputAudioSampleRate.Value.ToString(UsCulture);
+ args += " -ar " + state.OutputAudioSampleRate.Value.ToString(CultureInfo.InvariantCulture);
}
args += " " + EncodingHelper.GetAudioFilterParam(state, encodingOptions, true);
@@ -909,7 +909,7 @@ namespace MediaBrowser.Api.Playback.Hls
else
{
var keyFrameArg = string.Format(" -force_key_frames \"expr:gte(t,n_forced*{0})\"",
- state.SegmentLength.ToString(UsCulture));
+ state.SegmentLength.ToString(CultureInfo.InvariantCulture));
var hasGraphicalSubs = state.SubtitleStream != null && !state.SubtitleStream.IsTextSubtitleStream && state.SubtitleDeliveryMethod == SubtitleDeliveryMethod.Encode;
@@ -957,7 +957,7 @@ namespace MediaBrowser.Api.Playback.Hls
// If isEncoding is true we're actually starting ffmpeg
var startNumber = GetStartNumber(state);
- var startNumberParam = isEncoding ? startNumber.ToString(UsCulture) : "0";
+ var startNumberParam = isEncoding ? startNumber.ToString(CultureInfo.InvariantCulture) : "0";
var mapArgs = state.IsOutputVideo ? EncodingHelper.GetMapArgs(state) : string.Empty;
@@ -988,7 +988,7 @@ namespace MediaBrowser.Api.Playback.Hls
mapArgs,
GetVideoArguments(state, encodingOptions),
GetAudioArguments(state, encodingOptions),
- state.SegmentLength.ToString(UsCulture),
+ state.SegmentLength.ToString(CultureInfo.InvariantCulture),
startNumberParam,
outputPath,
outputTsArg,
diff --git a/MediaBrowser.Api/Playback/Hls/VideoHlsService.cs b/MediaBrowser.Api/Playback/Hls/VideoHlsService.cs
index d441332c7..4a5f4025b 100644
--- a/MediaBrowser.Api/Playback/Hls/VideoHlsService.cs
+++ b/MediaBrowser.Api/Playback/Hls/VideoHlsService.cs
@@ -1,4 +1,5 @@
using System;
+using System.Globalization;
using System.Threading.Tasks;
using MediaBrowser.Controller.Configuration;
using MediaBrowser.Controller.Devices;
@@ -55,12 +56,12 @@ namespace MediaBrowser.Api.Playback.Hls
if (bitrate.HasValue)
{
- args += " -ab " + bitrate.Value.ToString(UsCulture);
+ args += " -ab " + bitrate.Value.ToString(CultureInfo.InvariantCulture);
}
if (state.OutputAudioSampleRate.HasValue)
{
- args += " -ar " + state.OutputAudioSampleRate.Value.ToString(UsCulture);
+ args += " -ar " + state.OutputAudioSampleRate.Value.ToString(CultureInfo.InvariantCulture);
}
args += " " + EncodingHelper.GetAudioFilterParam(state, encodingOptions, true);
@@ -104,7 +105,7 @@ namespace MediaBrowser.Api.Playback.Hls
else
{
var keyFrameArg = string.Format(" -force_key_frames \"expr:gte(t,n_forced*{0})\"",
- state.SegmentLength.ToString(UsCulture));
+ state.SegmentLength.ToString(CultureInfo.InvariantCulture));
var hasGraphicalSubs = state.SubtitleStream != null && !state.SubtitleStream.IsTextSubtitleStream && state.SubtitleDeliveryMethod == SubtitleDeliveryMethod.Encode;
diff --git a/MediaBrowser.Api/Playback/MediaInfoService.cs b/MediaBrowser.Api/Playback/MediaInfoService.cs
index ab3994a63..da8f99a3d 100644
--- a/MediaBrowser.Api/Playback/MediaInfoService.cs
+++ b/MediaBrowser.Api/Playback/MediaInfoService.cs
@@ -1,5 +1,6 @@
using System;
using System.Collections.Generic;
+using System.Globalization;
using System.Linq;
using System.Threading;
using System.Threading.Tasks;
@@ -306,7 +307,7 @@ namespace MediaBrowser.Api.Playback
{
result.MediaSources = Clone(result.MediaSources);
- result.PlaySessionId = Guid.NewGuid().ToString("N");
+ result.PlaySessionId = Guid.NewGuid().ToString("N", CultureInfo.InvariantCulture);
}
return result;
diff --git a/MediaBrowser.Api/Playback/StreamState.cs b/MediaBrowser.Api/Playback/StreamState.cs
index 8d4b0cb3d..7396b5c99 100644
--- a/MediaBrowser.Api/Playback/StreamState.cs
+++ b/MediaBrowser.Api/Playback/StreamState.cs
@@ -1,17 +1,14 @@
using System;
-using System.IO;
using MediaBrowser.Controller.Library;
using MediaBrowser.Controller.MediaEncoding;
using MediaBrowser.Model.Dlna;
-using MediaBrowser.Model.Net;
-using Microsoft.Extensions.Logging;
namespace MediaBrowser.Api.Playback
{
public class StreamState : EncodingJobInfo, IDisposable
{
- private readonly ILogger _logger;
private readonly IMediaSourceManager _mediaSourceManager;
+ private bool _disposed = false;
public string RequestedUrl { get; set; }
@@ -30,11 +27,6 @@ namespace MediaBrowser.Api.Playback
public VideoStreamRequest VideoRequest => Request as VideoStreamRequest;
- /// <summary>
- /// Gets or sets the log file stream.
- /// </summary>
- /// <value>The log file stream.</value>
- public Stream LogFileStream { get; set; }
public IDirectStreamProvider DirectStreamProvider { get; set; }
public string WaitForPath { get; set; }
@@ -72,6 +64,7 @@ namespace MediaBrowser.Api.Playback
{
return 3;
}
+
return 6;
}
@@ -94,82 +87,57 @@ namespace MediaBrowser.Api.Playback
public string UserAgent { get; set; }
- public StreamState(IMediaSourceManager mediaSourceManager, ILogger logger, TranscodingJobType transcodingType)
- : base(transcodingType)
- {
- _mediaSourceManager = mediaSourceManager;
- _logger = logger;
- }
-
public bool EstimateContentLength { get; set; }
+
public TranscodeSeekInfo TranscodeSeekInfo { get; set; }
public bool EnableDlnaHeaders { get; set; }
- public override void Dispose()
- {
- DisposeTranscodingThrottler();
- DisposeLogStream();
- DisposeLiveStream();
+ public DeviceProfile DeviceProfile { get; set; }
- TranscodingJob = null;
+ public TranscodingJob TranscodingJob { get; set; }
+
+ public StreamState(IMediaSourceManager mediaSourceManager, TranscodingJobType transcodingType)
+ : base(transcodingType)
+ {
+ _mediaSourceManager = mediaSourceManager;
}
- private void DisposeTranscodingThrottler()
+ public override void ReportTranscodingProgress(TimeSpan? transcodingPosition, float framerate, double? percentComplete, long bytesTranscoded, int? bitRate)
{
- if (TranscodingThrottler != null)
- {
- try
- {
- TranscodingThrottler.Dispose();
- }
- catch (Exception ex)
- {
- _logger.LogError(ex, "Error disposing TranscodingThrottler");
- }
+ ApiEntryPoint.Instance.ReportTranscodingProgress(TranscodingJob, this, transcodingPosition, framerate, percentComplete, bytesTranscoded, bitRate);
+ }
- TranscodingThrottler = null;
- }
+ public void Dispose()
+ {
+ Dispose(true);
+ GC.SuppressFinalize(this);
}
- private void DisposeLogStream()
+ protected virtual void Dispose(bool disposing)
{
- if (LogFileStream != null)
+ if (_disposed)
{
- try
- {
- LogFileStream.Dispose();
- }
- catch (Exception ex)
- {
- _logger.LogError(ex, "Error disposing log stream");
- }
-
- LogFileStream = null;
+ return;
}
- }
- private async void DisposeLiveStream()
- {
- if (MediaSource.RequiresClosing && string.IsNullOrWhiteSpace(Request.LiveStreamId) && !string.IsNullOrWhiteSpace(MediaSource.LiveStreamId))
+ if (disposing)
{
- try
- {
- await _mediaSourceManager.CloseLiveStream(MediaSource.LiveStreamId).ConfigureAwait(false);
- }
- catch (Exception ex)
+ // REVIEW: Is this the right place for this?
+ if (MediaSource.RequiresClosing
+ && string.IsNullOrWhiteSpace(Request.LiveStreamId)
+ && !string.IsNullOrWhiteSpace(MediaSource.LiveStreamId))
{
- _logger.LogError(ex, "Error closing media source");
+ _mediaSourceManager.CloseLiveStream(MediaSource.LiveStreamId).GetAwaiter().GetResult();
}
+
+ TranscodingThrottler?.Dispose();
}
- }
- public DeviceProfile DeviceProfile { get; set; }
+ TranscodingThrottler = null;
+ TranscodingJob = null;
- public TranscodingJob TranscodingJob;
- public override void ReportTranscodingProgress(TimeSpan? transcodingPosition, float framerate, double? percentComplete, long bytesTranscoded, int? bitRate)
- {
- ApiEntryPoint.Instance.ReportTranscodingProgress(TranscodingJob, this, transcodingPosition, framerate, percentComplete, bytesTranscoded, bitRate);
+ _disposed = true;
}
}
}
diff --git a/MediaBrowser.Api/ScheduledTasks/ScheduledTasksWebSocketListener.cs b/MediaBrowser.Api/ScheduledTasks/ScheduledTasksWebSocketListener.cs
index d24a18743..d9530ffb7 100644
--- a/MediaBrowser.Api/ScheduledTasks/ScheduledTasksWebSocketListener.cs
+++ b/MediaBrowser.Api/ScheduledTasks/ScheduledTasksWebSocketListener.cs
@@ -1,6 +1,5 @@
using System.Collections.Generic;
using System.Linq;
-using System.Threading;
using System.Threading.Tasks;
using MediaBrowser.Controller.Net;
using MediaBrowser.Model.Events;
diff --git a/MediaBrowser.Api/SearchService.cs b/MediaBrowser.Api/SearchService.cs
index ecf07c912..6c67d4fb1 100644
--- a/MediaBrowser.Api/SearchService.cs
+++ b/MediaBrowser.Api/SearchService.cs
@@ -1,4 +1,5 @@
using System;
+using System.Globalization;
using System.Linq;
using MediaBrowser.Controller.Drawing;
using MediaBrowser.Controller.Dto;
@@ -305,7 +306,7 @@ namespace MediaBrowser.Api
if (tag != null)
{
hint.ThumbImageTag = tag;
- hint.ThumbImageItemId = itemWithImage.Id.ToString("N");
+ hint.ThumbImageItemId = itemWithImage.Id.ToString("N", CultureInfo.InvariantCulture);
}
}
}
@@ -326,7 +327,7 @@ namespace MediaBrowser.Api
if (tag != null)
{
hint.BackdropImageTag = tag;
- hint.BackdropImageItemId = itemWithImage.Id.ToString("N");
+ hint.BackdropImageItemId = itemWithImage.Id.ToString("N", CultureInfo.InvariantCulture);
}
}
}
diff --git a/MediaBrowser.Api/Session/SessionInfoWebSocketListener.cs b/MediaBrowser.Api/Session/SessionInfoWebSocketListener.cs
index b79e9f84b..f1a6622fb 100644
--- a/MediaBrowser.Api/Session/SessionInfoWebSocketListener.cs
+++ b/MediaBrowser.Api/Session/SessionInfoWebSocketListener.cs
@@ -1,5 +1,4 @@
using System.Collections.Generic;
-using System.Threading;
using System.Threading.Tasks;
using MediaBrowser.Controller.Library;
using MediaBrowser.Controller.Net;
diff --git a/MediaBrowser.Api/Session/SessionsService.cs b/MediaBrowser.Api/Session/SessionsService.cs
index 4109b12bf..76392e27c 100644
--- a/MediaBrowser.Api/Session/SessionsService.cs
+++ b/MediaBrowser.Api/Session/SessionsService.cs
@@ -1,4 +1,5 @@
using System;
+using System.Globalization;
using System.Linq;
using System.Threading;
using System.Threading.Tasks;
@@ -316,7 +317,7 @@ namespace MediaBrowser.Api.Session
_authRepo.Create(new AuthenticationInfo
{
AppName = request.App,
- AccessToken = Guid.NewGuid().ToString("N"),
+ AccessToken = Guid.NewGuid().ToString("N", CultureInfo.InvariantCulture),
DateCreated = DateTime.UtcNow,
DeviceId = _appHost.SystemId,
DeviceName = _appHost.FriendlyName,
diff --git a/MediaBrowser.Api/Subtitles/SubtitleService.cs b/MediaBrowser.Api/Subtitles/SubtitleService.cs
index 08aa540a5..52043d3df 100644
--- a/MediaBrowser.Api/Subtitles/SubtitleService.cs
+++ b/MediaBrowser.Api/Subtitles/SubtitleService.cs
@@ -168,7 +168,7 @@ namespace MediaBrowser.Api.Subtitles
builder.AppendLine("#EXT-X-MEDIA-SEQUENCE:0");
builder.AppendLine("#EXT-X-PLAYLIST-TYPE:VOD");
- long positionTicks = 0;
+ long positionTicks = 0;
var accessToken = _authContext.GetAuthorizationInfo(Request).Token;
@@ -206,7 +206,7 @@ namespace MediaBrowser.Api.Subtitles
{
var item = (Video)_libraryManager.GetItemById(request.Id);
- var idString = request.Id.ToString("N");
+ var idString = request.Id.ToString("N", CultureInfo.InvariantCulture);
var mediaSource = _mediaSourceManager.GetStaticMediaSources(item, false, null)
.First(i => string.Equals(i.Id, request.MediaSourceId ?? idString));
diff --git a/MediaBrowser.Api/TvShowsService.cs b/MediaBrowser.Api/TvShowsService.cs
index b0900a554..2951fa6b4 100644
--- a/MediaBrowser.Api/TvShowsService.cs
+++ b/MediaBrowser.Api/TvShowsService.cs
@@ -1,5 +1,6 @@
using System;
using System.Collections.Generic;
+using System.Globalization;
using System.Linq;
using MediaBrowser.Common.Extensions;
using MediaBrowser.Controller.Dto;
@@ -470,7 +471,7 @@ namespace MediaBrowser.Api
if (!string.IsNullOrWhiteSpace(request.StartItemId))
{
- episodes = episodes.SkipWhile(i => !string.Equals(i.Id.ToString("N"), request.StartItemId, StringComparison.OrdinalIgnoreCase)).ToList();
+ episodes = episodes.SkipWhile(i => !string.Equals(i.Id.ToString("N", CultureInfo.InvariantCulture), request.StartItemId, StringComparison.OrdinalIgnoreCase)).ToList();
}
// This must be the last filter
diff --git a/MediaBrowser.Api/UserLibrary/ItemsService.cs b/MediaBrowser.Api/UserLibrary/ItemsService.cs
index 3c7ad1d0a..a1e976bed 100644
--- a/MediaBrowser.Api/UserLibrary/ItemsService.cs
+++ b/MediaBrowser.Api/UserLibrary/ItemsService.cs
@@ -99,7 +99,7 @@ namespace MediaBrowser.Api.UserLibrary
{
ancestorIds = _libraryManager.GetUserRootFolder().GetChildren(user, true)
.Where(i => i is Folder)
- .Where(i => !excludeFolderIds.Contains(i.Id.ToString("N")))
+ .Where(i => !excludeFolderIds.Contains(i.Id.ToString("N", CultureInfo.InvariantCulture)))
.Select(i => i.Id)
.ToArray();
}
@@ -224,7 +224,19 @@ namespace MediaBrowser.Api.UserLibrary
request.IncludeItemTypes = "Playlist";
}
- if (!user.Policy.EnableAllFolders && !user.Policy.EnabledFolders.Any(i => new Guid(i) == item.Id))
+ bool isInEnabledFolder = user.Policy.EnabledFolders.Any(i => new Guid(i) == item.Id);
+ var collectionFolders = _libraryManager.GetCollectionFolders(item);
+ foreach (var collectionFolder in collectionFolders)
+ {
+ if (user.Policy.EnabledFolders.Contains(
+ collectionFolder.Id.ToString("N", CultureInfo.InvariantCulture),
+ StringComparer.OrdinalIgnoreCase))
+ {
+ isInEnabledFolder = true;
+ }
+ }
+
+ if (!(item is UserRootFolder) && !user.Policy.EnableAllFolders && !isInEnabledFolder)
{
Logger.LogWarning("{UserName} is not permitted to access Library {ItemName}.", user.Name, item.Name);
return new QueryResult<BaseItem>
diff --git a/MediaBrowser.Api/UserLibrary/UserViewsService.cs b/MediaBrowser.Api/UserLibrary/UserViewsService.cs
index 1d61c5c1e..2fa5d8933 100644
--- a/MediaBrowser.Api/UserLibrary/UserViewsService.cs
+++ b/MediaBrowser.Api/UserLibrary/UserViewsService.cs
@@ -1,4 +1,5 @@
using System;
+using System.Globalization;
using System.Linq;
using MediaBrowser.Controller.Dto;
using MediaBrowser.Controller.Entities;
@@ -116,7 +117,7 @@ namespace MediaBrowser.Api.UserLibrary
.Select(i => new SpecialViewOption
{
Name = i.Name,
- Id = i.Id.ToString("N")
+ Id = i.Id.ToString("N", CultureInfo.InvariantCulture)
})
.OrderBy(i => i.Name)
diff --git a/MediaBrowser.Api/UserService.cs b/MediaBrowser.Api/UserService.cs
index 497800d26..21a94a4e0 100644
--- a/MediaBrowser.Api/UserService.cs
+++ b/MediaBrowser.Api/UserService.cs
@@ -214,6 +214,9 @@ namespace MediaBrowser.Api
{
[ApiMember(Name = "Name", IsRequired = true, DataType = "string", ParameterType = "body", Verb = "POST")]
public string Name { get; set; }
+
+ [ApiMember(Name = "Password", IsRequired = false, DataType = "string", ParameterType = "body", Verb = "POST")]
+ public string Password { get; set; }
}
[Route("/Users/ForgotPassword", "POST", Summary = "Initiates the forgot password process for a local user")]
@@ -362,8 +365,8 @@ namespace MediaBrowser.Api
}
_sessionMananger.RevokeUserTokens(user.Id, null);
-
- return _userManager.DeleteUser(user);
+ _userManager.DeleteUser(user);
+ return Task.CompletedTask;
}
/// <summary>
@@ -406,7 +409,6 @@ namespace MediaBrowser.Api
PasswordSha1 = request.Password,
RemoteEndPoint = Request.RemoteIp,
Username = request.Username
-
}).ConfigureAwait(false);
return ToOptimizedResult(result);
@@ -508,20 +510,19 @@ namespace MediaBrowser.Api
/// <returns>System.Object.</returns>
public async Task<object> Post(CreateUserByName request)
{
- var dtoUser = request;
+ var newUser = _userManager.CreateUser(request.Name);
- var newUser = await _userManager.CreateUser(dtoUser.Name).ConfigureAwait(false);
+ // no need to authenticate password for new user
+ if (request.Password != null)
+ {
+ await _userManager.ChangePassword(newUser, request.Password).ConfigureAwait(false);
+ }
var result = _userManager.GetUserDto(newUser, Request.RemoteIp);
return ToOptimizedResult(result);
}
- /// <summary>
- /// Posts the specified request.
- /// </summary>
- /// <param name="request">The request.</param>
- /// <returns>System.Object.</returns>
public async Task<object> Post(ForgotPassword request)
{
var isLocal = Request.IsLocal || _networkManager.IsInLocalNetwork(Request.RemoteIp);
diff --git a/MediaBrowser.Api/VideosService.cs b/MediaBrowser.Api/VideosService.cs
index 061f72438..474036f5c 100644
--- a/MediaBrowser.Api/VideosService.cs
+++ b/MediaBrowser.Api/VideosService.cs
@@ -1,4 +1,5 @@
using System;
+using System.Globalization;
using System.Linq;
using System.Threading;
using MediaBrowser.Controller.Configuration;
@@ -168,7 +169,7 @@ namespace MediaBrowser.Api
foreach (var item in items.Where(i => i.Id != primaryVersion.Id))
{
- item.SetPrimaryVersionId(primaryVersion.Id.ToString("N"));
+ item.SetPrimaryVersionId(primaryVersion.Id.ToString("N", CultureInfo.InvariantCulture));
item.UpdateToRepository(ItemUpdateType.MetadataEdit, CancellationToken.None);