mirror of
https://github.com/jellyfin/jellyfin.git
synced 2026-07-01 20:02:52 +01:00
Merge branch 'master' into h265
This commit is contained in:
@@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -133,8 +133,21 @@ 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)
|
||||
{
|
||||
var file = req.Form.Files.Count == 0 ? null : req.Form.Files[0];
|
||||
|
||||
return _deviceManager.AcceptCameraUpload(deviceId, file.OpenReadStream(), new LocalFileInfo
|
||||
{
|
||||
MimeType = file.ContentType,
|
||||
Album = album,
|
||||
Name = name,
|
||||
Id = id
|
||||
});
|
||||
}
|
||||
else
|
||||
{
|
||||
return _deviceManager.AcceptCameraUpload(deviceId, request.RequestStream, new LocalFileInfo
|
||||
{
|
||||
@@ -144,18 +157,6 @@ namespace MediaBrowser.Api.Devices
|
||||
Id = id
|
||||
});
|
||||
}
|
||||
else
|
||||
{
|
||||
var file = Request.Files.Length == 0 ? null : Request.Files[0];
|
||||
|
||||
return _deviceManager.AcceptCameraUpload(deviceId, file.InputStream, new LocalFileInfo
|
||||
{
|
||||
MimeType = file.ContentType,
|
||||
Album = album,
|
||||
Name = name,
|
||||
Id = id
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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) &&
|
||||
|
||||
@@ -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>
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
@@ -12,6 +12,7 @@
|
||||
<PropertyGroup>
|
||||
<TargetFramework>netstandard2.0</TargetFramework>
|
||||
<GenerateAssemblyInfo>false</GenerateAssemblyInfo>
|
||||
<GenerateDocumentationFile>true</GenerateDocumentationFile>
|
||||
</PropertyGroup>
|
||||
|
||||
</Project>
|
||||
|
||||
@@ -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();
|
||||
|
||||
@@ -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));
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -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,15 +65,25 @@ 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; }
|
||||
|
||||
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>
|
||||
@@ -112,12 +122,6 @@ namespace MediaBrowser.Api.Playback
|
||||
/// </summary>
|
||||
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>
|
||||
@@ -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);
|
||||
|
||||
@@ -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();
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -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;
|
||||
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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();
|
||||
|
||||
TranscodingJob = null;
|
||||
}
|
||||
|
||||
private void DisposeTranscodingThrottler()
|
||||
{
|
||||
if (TranscodingThrottler != null)
|
||||
{
|
||||
try
|
||||
{
|
||||
TranscodingThrottler.Dispose();
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
_logger.LogError(ex, "Error disposing TranscodingThrottler");
|
||||
}
|
||||
|
||||
TranscodingThrottler = null;
|
||||
}
|
||||
}
|
||||
|
||||
private void DisposeLogStream()
|
||||
{
|
||||
if (LogFileStream != null)
|
||||
{
|
||||
try
|
||||
{
|
||||
LogFileStream.Dispose();
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
_logger.LogError(ex, "Error disposing log stream");
|
||||
}
|
||||
|
||||
LogFileStream = null;
|
||||
}
|
||||
}
|
||||
|
||||
private async void DisposeLiveStream()
|
||||
{
|
||||
if (MediaSource.RequiresClosing && string.IsNullOrWhiteSpace(Request.LiveStreamId) && !string.IsNullOrWhiteSpace(MediaSource.LiveStreamId))
|
||||
{
|
||||
try
|
||||
{
|
||||
await _mediaSourceManager.CloseLiveStream(MediaSource.LiveStreamId).ConfigureAwait(false);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
_logger.LogError(ex, "Error closing media source");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public DeviceProfile DeviceProfile { get; set; }
|
||||
|
||||
public TranscodingJob TranscodingJob;
|
||||
public TranscodingJob TranscodingJob { get; set; }
|
||||
|
||||
public StreamState(IMediaSourceManager mediaSourceManager, TranscodingJobType transcodingType)
|
||||
: base(transcodingType)
|
||||
{
|
||||
_mediaSourceManager = mediaSourceManager;
|
||||
}
|
||||
|
||||
public override void ReportTranscodingProgress(TimeSpan? transcodingPosition, float framerate, double? percentComplete, long bytesTranscoded, int? bitRate)
|
||||
{
|
||||
ApiEntryPoint.Instance.ReportTranscodingProgress(TranscodingJob, this, transcodingPosition, framerate, percentComplete, bytesTranscoded, bitRate);
|
||||
}
|
||||
|
||||
public void Dispose()
|
||||
{
|
||||
Dispose(true);
|
||||
GC.SuppressFinalize(this);
|
||||
}
|
||||
|
||||
protected virtual void Dispose(bool disposing)
|
||||
{
|
||||
if (_disposed)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
if (disposing)
|
||||
{
|
||||
// REVIEW: Is this the right place for this?
|
||||
if (MediaSource.RequiresClosing
|
||||
&& string.IsNullOrWhiteSpace(Request.LiveStreamId)
|
||||
&& !string.IsNullOrWhiteSpace(MediaSource.LiveStreamId))
|
||||
{
|
||||
_mediaSourceManager.CloseLiveStream(MediaSource.LiveStreamId).GetAwaiter().GetResult();
|
||||
}
|
||||
|
||||
TranscodingThrottler?.Dispose();
|
||||
}
|
||||
|
||||
TranscodingThrottler = null;
|
||||
TranscodingJob = null;
|
||||
|
||||
_disposed = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,5 +1,4 @@
|
||||
using System.Collections.Generic;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
using MediaBrowser.Controller.Library;
|
||||
using MediaBrowser.Controller.Net;
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -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));
|
||||
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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>
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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);
|
||||
|
||||
|
||||
Reference in New Issue
Block a user