diff options
Diffstat (limited to 'MediaBrowser.Api')
| -rw-r--r-- | MediaBrowser.Api/ConnectService.cs | 55 | ||||
| -rw-r--r-- | MediaBrowser.Api/Images/ImageRequest.cs | 5 | ||||
| -rw-r--r-- | MediaBrowser.Api/Images/ImageService.cs | 1 | ||||
| -rw-r--r-- | MediaBrowser.Api/Library/FileOrganizationService.cs | 39 | ||||
| -rw-r--r-- | MediaBrowser.Api/MediaBrowser.Api.csproj | 3 | ||||
| -rw-r--r-- | MediaBrowser.Api/PinLoginService.cs | 202 | ||||
| -rw-r--r-- | MediaBrowser.Api/Playback/BaseStreamingService.cs | 39 | ||||
| -rw-r--r-- | MediaBrowser.Api/Playback/Progressive/VideoService.cs | 29 | ||||
| -rw-r--r-- | MediaBrowser.Api/Playback/StreamRequest.cs | 3 | ||||
| -rw-r--r-- | MediaBrowser.Api/ScheduledTasks/ScheduledTaskService.cs | 22 | ||||
| -rw-r--r-- | MediaBrowser.Api/UserService.cs | 17 | ||||
| -rw-r--r-- | MediaBrowser.Api/packages.config | 2 |
12 files changed, 121 insertions, 296 deletions
diff --git a/MediaBrowser.Api/ConnectService.cs b/MediaBrowser.Api/ConnectService.cs index bdd2eeaadd..4bcd33d9e3 100644 --- a/MediaBrowser.Api/ConnectService.cs +++ b/MediaBrowser.Api/ConnectService.cs @@ -1,10 +1,8 @@ -using System; -using MediaBrowser.Common.Extensions; +using MediaBrowser.Common.Extensions; using MediaBrowser.Controller.Connect; using MediaBrowser.Controller.Library; using MediaBrowser.Controller.Net; using MediaBrowser.Model.Connect; -using MediaBrowser.Model.Dto; using ServiceStack; using System.Collections.Generic; using System.Linq; @@ -75,28 +73,6 @@ namespace MediaBrowser.Api public string ConnectUserId { get; set; } } - [Route("/Connect/Supporters", "GET")] - [Authenticated(Roles = "Admin")] - public class GetConnectSupporterSummary : IReturn<ConnectSupporterSummary> - { - } - - [Route("/Connect/Supporters", "DELETE")] - [Authenticated(Roles = "Admin")] - public class RemoveConnectSupporter : IReturnVoid - { - [ApiMember(Name = "Id", Description = "User Id", IsRequired = true, DataType = "string", ParameterType = "query", Verb = "DELETE")] - public string Id { get; set; } - } - - [Route("/Connect/Supporters", "POST")] - [Authenticated(Roles = "Admin")] - public class AddConnectSupporter : IReturnVoid - { - [ApiMember(Name = "Id", Description = "User Id", IsRequired = true, DataType = "string", ParameterType = "query", Verb = "POST")] - public string Id { get; set; } - } - public class ConnectService : BaseApiService { private readonly IConnectManager _connectManager; @@ -108,35 +84,6 @@ namespace MediaBrowser.Api _userManager = userManager; } - public async Task<object> Get(GetConnectSupporterSummary request) - { - var result = await _connectManager.GetConnectSupporterSummary().ConfigureAwait(false); - var existingConnectUserIds = result.Users.Select(i => i.Id).ToList(); - - result.EligibleUsers = _userManager.Users - .Where(i => !string.IsNullOrWhiteSpace(i.ConnectUserId)) - .Where(i => !existingConnectUserIds.Contains(i.ConnectUserId, StringComparer.OrdinalIgnoreCase)) - .OrderBy(i => i.Name) - .Select(i => _userManager.GetUserDto(i)) - .ToList(); - - return ToOptimizedResult(result); - } - - public void Delete(RemoveConnectSupporter request) - { - var task = _connectManager.RemoveConnectSupporter(request.Id); - - Task.WaitAll(task); - } - - public void Post(AddConnectSupporter request) - { - var task = _connectManager.AddConnectSupporter(request.Id); - - Task.WaitAll(task); - } - public object Post(CreateConnectLink request) { return _connectManager.LinkUser(request.Id, request.ConnectUsername); diff --git a/MediaBrowser.Api/Images/ImageRequest.cs b/MediaBrowser.Api/Images/ImageRequest.cs index cdd348bb52..8b86ee7e0f 100644 --- a/MediaBrowser.Api/Images/ImageRequest.cs +++ b/MediaBrowser.Api/Images/ImageRequest.cs @@ -66,7 +66,10 @@ namespace MediaBrowser.Api.Images [ApiMember(Name = "BackgroundColor", Description = "Optional. Apply a background color for transparent images.", IsRequired = false, DataType = "string", ParameterType = "query", Verb = "GET")] public string BackgroundColor { get; set; } - + + [ApiMember(Name = "ForegroundLayer", Description = "Optional. Apply a foreground layer on top of the image.", IsRequired = false, DataType = "string", ParameterType = "query", Verb = "GET")] + public string ForegroundLayer { get; set; } + public ImageRequest() { EnableImageEnhancers = true; diff --git a/MediaBrowser.Api/Images/ImageService.cs b/MediaBrowser.Api/Images/ImageService.cs index 7122c8fc12..8d58070fdf 100644 --- a/MediaBrowser.Api/Images/ImageService.cs +++ b/MediaBrowser.Api/Images/ImageService.cs @@ -624,6 +624,7 @@ namespace MediaBrowser.Api.Images PercentPlayed = request.PercentPlayed ?? 0, UnplayedCount = request.UnplayedCount, BackgroundColor = request.BackgroundColor, + ForegroundLayer = request.ForegroundLayer, SupportedOutputFormats = supportedFormats }; diff --git a/MediaBrowser.Api/Library/FileOrganizationService.cs b/MediaBrowser.Api/Library/FileOrganizationService.cs index 1224fa9570..849e9cf0db 100644 --- a/MediaBrowser.Api/Library/FileOrganizationService.cs +++ b/MediaBrowser.Api/Library/FileOrganizationService.cs @@ -6,6 +6,7 @@ using MediaBrowser.Model.Querying; using ServiceStack; using System.Threading.Tasks; using MediaBrowser.Model.Dto; +using MediaBrowser.Model.Serialization; namespace MediaBrowser.Api.Library { @@ -54,7 +55,7 @@ namespace MediaBrowser.Api.Library public string Id { get; set; } } - [Route("/Library/FileOrganizations/{Id}/Episode/Organize", "POST", Summary = "Performs an organization")] + [Route("/Library/FileOrganizations/{Id}/Episode/Organize", "POST", Summary = "Performs organization of a tv episode")] public class OrganizeEpisode { [ApiMember(Name = "Id", Description = "Result Id", IsRequired = true, DataType = "string", ParameterType = "path", Verb = "POST")] @@ -74,6 +75,18 @@ namespace MediaBrowser.Api.Library [ApiMember(Name = "RememberCorrection", Description = "Whether or not to apply the same correction to future episodes of the same series.", IsRequired = false, DataType = "bool", ParameterType = "query", Verb = "POST")] public bool RememberCorrection { get; set; } + + [ApiMember(Name = "NewSeriesProviderIds", Description = "A list of provider IDs identifying a new series.", IsRequired = false, DataType = "Dictionary<string, string>", ParameterType = "query", Verb = "POST")] + public Dictionary<string, string> NewSeriesProviderIds { get; set; } + + [ApiMember(Name = "NewSeriesName", Description = "Name of a series to add.", IsRequired = false, DataType = "string", ParameterType = "query", Verb = "POST")] + public string NewSeriesName { get; set; } + + [ApiMember(Name = "NewSeriesYear", Description = "Year of a series to add.", IsRequired = false, DataType = "string", ParameterType = "query", Verb = "POST")] + public string NewSeriesYear { get; set; } + + [ApiMember(Name = "TargetFolder", Description = "Target Folder", IsRequired = false, DataType = "string", ParameterType = "query", Verb = "POST")] + public string TargetFolder { get; set; } } [Route("/Library/FileOrganizations/SmartMatches", "GET", Summary = "Gets smart match entries")] @@ -106,9 +119,14 @@ namespace MediaBrowser.Api.Library { private readonly IFileOrganizationService _iFileOrganizationService; - public FileOrganizationService(IFileOrganizationService iFileOrganizationService) + /// The _json serializer + /// </summary> + private readonly IJsonSerializer _jsonSerializer; + + public FileOrganizationService(IFileOrganizationService iFileOrganizationService, IJsonSerializer jsonSerializer) { _iFileOrganizationService = iFileOrganizationService; + _jsonSerializer = jsonSerializer; } public object Get(GetFileOrganizationActivity request) @@ -145,6 +163,13 @@ namespace MediaBrowser.Api.Library public void Post(OrganizeEpisode request) { + var dicNewProviderIds = new Dictionary<string, string>(); + + if (request.NewSeriesProviderIds != null) + { + dicNewProviderIds = request.NewSeriesProviderIds; + } + var task = _iFileOrganizationService.PerformEpisodeOrganization(new EpisodeFileOrganizationRequest { EndingEpisodeNumber = request.EndingEpisodeNumber, @@ -152,9 +177,17 @@ namespace MediaBrowser.Api.Library RememberCorrection = request.RememberCorrection, ResultId = request.Id, SeasonNumber = request.SeasonNumber, - SeriesId = request.SeriesId + SeriesId = request.SeriesId, + NewSeriesName = request.NewSeriesName, + NewSeriesYear = request.NewSeriesYear, + NewSeriesProviderIds = dicNewProviderIds, + TargetFolder = request.TargetFolder }); + // For async processing (close dialog early instead of waiting until the file has been copied) + //var tasks = new Task[] { task }; + //Task.WaitAll(tasks, 8000); + Task.WaitAll(task); } diff --git a/MediaBrowser.Api/MediaBrowser.Api.csproj b/MediaBrowser.Api/MediaBrowser.Api.csproj index f711c69e63..be79f4d74f 100644 --- a/MediaBrowser.Api/MediaBrowser.Api.csproj +++ b/MediaBrowser.Api/MediaBrowser.Api.csproj @@ -47,7 +47,7 @@ <ItemGroup> <Reference Include="CommonIO, Version=1.0.0.0, Culture=neutral, processorArchitecture=MSIL"> <SpecificVersion>False</SpecificVersion> - <HintPath>..\packages\CommonIO.1.0.0.7\lib\net45\CommonIO.dll</HintPath> + <HintPath>..\packages\CommonIO.1.0.0.8\lib\net45\CommonIO.dll</HintPath> </Reference> <Reference Include="MoreLinq"> <HintPath>..\packages\morelinq.1.4.0\lib\net35\MoreLinq.dll</HintPath> @@ -80,7 +80,6 @@ <Compile Include="FilterService.cs" /> <Compile Include="IHasDtoOptions.cs" /> <Compile Include="Library\ChapterService.cs" /> - <Compile Include="PinLoginService.cs" /> <Compile Include="Playback\Dash\ManifestBuilder.cs" /> <Compile Include="Playback\Dash\MpegDashService.cs" /> <Compile Include="Playback\MediaInfoService.cs" /> diff --git a/MediaBrowser.Api/PinLoginService.cs b/MediaBrowser.Api/PinLoginService.cs deleted file mode 100644 index 8b63de10a5..0000000000 --- a/MediaBrowser.Api/PinLoginService.cs +++ /dev/null @@ -1,202 +0,0 @@ -using System; -using System.Collections.Concurrent; -using System.Globalization; -using MediaBrowser.Common.Extensions; -using MediaBrowser.Controller.Net; -using MediaBrowser.Model.Connect; -using ServiceStack; - -namespace MediaBrowser.Api -{ - [Route("/Auth/Pin", "POST", Summary = "Creates a pin request")] - public class CreatePinRequest : IReturn<PinCreationResult> - { - [ApiMember(Name = "DeviceId", IsRequired = true, DataType = "string", ParameterType = "query", Verb = "POST")] - public string DeviceId { get; set; } - } - - [Route("/Auth/Pin", "GET", Summary = "Gets pin status")] - public class GetPinStatusRequest : IReturn<PinStatusResult> - { - [ApiMember(Name = "DeviceId", IsRequired = true, DataType = "string", ParameterType = "query", Verb = "GET")] - public string DeviceId { get; set; } - [ApiMember(Name = "Pin", IsRequired = true, DataType = "string", ParameterType = "query", Verb = "GET")] - public string Pin { get; set; } - } - - [Route("/Auth/Pin/Exchange", "POST", Summary = "Exchanges a pin")] - public class ExchangePinRequest : IReturn<PinExchangeResult> - { - [ApiMember(Name = "DeviceId", IsRequired = true, DataType = "string", ParameterType = "query", Verb = "POST")] - public string DeviceId { get; set; } - [ApiMember(Name = "Pin", IsRequired = true, DataType = "string", ParameterType = "query", Verb = "POST")] - public string Pin { get; set; } - } - - [Route("/Auth/Pin/Validate", "POST", Summary = "Validates a pin")] - [Authenticated] - public class ValidatePinRequest : IReturnVoid - { - [ApiMember(Name = "Pin", IsRequired = true, DataType = "string", ParameterType = "query", Verb = "POST")] - public string Pin { get; set; } - } - - public class PinLoginService : BaseApiService - { - private readonly ConcurrentDictionary<string, MyPinStatus> _activeRequests = new ConcurrentDictionary<string, MyPinStatus>(StringComparer.OrdinalIgnoreCase); - - public object Post(CreatePinRequest request) - { - var pin = GetNewPin(); - - var value = new MyPinStatus - { - CreationTimeUtc = DateTime.UtcNow, - IsConfirmed = false, - IsExpired = false, - Pin = pin, - DeviceId = request.DeviceId - }; - - _activeRequests.AddOrUpdate(pin, value, (k, v) => value); - - return ToOptimizedResult(new PinCreationResult - { - DeviceId = request.DeviceId, - IsConfirmed = false, - IsExpired = false, - Pin = pin - }); - } - - public object Get(GetPinStatusRequest request) - { - MyPinStatus status; - - if (!_activeRequests.TryGetValue(request.Pin, out status)) - { - throw new ResourceNotFoundException(); - } - - EnsureValid(request.DeviceId, status); - - return ToOptimizedResult(new PinStatusResult - { - Pin = status.Pin, - IsConfirmed = status.IsConfirmed, - IsExpired = status.IsExpired - }); - } - - public object Post(ExchangePinRequest request) - { - MyPinStatus status; - - if (!_activeRequests.TryGetValue(request.Pin, out status)) - { - throw new ResourceNotFoundException(); - } - - EnsureValid(request.DeviceId, status); - - if (!status.IsConfirmed) - { - throw new ResourceNotFoundException(); - } - - return ToOptimizedResult(new PinExchangeResult - { - // TODO: Add access token - UserId = status.UserId - }); - } - - public void Post(ValidatePinRequest request) - { - MyPinStatus status; - - if (!_activeRequests.TryGetValue(request.Pin, out status)) - { - throw new ResourceNotFoundException(); - } - - EnsureValid(status); - - status.IsConfirmed = true; - status.UserId = AuthorizationContext.GetAuthorizationInfo(Request).UserId; - } - - private void EnsureValid(string requestedDeviceId, MyPinStatus status) - { - if (!string.Equals(requestedDeviceId, status.DeviceId, StringComparison.OrdinalIgnoreCase)) - { - throw new ResourceNotFoundException(); - } - - EnsureValid(status); - } - - private void EnsureValid(MyPinStatus status) - { - if ((DateTime.UtcNow - status.CreationTimeUtc).TotalMinutes > 10) - { - status.IsExpired = true; - } - - if (status.IsExpired) - { - throw new ResourceNotFoundException(); - } - } - - private string GetNewPin() - { - var pin = GetNewPinInternal(); - - while (IsPinActive(pin)) - { - pin = GetNewPinInternal(); - } - - return pin; - } - - private string GetNewPinInternal() - { - var length = 5; - var pin = string.Empty; - - while (pin.Length < length) - { - var digit = new Random().Next(0, 9); - pin += digit.ToString(CultureInfo.InvariantCulture); - } - - return pin; - } - - private bool IsPinActive(string pin) - { - MyPinStatus status; - - if (!_activeRequests.TryGetValue(pin, out status)) - { - return true; - } - - if (status.IsExpired) - { - return true; - } - - return false; - } - - public class MyPinStatus : PinStatusResult - { - public DateTime CreationTimeUtc { get; set; } - public string DeviceId { get; set; } - public string UserId { get; set; } - } - } -} diff --git a/MediaBrowser.Api/Playback/BaseStreamingService.cs b/MediaBrowser.Api/Playback/BaseStreamingService.cs index bae8074fd4..f66363da67 100644 --- a/MediaBrowser.Api/Playback/BaseStreamingService.cs +++ b/MediaBrowser.Api/Playback/BaseStreamingService.cs @@ -477,7 +477,7 @@ namespace MediaBrowser.Api.Playback var pts = string.Empty; - if (state.SubtitleStream != null && state.SubtitleStream.IsTextSubtitleStream) + if (state.SubtitleStream != null && state.SubtitleStream.IsTextSubtitleStream && !state.VideoRequest.CopyTimestamps) { var seconds = TimeSpan.FromTicks(state.Request.StartTimeTicks ?? 0).TotalSeconds; @@ -604,6 +604,10 @@ namespace MediaBrowser.Api.Playback { var seconds = Math.Round(TimeSpan.FromTicks(state.Request.StartTimeTicks ?? 0).TotalSeconds); + var setPtsParam = state.VideoRequest.CopyTimestamps + ? string.Empty + : string.Format(",setpts=PTS -{0}/TB", seconds.ToString(UsCulture)); + if (state.SubtitleStream.IsExternal) { var subtitlePath = state.SubtitleStream.Path; @@ -621,18 +625,18 @@ namespace MediaBrowser.Api.Playback } // TODO: Perhaps also use original_size=1920x800 ?? - return string.Format("subtitles=filename='{0}'{1},setpts=PTS -{2}/TB", + return string.Format("subtitles=filename='{0}'{1}{2}", MediaEncoder.EscapeSubtitleFilterPath(subtitlePath), charsetParam, - seconds.ToString(UsCulture)); + setPtsParam); } var mediaPath = state.MediaPath ?? string.Empty; - return string.Format("subtitles='{0}:si={1}',setpts=PTS -{2}/TB", + return string.Format("subtitles='{0}:si={1}'{2}", MediaEncoder.EscapeSubtitleFilterPath(mediaPath), state.InternalSubtitleStreamOffset.ToString(UsCulture), - seconds.ToString(UsCulture)); + setPtsParam); } /// <summary> @@ -865,6 +869,15 @@ namespace MediaBrowser.Api.Playback { if (state.SubtitleStream.IsExternal && !state.SubtitleStream.IsTextSubtitleStream) { + if (state.VideoStream != null && state.VideoStream.Width.HasValue) + { + // This is hacky but not sure how to get the exact subtitle resolution + double height = state.VideoStream.Width.Value; + height /= 16; + height *= 9; + + arg += string.Format(" -canvas_size {0}:{1}", state.VideoStream.Width.Value.ToString(CultureInfo.InvariantCulture), Convert.ToInt32(height).ToString(CultureInfo.InvariantCulture)); + } arg += " -i \"" + state.SubtitleStream.Path + "\""; } } @@ -1462,6 +1475,13 @@ namespace MediaBrowser.Api.Playback { // Duplicating ItemId because of MediaMonkey } + else if (i == 24) + { + if (videoRequest != null) + { + videoRequest.CopyTimestamps = string.Equals("true", val, StringComparison.OrdinalIgnoreCase); + } + } } } @@ -2021,6 +2041,11 @@ namespace MediaBrowser.Api.Playback state.EstimateContentLength = transcodingProfile.EstimateContentLength; state.EnableMpegtsM2TsMode = transcodingProfile.EnableMpegtsM2TsMode; state.TranscodeSeekInfo = transcodingProfile.TranscodeSeekInfo; + + if (state.VideoRequest != null) + { + state.VideoRequest.CopyTimestamps = transcodingProfile.CopyTimestamps; + } } } } @@ -2184,9 +2209,9 @@ namespace MediaBrowser.Api.Playback if (state.VideoRequest != null) { - if (string.Equals(state.OutputContainer, "mkv", StringComparison.OrdinalIgnoreCase)) + if (string.Equals(state.OutputContainer, "mkv", StringComparison.OrdinalIgnoreCase) && state.VideoRequest.CopyTimestamps) { - //inputModifier += " -noaccurate_seek"; + inputModifier += " -noaccurate_seek"; } } diff --git a/MediaBrowser.Api/Playback/Progressive/VideoService.cs b/MediaBrowser.Api/Playback/Progressive/VideoService.cs index eaf65bd6b6..b7e180eca0 100644 --- a/MediaBrowser.Api/Playback/Progressive/VideoService.cs +++ b/MediaBrowser.Api/Playback/Progressive/VideoService.cs @@ -36,6 +36,7 @@ namespace MediaBrowser.Api.Playback.Progressive [Route("/Videos/{Id}/stream.wmv", "GET")] [Route("/Videos/{Id}/stream.wtv", "GET")] [Route("/Videos/{Id}/stream.mov", "GET")] + [Route("/Videos/{Id}/stream.iso", "GET")] [Route("/Videos/{Id}/stream", "GET")] [Route("/Videos/{Id}/stream.ts", "HEAD")] [Route("/Videos/{Id}/stream.webm", "HEAD")] @@ -53,6 +54,7 @@ namespace MediaBrowser.Api.Playback.Progressive [Route("/Videos/{Id}/stream.wtv", "HEAD")] [Route("/Videos/{Id}/stream.m2ts", "HEAD")] [Route("/Videos/{Id}/stream.mov", "HEAD")] + [Route("/Videos/{Id}/stream.iso", "HEAD")] [Route("/Videos/{Id}/stream", "HEAD")] [Api(Description = "Gets a video stream")] public class GetVideoStream : VideoStreamRequest @@ -65,7 +67,8 @@ namespace MediaBrowser.Api.Playback.Progressive /// </summary> public class VideoService : BaseProgressiveStreamingService { - public VideoService(IServerConfigurationManager serverConfig, IUserManager userManager, ILibraryManager libraryManager, IIsoManager isoManager, IMediaEncoder mediaEncoder, IFileSystem fileSystem, IDlnaManager dlnaManager, ISubtitleEncoder subtitleEncoder, IDeviceManager deviceManager, IMediaSourceManager mediaSourceManager, IZipClient zipClient, IJsonSerializer jsonSerializer, IImageProcessor imageProcessor, IHttpClient httpClient) : base(serverConfig, userManager, libraryManager, isoManager, mediaEncoder, fileSystem, dlnaManager, subtitleEncoder, deviceManager, mediaSourceManager, zipClient, jsonSerializer, imageProcessor, httpClient) + public VideoService(IServerConfigurationManager serverConfig, IUserManager userManager, ILibraryManager libraryManager, IIsoManager isoManager, IMediaEncoder mediaEncoder, IFileSystem fileSystem, IDlnaManager dlnaManager, ISubtitleEncoder subtitleEncoder, IDeviceManager deviceManager, IMediaSourceManager mediaSourceManager, IZipClient zipClient, IJsonSerializer jsonSerializer, IImageProcessor imageProcessor, IHttpClient httpClient) + : base(serverConfig, userManager, libraryManager, isoManager, mediaEncoder, fileSystem, dlnaManager, subtitleEncoder, deviceManager, mediaSourceManager, zipClient, jsonSerializer, imageProcessor, httpClient) { } @@ -137,11 +140,6 @@ namespace MediaBrowser.Api.Playback.Progressive var isOutputMkv = string.Equals(state.OutputContainer, "mkv", StringComparison.OrdinalIgnoreCase); - if (state.RunTimeTicks.HasValue) - { - //args += " -copyts -avoid_negative_ts disabled -start_at_zero"; - } - if (string.Equals(videoCodec, "copy", StringComparison.OrdinalIgnoreCase)) { if (state.VideoStream != null && IsH264(state.VideoStream) && @@ -150,6 +148,11 @@ namespace MediaBrowser.Api.Playback.Progressive args += " -bsf:v h264_mp4toannexb"; } + if (state.RunTimeTicks.HasValue && state.VideoRequest.CopyTimestamps) + { + args += " -copyts -avoid_negative_ts disabled -start_at_zero"; + } + return args; } @@ -160,10 +163,22 @@ namespace MediaBrowser.Api.Playback.Progressive var hasGraphicalSubs = state.SubtitleStream != null && !state.SubtitleStream.IsTextSubtitleStream; + var hasCopyTs = false; // Add resolution params, if specified if (!hasGraphicalSubs) { - args += GetOutputSizeParam(state, videoCodec); + var outputSizeParam = GetOutputSizeParam(state, videoCodec); + args += outputSizeParam; + hasCopyTs = outputSizeParam.IndexOf("copyts", StringComparison.OrdinalIgnoreCase) != -1; + } + + if (state.RunTimeTicks.HasValue && state.VideoRequest.CopyTimestamps) + { + if (!hasCopyTs) + { + args += " -copyts"; + } + args += " -avoid_negative_ts disabled -start_at_zero"; } var qualityParam = GetVideoQualityParam(state, videoCodec); diff --git a/MediaBrowser.Api/Playback/StreamRequest.cs b/MediaBrowser.Api/Playback/StreamRequest.cs index 69f8e6e046..1135a3a54d 100644 --- a/MediaBrowser.Api/Playback/StreamRequest.cs +++ b/MediaBrowser.Api/Playback/StreamRequest.cs @@ -187,6 +187,9 @@ namespace MediaBrowser.Api.Playback [ApiMember(Name = "EnableAutoStreamCopy", Description = "Whether or not to allow automatic stream copy if requested values match the original source. Defaults to true.", IsRequired = false, DataType = "bool", ParameterType = "query", Verb = "GET")] public bool EnableAutoStreamCopy { get; set; } + [ApiMember(Name = "CopyTimestamps", Description = "Whether or not to copy timestamps when transcoding with an offset. Defaults to false.", IsRequired = false, DataType = "bool", ParameterType = "query", Verb = "GET")] + public bool CopyTimestamps { get; set; } + [ApiMember(Name = "Cabac", Description = "Enable if cabac encoding is required", IsRequired = false, DataType = "bool", ParameterType = "query", Verb = "GET")] public bool? Cabac { get; set; } diff --git a/MediaBrowser.Api/ScheduledTasks/ScheduledTaskService.cs b/MediaBrowser.Api/ScheduledTasks/ScheduledTaskService.cs index 949dac9261..d2da2ee846 100644 --- a/MediaBrowser.Api/ScheduledTasks/ScheduledTaskService.cs +++ b/MediaBrowser.Api/ScheduledTasks/ScheduledTaskService.cs @@ -6,6 +6,7 @@ using ServiceStack; using System; using System.Collections.Generic; using System.Linq; +using MediaBrowser.Controller.Configuration; namespace MediaBrowser.Api.ScheduledTasks { @@ -90,12 +91,14 @@ namespace MediaBrowser.Api.ScheduledTasks /// <value>The task manager.</value> private ITaskManager TaskManager { get; set; } + private readonly IServerConfigurationManager _config; + /// <summary> /// Initializes a new instance of the <see cref="ScheduledTaskService" /> class. /// </summary> /// <param name="taskManager">The task manager.</param> - /// <exception cref="System.ArgumentNullException">taskManager</exception> - public ScheduledTaskService(ITaskManager taskManager) + /// <exception cref="ArgumentNullException">taskManager</exception> + public ScheduledTaskService(ITaskManager taskManager, IServerConfigurationManager config) { if (taskManager == null) { @@ -103,6 +106,7 @@ namespace MediaBrowser.Api.ScheduledTasks } TaskManager = taskManager; + _config = config; } /// <summary> @@ -194,6 +198,20 @@ namespace MediaBrowser.Api.ScheduledTasks throw new ResourceNotFoundException("Task not found"); } + var hasKey = task.ScheduledTask as IHasKey; + if (hasKey != null) + { + if (string.Equals(hasKey.Key, "SystemUpdateTask", StringComparison.OrdinalIgnoreCase)) + { + // This is a hack for now just to get the update application function to work when auto-update is disabled + if (!_config.Configuration.EnableAutoUpdate) + { + _config.Configuration.EnableAutoUpdate = true; + _config.SaveConfiguration(); + } + } + } + TaskManager.Execute(task); } diff --git a/MediaBrowser.Api/UserService.cs b/MediaBrowser.Api/UserService.cs index 3996a03114..a35a1c3a23 100644 --- a/MediaBrowser.Api/UserService.cs +++ b/MediaBrowser.Api/UserService.cs @@ -415,23 +415,6 @@ namespace MediaBrowser.Api { var auth = AuthorizationContext.GetAuthorizationInfo(Request); - if (string.IsNullOrWhiteSpace(auth.Client)) - { - auth.Client = "Unknown app"; - } - if (string.IsNullOrWhiteSpace(auth.Device)) - { - auth.Device = "Unknown device"; - } - if (string.IsNullOrWhiteSpace(auth.Version)) - { - auth.Version = "Unknown version"; - } - if (string.IsNullOrWhiteSpace(auth.DeviceId)) - { - auth.DeviceId = "Unknown device id"; - } - var result = await _sessionMananger.AuthenticateNewSession(new AuthenticationRequest { App = auth.Client, diff --git a/MediaBrowser.Api/packages.config b/MediaBrowser.Api/packages.config index 83890e6975..ecb1109cad 100644 --- a/MediaBrowser.Api/packages.config +++ b/MediaBrowser.Api/packages.config @@ -1,6 +1,6 @@ <?xml version="1.0" encoding="utf-8"?> <packages> - <package id="CommonIO" version="1.0.0.7" targetFramework="net45" /> + <package id="CommonIO" version="1.0.0.8" targetFramework="net45" /> <package id="morelinq" version="1.4.0" targetFramework="net45" /> <package id="Patterns.Logging" version="1.0.0.2" targetFramework="net45" /> </packages>
\ No newline at end of file |
