support deleting and canceling live tv recordings and timers

This commit is contained in:
Luke Pulverenti 2013-11-29 11:58:24 -05:00
parent 4892fb4e95
commit 235b838fbe
26 changed files with 280 additions and 81 deletions

View File

@ -1,4 +1,5 @@
using System.Threading; using System.Threading;
using System.Threading.Tasks;
using MediaBrowser.Controller.LiveTv; using MediaBrowser.Controller.LiveTv;
using MediaBrowser.Model.LiveTv; using MediaBrowser.Model.LiveTv;
using MediaBrowser.Model.Querying; using MediaBrowser.Model.Querying;
@ -82,6 +83,22 @@ namespace MediaBrowser.Api.LiveTv
public string UserId { get; set; } public string UserId { get; set; }
} }
[Route("/LiveTv/Recordings/{Id}", "DELETE")]
[Api(Description = "Deletes a live tv recording")]
public class DeleteRecording : IReturnVoid
{
[ApiMember(Name = "Id", Description = "Recording Id", IsRequired = true, DataType = "string", ParameterType = "path", Verb = "GET")]
public string Id { get; set; }
}
[Route("/LiveTv/Timers/{Id}", "DELETE")]
[Api(Description = "Cancels a live tv timer")]
public class CancelTimer : IReturnVoid
{
[ApiMember(Name = "Id", Description = "Timer Id", IsRequired = true, DataType = "string", ParameterType = "path", Verb = "GET")]
public string Id { get; set; }
}
public class LiveTvService : BaseApiService public class LiveTvService : BaseApiService
{ {
private readonly ILiveTvManager _liveTvManager; private readonly ILiveTvManager _liveTvManager;
@ -176,5 +193,19 @@ namespace MediaBrowser.Api.LiveTv
return ToOptimizedResult(result); return ToOptimizedResult(result);
} }
public void Delete(DeleteRecording request)
{
var task = _liveTvManager.DeleteRecording(request.Id);
Task.WaitAll(task);
}
public void Delete(CancelTimer request)
{
var task = _liveTvManager.CancelTimer(request.Id);
Task.WaitAll(task);
}
} }
} }

View File

@ -31,7 +31,8 @@ namespace MediaBrowser.Api.ScheduledTasks
[Api(Description = "Gets scheduled tasks")] [Api(Description = "Gets scheduled tasks")]
public class GetScheduledTasks : IReturn<List<TaskInfo>> public class GetScheduledTasks : IReturn<List<TaskInfo>>
{ {
[ApiMember(Name = "IsHidden", Description = "Optional filter tasks that are hidden, or not.", IsRequired = false, DataType = "bool", ParameterType = "query", Verb = "GET")]
public bool? IsHidden { get; set; }
} }
/// <summary> /// <summary>
@ -112,10 +113,33 @@ namespace MediaBrowser.Api.ScheduledTasks
/// <returns>IEnumerable{TaskInfo}.</returns> /// <returns>IEnumerable{TaskInfo}.</returns>
public object Get(GetScheduledTasks request) public object Get(GetScheduledTasks request)
{ {
var result = TaskManager.ScheduledTasks.OrderBy(i => i.Name) IEnumerable<IScheduledTaskWorker> result = TaskManager.ScheduledTasks
.Select(ScheduledTaskHelpers.GetTaskInfo).ToList(); .OrderBy(i => i.Name);
return ToOptimizedResult(result); if (request.IsHidden.HasValue)
{
var val = request.IsHidden.Value;
result = result.Where(i =>
{
var isHidden = false;
var configurableTask = i.ScheduledTask as IConfigurableScheduledTask;
if (configurableTask != null)
{
isHidden = configurableTask.IsHidden;
}
return isHidden == val;
});
}
var infos = result
.Select(ScheduledTaskHelpers.GetTaskInfo)
.ToList();
return ToOptimizedResult(infos);
} }
/// <summary> /// <summary>

View File

@ -46,8 +46,10 @@ namespace MediaBrowser.Api.ScheduledTasks
/// <returns>Task{IEnumerable{TaskInfo}}.</returns> /// <returns>Task{IEnumerable{TaskInfo}}.</returns>
protected override Task<IEnumerable<TaskInfo>> GetDataToSend(object state) protected override Task<IEnumerable<TaskInfo>> GetDataToSend(object state)
{ {
return Task.FromResult(TaskManager.ScheduledTasks.OrderBy(i => i.Name) return Task.FromResult(TaskManager.ScheduledTasks
.Select(ScheduledTaskHelpers.GetTaskInfo)); .OrderBy(i => i.Name)
.Select(ScheduledTaskHelpers.GetTaskInfo)
.Where(i => !i.IsHidden));
} }
} }
} }

View File

@ -81,8 +81,11 @@ namespace MediaBrowser.Api
[ApiMember(Name = "Season", Description = "Optional filter by season number.", IsRequired = false, DataType = "string", ParameterType = "query", Verb = "GET")] [ApiMember(Name = "Season", Description = "Optional filter by season number.", IsRequired = false, DataType = "string", ParameterType = "query", Verb = "GET")]
public int? Season { get; set; } public int? Season { get; set; }
[ApiMember(Name = "ExcludeLocationTypes", Description = "Optional. If specified, results will be filtered based on LocationType. This allows multiple, comma delimeted.", IsRequired = false, DataType = "string", ParameterType = "query", Verb = "GET", AllowMultiple = true)] [ApiMember(Name = "IsMissing", Description = "Optional filter by items that are missing episodes or not.", IsRequired = false, DataType = "bool", ParameterType = "query", Verb = "GET")]
public string ExcludeLocationTypes { get; set; } public bool? IsMissing { get; set; }
[ApiMember(Name = "IsVirtualUnaired", Description = "Optional filter by items that are virtual unaired episodes or not.", IsRequired = false, DataType = "bool", ParameterType = "query", Verb = "GET")]
public bool? IsVirtualUnaired { get; set; }
} }
[Route("/Shows/{Id}/Seasons", "GET")] [Route("/Shows/{Id}/Seasons", "GET")]
@ -106,11 +109,14 @@ namespace MediaBrowser.Api
[ApiMember(Name = "Id", Description = "The series id", IsRequired = true, DataType = "string", ParameterType = "query", Verb = "GET")] [ApiMember(Name = "Id", Description = "The series id", IsRequired = true, DataType = "string", ParameterType = "query", Verb = "GET")]
public Guid Id { get; set; } public Guid Id { get; set; }
[ApiMember(Name = "ExcludeLocationTypes", Description = "Optional. If specified, results will be filtered based on LocationType. This allows multiple, comma delimeted.", IsRequired = false, DataType = "string", ParameterType = "query", Verb = "GET", AllowMultiple = true)]
public string ExcludeLocationTypes { get; set; }
[ApiMember(Name = "IsSpecialSeason", Description = "Optional. Filter by special season.", IsRequired = false, DataType = "bool", ParameterType = "query", Verb = "GET")] [ApiMember(Name = "IsSpecialSeason", Description = "Optional. Filter by special season.", IsRequired = false, DataType = "bool", ParameterType = "query", Verb = "GET")]
public bool? IsSpecialSeason { get; set; } public bool? IsSpecialSeason { get; set; }
[ApiMember(Name = "IsMissing", Description = "Optional filter by items that are missing episodes or not.", IsRequired = false, DataType = "bool", ParameterType = "query", Verb = "GET")]
public bool? IsMissing { get; set; }
[ApiMember(Name = "IsVirtualUnaired", Description = "Optional filter by items that are virtual unaired episodes or not.", IsRequired = false, DataType = "bool", ParameterType = "query", Verb = "GET")]
public bool? IsVirtualUnaired { get; set; }
} }
/// <summary> /// <summary>
@ -380,12 +386,7 @@ namespace MediaBrowser.Api
} }
} }
// ExcludeLocationTypes seasons = FilterVirtualSeasons(request, seasons);
if (!string.IsNullOrEmpty(request.ExcludeLocationTypes))
{
var vals = request.ExcludeLocationTypes.Split(',');
seasons = seasons.Where(f => !vals.Contains(f.LocationType.ToString(), StringComparer.OrdinalIgnoreCase));
}
seasons = _libraryManager.Sort(seasons, user, new[] { sortOrder }, SortOrder.Ascending) seasons = _libraryManager.Sort(seasons, user, new[] { sortOrder }, SortOrder.Ascending)
.Cast<Season>(); .Cast<Season>();
@ -400,6 +401,34 @@ namespace MediaBrowser.Api
}; };
} }
private IEnumerable<Season> FilterVirtualSeasons(GetSeasons request, IEnumerable<Season> items)
{
if (request.IsMissing.HasValue && request.IsVirtualUnaired.HasValue)
{
var isMissing = request.IsMissing.Value;
var isVirtualUnaired = request.IsVirtualUnaired.Value;
if (!isMissing && !isVirtualUnaired)
{
return items.Where(i => !i.IsMissingOrVirtualUnaired);
}
}
if (request.IsMissing.HasValue)
{
var val = request.IsMissing.Value;
items = items.Where(i => i.IsMissingSeason == val);
}
if (request.IsVirtualUnaired.HasValue)
{
var val = request.IsVirtualUnaired.Value;
items = items.Where(i => i.IsVirtualUnaired == val);
}
return items;
}
public object Get(GetEpisodes request) public object Get(GetEpisodes request)
{ {
var user = _userManager.GetUserById(request.UserId); var user = _userManager.GetUserById(request.UserId);
@ -431,11 +460,16 @@ namespace MediaBrowser.Api
episodes = episodes.Where(i => !i.IsVirtualUnaired); episodes = episodes.Where(i => !i.IsVirtualUnaired);
} }
// ExcludeLocationTypes if (request.IsMissing.HasValue)
if (!string.IsNullOrEmpty(request.ExcludeLocationTypes))
{ {
var vals = request.ExcludeLocationTypes.Split(','); var val = request.IsMissing.Value;
episodes = episodes.Where(f => !vals.Contains(f.LocationType.ToString(), StringComparer.OrdinalIgnoreCase)); episodes = episodes.Where(i => i.IsMissingEpisode == val);
}
if (request.IsVirtualUnaired.HasValue)
{
var val = request.IsVirtualUnaired.Value;
episodes = episodes.Where(i => i.IsVirtualUnaired == val);
} }
episodes = _libraryManager.Sort(episodes, user, new[] { sortOrder }, SortOrder.Ascending) episodes = _libraryManager.Sort(episodes, user, new[] { sortOrder }, SortOrder.Ascending)

View File

@ -218,7 +218,7 @@ namespace MediaBrowser.Common.Implementations
try try
{ {
// Increase the max http request limit // Increase the max http request limit
ServicePointManager.DefaultConnectionLimit = Math.Max(48, ServicePointManager.DefaultConnectionLimit); ServicePointManager.DefaultConnectionLimit = Math.Max(96, ServicePointManager.DefaultConnectionLimit);
} }
catch (Exception ex) catch (Exception ex)
{ {

View File

@ -1,4 +1,5 @@
using MediaBrowser.Common.Configuration; using System.Reflection;
using MediaBrowser.Common.Configuration;
using MediaBrowser.Common.IO; using MediaBrowser.Common.IO;
using MediaBrowser.Common.Net; using MediaBrowser.Common.Net;
using MediaBrowser.Model.Logging; using MediaBrowser.Model.Logging;

View File

@ -29,7 +29,6 @@ namespace MediaBrowser.Common.Implementations.ScheduledTasks.Tasks
/// <summary> /// <summary>
/// Initializes a new instance of the <see cref="DeleteCacheFileTask" /> class. /// Initializes a new instance of the <see cref="DeleteCacheFileTask" /> class.
/// </summary> /// </summary>
/// <param name="appPaths">The app paths.</param>
public DeleteCacheFileTask(IApplicationPaths appPaths, ILogger logger, IFileSystem fileSystem) public DeleteCacheFileTask(IApplicationPaths appPaths, ILogger logger, IFileSystem fileSystem)
{ {
ApplicationPaths = appPaths; ApplicationPaths = appPaths;

View File

@ -42,4 +42,9 @@ namespace MediaBrowser.Common.ScheduledTasks
/// <returns>IEnumerable{BaseTaskTrigger}.</returns> /// <returns>IEnumerable{BaseTaskTrigger}.</returns>
IEnumerable<ITaskTrigger> GetDefaultTriggers(); IEnumerable<ITaskTrigger> GetDefaultTriggers();
} }
public interface IConfigurableScheduledTask
{
bool IsHidden { get; }
}
} }

View File

@ -16,6 +16,15 @@ namespace MediaBrowser.Common.ScheduledTasks
/// <returns>TaskInfo.</returns> /// <returns>TaskInfo.</returns>
public static TaskInfo GetTaskInfo(IScheduledTaskWorker task) public static TaskInfo GetTaskInfo(IScheduledTaskWorker task)
{ {
var isHidden = false;
var configurableTask = task.ScheduledTask as IConfigurableScheduledTask;
if (configurableTask != null)
{
isHidden = configurableTask.IsHidden;
}
return new TaskInfo return new TaskInfo
{ {
Name = task.Name, Name = task.Name,
@ -25,7 +34,8 @@ namespace MediaBrowser.Common.ScheduledTasks
LastExecutionResult = task.LastExecutionResult, LastExecutionResult = task.LastExecutionResult,
Triggers = task.Triggers.Select(GetTriggerInfo).ToList(), Triggers = task.Triggers.Select(GetTriggerInfo).ToList(),
Description = task.Description, Description = task.Description,
Category = task.Category Category = task.Category,
IsHidden = isHidden
}; };
} }

View File

@ -24,6 +24,20 @@ namespace MediaBrowser.Controller.LiveTv
/// <returns>Task.</returns> /// <returns>Task.</returns>
Task ScheduleRecording(string programId); Task ScheduleRecording(string programId);
/// <summary>
/// Deletes the recording.
/// </summary>
/// <param name="id">The identifier.</param>
/// <returns>Task.</returns>
Task DeleteRecording(string id);
/// <summary>
/// Cancels the timer.
/// </summary>
/// <param name="id">The identifier.</param>
/// <returns>Task.</returns>
Task CancelTimer(string id);
/// <summary> /// <summary>
/// Adds the parts. /// Adds the parts.
/// </summary> /// </summary>

View File

@ -47,14 +47,6 @@ namespace MediaBrowser.Controller.LiveTv
/// <returns>Task.</returns> /// <returns>Task.</returns>
Task CreateTimerAsync(TimerInfo info, CancellationToken cancellationToken); Task CreateTimerAsync(TimerInfo info, CancellationToken cancellationToken);
/// <summary>
/// Updates the timer asynchronous.
/// </summary>
/// <param name="info">The information.</param>
/// <param name="cancellationToken">The cancellation token.</param>
/// <returns>Task.</returns>
Task UpdateTimerAsync(TimerInfo info, CancellationToken cancellationToken);
/// <summary> /// <summary>
/// Gets the channel image asynchronous. /// Gets the channel image asynchronous.
/// </summary> /// </summary>

View File

@ -40,6 +40,12 @@ namespace MediaBrowser.Controller.LiveTv
/// </summary> /// </summary>
public DateTime EndDate { get; set; } public DateTime EndDate { get; set; }
/// <summary>
/// Gets or sets the program identifier.
/// </summary>
/// <value>The program identifier.</value>
public string ProgramId { get; set; }
/// <summary> /// <summary>
/// Gets or sets the status. /// Gets or sets the status.
/// </summary> /// </summary>

View File

@ -1,6 +1,5 @@
using MediaBrowser.Model.LiveTv; using MediaBrowser.Model.LiveTv;
using System; using System;
using System.Collections.Generic;
namespace MediaBrowser.Controller.LiveTv namespace MediaBrowser.Controller.LiveTv
{ {
@ -21,6 +20,12 @@ namespace MediaBrowser.Controller.LiveTv
/// </summary> /// </summary>
public string ChannelName { get; set; } public string ChannelName { get; set; }
/// <summary>
/// Gets or sets the program identifier.
/// </summary>
/// <value>The program identifier.</value>
public string ProgramId { get; set; }
/// <summary> /// <summary>
/// Name of the recording. /// Name of the recording.
/// </summary> /// </summary>
@ -52,16 +57,5 @@ namespace MediaBrowser.Controller.LiveTv
/// </summary> /// </summary>
/// <value><c>true</c> if this instance is recurring; otherwise, <c>false</c>.</value> /// <value><c>true</c> if this instance is recurring; otherwise, <c>false</c>.</value>
public bool IsRecurring { get; set; } public bool IsRecurring { get; set; }
/// <summary>
/// Gets or sets the recurring days.
/// </summary>
/// <value>The recurring days.</value>
public List<DayOfWeek> RecurringDays { get; set; }
public TimerInfo()
{
RecurringDays = new List<DayOfWeek>();
}
} }
} }

View File

@ -10,4 +10,11 @@ namespace MediaBrowser.Model.LiveTv
Conflicted, Conflicted,
Deleted Deleted
} }
public enum RecurrenceType
{
Manual,
NewProgramEvents,
AllProgramEvents
}
} }

View File

@ -1,11 +1,10 @@
using System; using System;
using System.Collections.Generic;
namespace MediaBrowser.Model.LiveTv namespace MediaBrowser.Model.LiveTv
{ {
public class TimerInfoDto public class TimerInfoDto
{ {
/// <summary> /// <summary>
/// Id of the recording. /// Id of the recording.
/// </summary> /// </summary>
public string Id { get; set; } public string Id { get; set; }
@ -15,7 +14,7 @@ namespace MediaBrowser.Model.LiveTv
/// </summary> /// </summary>
/// <value>The external identifier.</value> /// <value>The external identifier.</value>
public string ExternalId { get; set; } public string ExternalId { get; set; }
/// <summary> /// <summary>
/// ChannelId of the recording. /// ChannelId of the recording.
/// </summary> /// </summary>
@ -26,6 +25,12 @@ namespace MediaBrowser.Model.LiveTv
/// </summary> /// </summary>
public string ChannelName { get; set; } public string ChannelName { get; set; }
/// <summary>
/// Gets or sets the program identifier.
/// </summary>
/// <value>The program identifier.</value>
public string ProgramId { get; set; }
/// <summary> /// <summary>
/// Name of the recording. /// Name of the recording.
/// </summary> /// </summary>
@ -57,16 +62,5 @@ namespace MediaBrowser.Model.LiveTv
/// </summary> /// </summary>
/// <value><c>true</c> if this instance is recurring; otherwise, <c>false</c>.</value> /// <value><c>true</c> if this instance is recurring; otherwise, <c>false</c>.</value>
public bool IsRecurring { get; set; } public bool IsRecurring { get; set; }
}
/// <summary>
/// Gets or sets the recurring days.
/// </summary>
/// <value>The recurring days.</value>
public List<DayOfWeek> RecurringDays { get; set; }
public TimerInfoDto()
{
RecurringDays = new List<DayOfWeek>();
}
}
} }

View File

@ -1,5 +1,4 @@
using MediaBrowser.Model.Entities; 
namespace MediaBrowser.Model.Querying namespace MediaBrowser.Model.Querying
{ {
public class EpisodeQuery public class EpisodeQuery
@ -8,7 +7,9 @@ namespace MediaBrowser.Model.Querying
public string SeriesId { get; set; } public string SeriesId { get; set; }
public LocationType[] ExcludeLocationTypes { get; set; } public bool? IsMissing { get; set; }
public bool? IsVirtualUnaired { get; set; }
public int? SeasonNumber { get; set; } public int? SeasonNumber { get; set; }
@ -17,7 +18,6 @@ namespace MediaBrowser.Model.Querying
public EpisodeQuery() public EpisodeQuery()
{ {
Fields = new ItemFields[] { }; Fields = new ItemFields[] { };
ExcludeLocationTypes = new LocationType[] { };
} }
} }
@ -27,7 +27,9 @@ namespace MediaBrowser.Model.Querying
public string SeriesId { get; set; } public string SeriesId { get; set; }
public LocationType[] ExcludeLocationTypes { get; set; } public bool? IsMissing { get; set; }
public bool? IsVirtualUnaired { get; set; }
public ItemFields[] Fields { get; set; } public ItemFields[] Fields { get; set; }
@ -36,7 +38,6 @@ namespace MediaBrowser.Model.Querying
public SeasonQuery() public SeasonQuery()
{ {
Fields = new ItemFields[] { }; Fields = new ItemFields[] { };
ExcludeLocationTypes = new LocationType[] { };
} }
} }
} }

View File

@ -56,6 +56,12 @@ namespace MediaBrowser.Model.Tasks
/// <value>The category.</value> /// <value>The category.</value>
public string Category { get; set; } public string Category { get; set; }
/// <summary>
/// Gets or sets a value indicating whether this instance is hidden.
/// </summary>
/// <value><c>true</c> if this instance is hidden; otherwise, <c>false</c>.</value>
public bool IsHidden { get; set; }
/// <summary> /// <summary>
/// Initializes a new instance of the <see cref="TaskInfo"/> class. /// Initializes a new instance of the <see cref="TaskInfo"/> class.
/// </summary> /// </summary>

View File

@ -397,6 +397,11 @@ namespace MediaBrowser.Server.Implementations.LiveTv
Status = info.Status Status = info.Status
}; };
if (!string.IsNullOrEmpty(info.ProgramId))
{
dto.ProgramId = GetInternalProgramIdId(service.Name, info.ProgramId).ToString("N");
}
return dto; return dto;
} }
@ -503,13 +508,61 @@ namespace MediaBrowser.Server.Implementations.LiveTv
ExternalId = info.Id, ExternalId = info.Id,
ChannelId = GetInternalChannelId(service.Name, info.ChannelId).ToString("N"), ChannelId = GetInternalChannelId(service.Name, info.ChannelId).ToString("N"),
Status = info.Status, Status = info.Status,
IsRecurring = info.IsRecurring, IsRecurring = info.IsRecurring
RecurringDays = info.RecurringDays
}; };
if (!string.IsNullOrEmpty(info.ProgramId))
{
dto.ProgramId = GetInternalProgramIdId(service.Name, info.ProgramId).ToString("N");
}
return dto; return dto;
} }
public async Task DeleteRecording(string recordingId)
{
var recordings = await GetRecordings(new RecordingQuery
{
}, CancellationToken.None).ConfigureAwait(false);
var recording = recordings.Items
.FirstOrDefault(i => string.Equals(recordingId, i.Id, StringComparison.OrdinalIgnoreCase));
if (recording == null)
{
throw new ResourceNotFoundException(string.Format("Recording with Id {0} not found", recordingId));
}
var channel = GetChannel(recording.ChannelId);
var service = GetServices(channel.ServiceName, null)
.First();
await service.DeleteRecordingAsync(recording.ExternalId, CancellationToken.None).ConfigureAwait(false);
}
public async Task CancelTimer(string id)
{
var timers = await GetTimers(new TimerQuery
{
}, CancellationToken.None).ConfigureAwait(false);
var timer = timers.Items
.FirstOrDefault(i => string.Equals(id, i.Id, StringComparison.OrdinalIgnoreCase));
if (timer == null)
{
throw new ResourceNotFoundException(string.Format("Timer with Id {0} not found", id));
}
var channel = GetChannel(timer.ChannelId);
var service = GetServices(channel.ServiceName, null)
.First();
await service.CancelTimerAsync(timer.ExternalId, CancellationToken.None).ConfigureAwait(false);
}
} }
} }

View File

@ -7,7 +7,7 @@ using System.Threading.Tasks;
namespace MediaBrowser.Server.Implementations.LiveTv namespace MediaBrowser.Server.Implementations.LiveTv
{ {
class RefreshChannelsScheduledTask : IScheduledTask class RefreshChannelsScheduledTask : IScheduledTask, IConfigurableScheduledTask
{ {
private readonly ILiveTvManager _liveTvManager; private readonly ILiveTvManager _liveTvManager;
@ -33,7 +33,7 @@ namespace MediaBrowser.Server.Implementations.LiveTv
public Task Execute(System.Threading.CancellationToken cancellationToken, IProgress<double> progress) public Task Execute(System.Threading.CancellationToken cancellationToken, IProgress<double> progress)
{ {
var manager = (LiveTvManager) _liveTvManager; var manager = (LiveTvManager)_liveTvManager;
return manager.RefreshChannels(progress, cancellationToken); return manager.RefreshChannels(progress, cancellationToken);
} }
@ -50,5 +50,10 @@ namespace MediaBrowser.Server.Implementations.LiveTv
new IntervalTrigger{ Interval = TimeSpan.FromHours(2)} new IntervalTrigger{ Interval = TimeSpan.FromHours(2)}
}; };
} }
public bool IsHidden
{
get { return _liveTvManager.Services.Count == 0; }
}
} }
} }

View File

@ -17,14 +17,19 @@ namespace MediaBrowser.ServerApplication.Native
/// <returns>HttpClient.</returns> /// <returns>HttpClient.</returns>
public static HttpClient GetHttpClient(bool enableHttpCompression) public static HttpClient GetHttpClient(bool enableHttpCompression)
{ {
return new HttpClient(new WebRequestHandler var client = new HttpClient(new WebRequestHandler
{ {
CachePolicy = new RequestCachePolicy(RequestCacheLevel.Revalidate), CachePolicy = new RequestCachePolicy(RequestCacheLevel.Revalidate),
AutomaticDecompression = enableHttpCompression ? DecompressionMethods.Deflate : DecompressionMethods.None AutomaticDecompression = enableHttpCompression ? DecompressionMethods.Deflate : DecompressionMethods.None
}) })
{ {
Timeout = TimeSpan.FromSeconds(20) Timeout = TimeSpan.FromSeconds(20)
}; };
client.DefaultRequestHeaders.Add("Connection", "Keep-Alive");
return client;
} }
} }
} }

View File

@ -506,6 +506,20 @@ MediaBrowser.ApiClient = function ($, navigator, JSON, WebSocket, setTimeout, wi
}); });
}; };
self.createLiveTvTimer = function (options) {
if (!options) {
throw new Error("null options");
}
var url = self.getUrl("LiveTv/Timers", options);
return self.ajax({
type: "POST",
url: url
});
};
/** /**
* Gets the current server status * Gets the current server status
*/ */
@ -1019,9 +1033,11 @@ MediaBrowser.ApiClient = function ($, navigator, JSON, WebSocket, setTimeout, wi
/** /**
* Gets the server's scheduled tasks * Gets the server's scheduled tasks
*/ */
self.getScheduledTasks = function () { self.getScheduledTasks = function (options) {
var url = self.getUrl("ScheduledTasks"); options = options || {};
var url = self.getUrl("ScheduledTasks", options);
return self.ajax({ return self.ajax({
type: "GET", type: "GET",

View File

@ -284,10 +284,10 @@
<Content Include="dashboard-ui\css\images\userdata\thumbs_up_on.png"> <Content Include="dashboard-ui\css\images\userdata\thumbs_up_on.png">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory> <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content> </Content>
<Content Include="dashboard-ui\css\images\userdata\playedoff.png"> <Content Include="dashboard-ui\css\images\userdata\checkedoff.png">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory> <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content> </Content>
<Content Include="dashboard-ui\css\images\userdata\playedon.png"> <Content Include="dashboard-ui\css\images\userdata\checkedon.png">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory> <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content> </Content>
<Content Include="dashboard-ui\css\librarybrowser.css"> <Content Include="dashboard-ui\css\librarybrowser.css">

View File

@ -1,6 +1,6 @@
<?xml version="1.0" encoding="utf-8"?> <?xml version="1.0" encoding="utf-8"?>
<packages> <packages>
<package id="MediaBrowser.ApiClient.Javascript" version="3.0.201" targetFramework="net45" /> <package id="MediaBrowser.ApiClient.Javascript" version="3.0.203" targetFramework="net45" />
<package id="ServiceStack.Common" version="3.9.62" targetFramework="net45" /> <package id="ServiceStack.Common" version="3.9.62" targetFramework="net45" />
<package id="ServiceStack.Text" version="3.9.62" targetFramework="net45" /> <package id="ServiceStack.Text" version="3.9.62" targetFramework="net45" />
</packages> </packages>

View File

@ -2,7 +2,7 @@
<package xmlns="http://schemas.microsoft.com/packaging/2011/08/nuspec.xsd"> <package xmlns="http://schemas.microsoft.com/packaging/2011/08/nuspec.xsd">
<metadata> <metadata>
<id>MediaBrowser.Common.Internal</id> <id>MediaBrowser.Common.Internal</id>
<version>3.0.252</version> <version>3.0.253</version>
<title>MediaBrowser.Common.Internal</title> <title>MediaBrowser.Common.Internal</title>
<authors>Luke</authors> <authors>Luke</authors>
<owners>ebr,Luke,scottisafool</owners> <owners>ebr,Luke,scottisafool</owners>
@ -12,7 +12,7 @@
<description>Contains common components shared by Media Browser Theater and Media Browser Server. Not intended for plugin developer consumption.</description> <description>Contains common components shared by Media Browser Theater and Media Browser Server. Not intended for plugin developer consumption.</description>
<copyright>Copyright © Media Browser 2013</copyright> <copyright>Copyright © Media Browser 2013</copyright>
<dependencies> <dependencies>
<dependency id="MediaBrowser.Common" version="3.0.252" /> <dependency id="MediaBrowser.Common" version="3.0.253" />
<dependency id="NLog" version="2.1.0" /> <dependency id="NLog" version="2.1.0" />
<dependency id="ServiceStack.Text" version="3.9.58" /> <dependency id="ServiceStack.Text" version="3.9.58" />
<dependency id="SimpleInjector" version="2.3.6" /> <dependency id="SimpleInjector" version="2.3.6" />

View File

@ -2,7 +2,7 @@
<package xmlns="http://schemas.microsoft.com/packaging/2011/08/nuspec.xsd"> <package xmlns="http://schemas.microsoft.com/packaging/2011/08/nuspec.xsd">
<metadata> <metadata>
<id>MediaBrowser.Common</id> <id>MediaBrowser.Common</id>
<version>3.0.252</version> <version>3.0.253</version>
<title>MediaBrowser.Common</title> <title>MediaBrowser.Common</title>
<authors>Media Browser Team</authors> <authors>Media Browser Team</authors>
<owners>ebr,Luke,scottisafool</owners> <owners>ebr,Luke,scottisafool</owners>

View File

@ -2,7 +2,7 @@
<package xmlns="http://schemas.microsoft.com/packaging/2010/07/nuspec.xsd"> <package xmlns="http://schemas.microsoft.com/packaging/2010/07/nuspec.xsd">
<metadata> <metadata>
<id>MediaBrowser.Server.Core</id> <id>MediaBrowser.Server.Core</id>
<version>3.0.252</version> <version>3.0.253</version>
<title>Media Browser.Server.Core</title> <title>Media Browser.Server.Core</title>
<authors>Media Browser Team</authors> <authors>Media Browser Team</authors>
<owners>ebr,Luke,scottisafool</owners> <owners>ebr,Luke,scottisafool</owners>
@ -12,7 +12,7 @@
<description>Contains core components required to build plugins for Media Browser Server.</description> <description>Contains core components required to build plugins for Media Browser Server.</description>
<copyright>Copyright © Media Browser 2013</copyright> <copyright>Copyright © Media Browser 2013</copyright>
<dependencies> <dependencies>
<dependency id="MediaBrowser.Common" version="3.0.252" /> <dependency id="MediaBrowser.Common" version="3.0.253" />
</dependencies> </dependencies>
</metadata> </metadata>
<files> <files>