aboutsummaryrefslogtreecommitdiff
path: root/MediaBrowser.Api
diff options
context:
space:
mode:
Diffstat (limited to 'MediaBrowser.Api')
-rw-r--r--MediaBrowser.Api/ConnectService.cs55
-rw-r--r--MediaBrowser.Api/Images/ImageRequest.cs5
-rw-r--r--MediaBrowser.Api/Images/ImageService.cs1
-rw-r--r--MediaBrowser.Api/Library/FileOrganizationService.cs39
-rw-r--r--MediaBrowser.Api/MediaBrowser.Api.csproj3
-rw-r--r--MediaBrowser.Api/PinLoginService.cs202
-rw-r--r--MediaBrowser.Api/Playback/BaseStreamingService.cs39
-rw-r--r--MediaBrowser.Api/Playback/Progressive/VideoService.cs29
-rw-r--r--MediaBrowser.Api/Playback/StreamRequest.cs3
-rw-r--r--MediaBrowser.Api/ScheduledTasks/ScheduledTaskService.cs22
-rw-r--r--MediaBrowser.Api/UserService.cs17
-rw-r--r--MediaBrowser.Api/packages.config2
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