commit
b474b56c27
|
@ -567,7 +567,7 @@ namespace MediaBrowser.Api
|
|||
{
|
||||
try
|
||||
{
|
||||
await _mediaSourceManager.CloseLiveStream(job.LiveStreamId, CancellationToken.None).ConfigureAwait(false);
|
||||
await _mediaSourceManager.CloseLiveStream(job.LiveStreamId).ConfigureAwait(false);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
|
@ -789,12 +789,12 @@ namespace MediaBrowser.Api
|
|||
{
|
||||
if (KillTimer == null)
|
||||
{
|
||||
Logger.Debug("Starting kill timer at {0}ms. JobId {1} PlaySessionId {2}", intervalMs, Id, PlaySessionId);
|
||||
//Logger.Debug("Starting kill timer at {0}ms. JobId {1} PlaySessionId {2}", intervalMs, Id, PlaySessionId);
|
||||
KillTimer = new Timer(callback, this, intervalMs, Timeout.Infinite);
|
||||
}
|
||||
else
|
||||
{
|
||||
Logger.Debug("Changing kill timer to {0}ms. JobId {1} PlaySessionId {2}", intervalMs, Id, PlaySessionId);
|
||||
//Logger.Debug("Changing kill timer to {0}ms. JobId {1} PlaySessionId {2}", intervalMs, Id, PlaySessionId);
|
||||
KillTimer.Change(intervalMs, Timeout.Infinite);
|
||||
}
|
||||
}
|
||||
|
@ -813,7 +813,7 @@ namespace MediaBrowser.Api
|
|||
{
|
||||
var intervalMs = PingTimeout;
|
||||
|
||||
Logger.Debug("Changing kill timer to {0}ms. JobId {1} PlaySessionId {2}", intervalMs, Id, PlaySessionId);
|
||||
//Logger.Debug("Changing kill timer to {0}ms. JobId {1} PlaySessionId {2}", intervalMs, Id, PlaySessionId);
|
||||
KillTimer.Change(intervalMs, Timeout.Infinite);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -48,6 +48,21 @@ namespace MediaBrowser.Api.LiveTv
|
|||
[ApiMember(Name = "StartIndex", Description = "Optional. The record index to start at. All items with a lower index will be dropped from the results.", IsRequired = false, DataType = "int", ParameterType = "query", Verb = "GET")]
|
||||
public int? StartIndex { get; set; }
|
||||
|
||||
[ApiMember(Name = "IsMovie", Description = "Optional filter for movies.", IsRequired = false, DataType = "bool", ParameterType = "query", Verb = "GET,POST")]
|
||||
public bool? IsMovie { get; set; }
|
||||
|
||||
[ApiMember(Name = "IsSeries", Description = "Optional filter for movies.", IsRequired = false, DataType = "bool", ParameterType = "query", Verb = "GET,POST")]
|
||||
public bool? IsSeries { get; set; }
|
||||
|
||||
[ApiMember(Name = "IsNews", Description = "Optional filter for news.", IsRequired = false, DataType = "bool", ParameterType = "query", Verb = "GET,POST")]
|
||||
public bool? IsNews { get; set; }
|
||||
|
||||
[ApiMember(Name = "IsKids", Description = "Optional filter for kids.", IsRequired = false, DataType = "bool", ParameterType = "query", Verb = "GET,POST")]
|
||||
public bool? IsKids { get; set; }
|
||||
|
||||
[ApiMember(Name = "IsSports", Description = "Optional filter for sports.", IsRequired = false, DataType = "bool", ParameterType = "query", Verb = "GET,POST")]
|
||||
public bool? IsSports { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// The maximum number of items to return
|
||||
/// </summary>
|
||||
|
@ -163,6 +178,7 @@ namespace MediaBrowser.Api.LiveTv
|
|||
public bool? IsSeries { get; set; }
|
||||
public bool? IsKids { get; set; }
|
||||
public bool? IsSports { get; set; }
|
||||
public bool? IsNews { get; set; }
|
||||
|
||||
public GetRecordings()
|
||||
{
|
||||
|
@ -309,6 +325,12 @@ namespace MediaBrowser.Api.LiveTv
|
|||
[ApiMember(Name = "IsMovie", Description = "Optional filter for movies.", IsRequired = false, DataType = "bool", ParameterType = "query", Verb = "GET,POST")]
|
||||
public bool? IsMovie { get; set; }
|
||||
|
||||
[ApiMember(Name = "IsSeries", Description = "Optional filter for movies.", IsRequired = false, DataType = "bool", ParameterType = "query", Verb = "GET,POST")]
|
||||
public bool? IsSeries { get; set; }
|
||||
|
||||
[ApiMember(Name = "IsNews", Description = "Optional filter for news.", IsRequired = false, DataType = "bool", ParameterType = "query", Verb = "GET,POST")]
|
||||
public bool? IsNews { get; set; }
|
||||
|
||||
[ApiMember(Name = "IsKids", Description = "Optional filter for kids.", IsRequired = false, DataType = "bool", ParameterType = "query", Verb = "GET,POST")]
|
||||
public bool? IsKids { get; set; }
|
||||
|
||||
|
@ -380,15 +402,21 @@ namespace MediaBrowser.Api.LiveTv
|
|||
[ApiMember(Name = "HasAired", Description = "Optional. Filter by programs that have completed airing, or not.", IsRequired = false, DataType = "bool", ParameterType = "query", Verb = "GET")]
|
||||
public bool? HasAired { get; set; }
|
||||
|
||||
[ApiMember(Name = "IsSports", Description = "Optional filter for sports.", IsRequired = false, DataType = "bool", ParameterType = "query", Verb = "GET,POST")]
|
||||
public bool? IsSports { get; set; }
|
||||
[ApiMember(Name = "IsSeries", Description = "Optional filter for movies.", IsRequired = false, DataType = "bool", ParameterType = "query", Verb = "GET,POST")]
|
||||
public bool? IsSeries { get; set; }
|
||||
|
||||
[ApiMember(Name = "IsMovie", Description = "Optional filter for movies.", IsRequired = false, DataType = "bool", ParameterType = "query", Verb = "GET")]
|
||||
[ApiMember(Name = "IsMovie", Description = "Optional filter for movies.", IsRequired = false, DataType = "bool", ParameterType = "query", Verb = "GET,POST")]
|
||||
public bool? IsMovie { get; set; }
|
||||
|
||||
[ApiMember(Name = "IsKids", Description = "Optional filter for kids.", IsRequired = false, DataType = "bool", ParameterType = "query", Verb = "GET")]
|
||||
[ApiMember(Name = "IsNews", Description = "Optional filter for news.", IsRequired = false, DataType = "bool", ParameterType = "query", Verb = "GET,POST")]
|
||||
public bool? IsNews { get; set; }
|
||||
|
||||
[ApiMember(Name = "IsKids", Description = "Optional filter for kids.", IsRequired = false, DataType = "bool", ParameterType = "query", Verb = "GET,POST")]
|
||||
public bool? IsKids { get; set; }
|
||||
|
||||
[ApiMember(Name = "IsSports", Description = "Optional filter for sports.", IsRequired = false, DataType = "bool", ParameterType = "query", Verb = "GET,POST")]
|
||||
public bool? IsSports { get; set; }
|
||||
|
||||
[ApiMember(Name = "EnableImages", Description = "Optional, include image information in output", IsRequired = false, DataType = "boolean", ParameterType = "query", Verb = "GET")]
|
||||
public bool? EnableImages { get; set; }
|
||||
|
||||
|
@ -815,6 +843,11 @@ namespace MediaBrowser.Api.LiveTv
|
|||
IsLiked = request.IsLiked,
|
||||
IsDisliked = request.IsDisliked,
|
||||
EnableFavoriteSorting = request.EnableFavoriteSorting,
|
||||
IsMovie = request.IsMovie,
|
||||
IsSeries = request.IsSeries,
|
||||
IsNews = request.IsNews,
|
||||
IsKids = request.IsKids,
|
||||
IsSports = request.IsSports,
|
||||
AddCurrentProgram = request.AddCurrentProgram
|
||||
|
||||
}, CancellationToken.None).ConfigureAwait(false);
|
||||
|
@ -897,7 +930,9 @@ namespace MediaBrowser.Api.LiveTv
|
|||
query.Limit = request.Limit;
|
||||
query.SortBy = (request.SortBy ?? String.Empty).Split(new[] { ',' }, StringSplitOptions.RemoveEmptyEntries);
|
||||
query.SortOrder = request.SortOrder;
|
||||
query.IsNews = request.IsNews;
|
||||
query.IsMovie = request.IsMovie;
|
||||
query.IsSeries = request.IsSeries;
|
||||
query.IsKids = request.IsKids;
|
||||
query.IsSports = request.IsSports;
|
||||
query.Genres = (request.Genres ?? String.Empty).Split(new[] { ',' }, StringSplitOptions.RemoveEmptyEntries);
|
||||
|
@ -915,8 +950,10 @@ namespace MediaBrowser.Api.LiveTv
|
|||
IsAiring = request.IsAiring,
|
||||
Limit = request.Limit,
|
||||
HasAired = request.HasAired,
|
||||
IsSeries = request.IsSeries,
|
||||
IsMovie = request.IsMovie,
|
||||
IsKids = request.IsKids,
|
||||
IsNews = request.IsNews,
|
||||
IsSports = request.IsSports,
|
||||
EnableTotalRecordCount = request.EnableTotalRecordCount
|
||||
};
|
||||
|
@ -948,6 +985,7 @@ namespace MediaBrowser.Api.LiveTv
|
|||
IsInProgress = request.IsInProgress,
|
||||
EnableTotalRecordCount = request.EnableTotalRecordCount,
|
||||
IsMovie = request.IsMovie,
|
||||
IsNews = request.IsNews,
|
||||
IsSeries = request.IsSeries,
|
||||
IsKids = request.IsKids,
|
||||
IsSports = request.IsSports
|
||||
|
|
|
@ -1861,14 +1861,14 @@ namespace MediaBrowser.Api.Playback
|
|||
MediaSourceInfo mediaSource = null;
|
||||
if (string.IsNullOrWhiteSpace(request.LiveStreamId))
|
||||
{
|
||||
//TranscodingJob currentJob = !string.IsNullOrWhiteSpace(request.PlaySessionId) ?
|
||||
// ApiEntryPoint.Instance.GetTranscodingJob(request.PlaySessionId)
|
||||
// : null;
|
||||
TranscodingJob currentJob = !string.IsNullOrWhiteSpace(request.PlaySessionId) ?
|
||||
ApiEntryPoint.Instance.GetTranscodingJob(request.PlaySessionId)
|
||||
: null;
|
||||
|
||||
//if (currentJob != null)
|
||||
//{
|
||||
// mediaSource = currentJob.MediaSource;
|
||||
//}
|
||||
if (currentJob != null)
|
||||
{
|
||||
mediaSource = currentJob.MediaSource;
|
||||
}
|
||||
|
||||
if (mediaSource == null)
|
||||
{
|
||||
|
|
|
@ -140,7 +140,7 @@ namespace MediaBrowser.Api.Playback
|
|||
|
||||
public void Post(CloseMediaSource request)
|
||||
{
|
||||
var task = _mediaSourceManager.CloseLiveStream(request.LiveStreamId, CancellationToken.None);
|
||||
var task = _mediaSourceManager.CloseLiveStream(request.LiveStreamId);
|
||||
Task.WaitAll(task);
|
||||
}
|
||||
|
||||
|
|
|
@ -27,12 +27,10 @@ namespace MediaBrowser.Api.Playback.Progressive
|
|||
public abstract class BaseProgressiveStreamingService : BaseStreamingService
|
||||
{
|
||||
protected readonly IImageProcessor ImageProcessor;
|
||||
protected readonly IHttpClient HttpClient;
|
||||
|
||||
protected BaseProgressiveStreamingService(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 = imageProcessor;
|
||||
HttpClient = httpClient;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
|
|
|
@ -225,7 +225,7 @@ namespace MediaBrowser.Api.Playback
|
|||
{
|
||||
try
|
||||
{
|
||||
await _mediaSourceManager.CloseLiveStream(MediaSource.LiveStreamId, CancellationToken.None).ConfigureAwait(false);
|
||||
await _mediaSourceManager.CloseLiveStream(MediaSource.LiveStreamId).ConfigureAwait(false);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
|
|
|
@ -101,6 +101,8 @@ namespace MediaBrowser.Controller.Entities
|
|||
public bool? IsMovie { get; set; }
|
||||
public bool? IsSports { get; set; }
|
||||
public bool? IsKids { get; set; }
|
||||
public bool? IsNews { get; set; }
|
||||
public bool? IsSeries { get; set; }
|
||||
|
||||
public int? MinPlayers { get; set; }
|
||||
public int? MaxPlayers { get; set; }
|
||||
|
|
|
@ -92,8 +92,7 @@ namespace MediaBrowser.Controller.Library
|
|||
/// Closes the media source.
|
||||
/// </summary>
|
||||
/// <param name="id">The live stream identifier.</param>
|
||||
/// <param name="cancellationToken">The cancellation token.</param>
|
||||
/// <returns>Task.</returns>
|
||||
Task CloseLiveStream(string id, CancellationToken cancellationToken);
|
||||
Task CloseLiveStream(string id);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -28,8 +28,7 @@ namespace MediaBrowser.Controller.Library
|
|||
/// Closes the media source.
|
||||
/// </summary>
|
||||
/// <param name="liveStreamId">The live stream identifier.</param>
|
||||
/// <param name="cancellationToken">The cancellation token.</param>
|
||||
/// <returns>Task.</returns>
|
||||
Task CloseMediaSource(string liveStreamId, CancellationToken cancellationToken);
|
||||
Task CloseMediaSource(string liveStreamId);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -220,9 +220,8 @@ namespace MediaBrowser.Controller.LiveTv
|
|||
/// Closes the live stream.
|
||||
/// </summary>
|
||||
/// <param name="id">The identifier.</param>
|
||||
/// <param name="cancellationToken">The cancellation token.</param>
|
||||
/// <returns>Task.</returns>
|
||||
Task CloseLiveStream(string id, CancellationToken cancellationToken);
|
||||
Task CloseLiveStream(string id);
|
||||
|
||||
/// <summary>
|
||||
/// Gets the guide information.
|
||||
|
|
|
@ -22,9 +22,8 @@ namespace MediaBrowser.Controller.LiveTv
|
|||
/// <summary>
|
||||
/// Gets the channels.
|
||||
/// </summary>
|
||||
/// <param name="cancellationToken">The cancellation token.</param>
|
||||
/// <returns>Task<IEnumerable<ChannelInfo>>.</returns>
|
||||
Task<IEnumerable<ChannelInfo>> GetChannels(CancellationToken cancellationToken);
|
||||
Task<IEnumerable<ChannelInfo>> GetChannels(bool enableCache, CancellationToken cancellationToken);
|
||||
/// <summary>
|
||||
/// Gets the tuner infos.
|
||||
/// </summary>
|
||||
|
@ -46,8 +45,6 @@ namespace MediaBrowser.Controller.LiveTv
|
|||
/// <param name="cancellationToken">The cancellation token.</param>
|
||||
/// <returns>Task<List<MediaSourceInfo>>.</returns>
|
||||
Task<List<MediaSourceInfo>> GetChannelStreamMediaSources(string channelId, CancellationToken cancellationToken);
|
||||
|
||||
string ApplyDuration(string streamPath, TimeSpan duration);
|
||||
}
|
||||
public interface IConfigurableTunerHost
|
||||
{
|
||||
|
|
|
@ -1,4 +1,5 @@
|
|||
using System.Threading;
|
||||
using System;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
using MediaBrowser.Model.Dto;
|
||||
|
||||
|
@ -7,17 +8,27 @@ namespace MediaBrowser.Controller.LiveTv
|
|||
public class LiveStream
|
||||
{
|
||||
public MediaSourceInfo OriginalMediaSource { get; set; }
|
||||
public MediaSourceInfo PublicMediaSource { get; set; }
|
||||
public string Id { get; set; }
|
||||
public MediaSourceInfo OpenedMediaSource { get; set; }
|
||||
public DateTime DateOpened { get; set; }
|
||||
public int ConsumerCount { get; set; }
|
||||
public ITunerHost TunerHost { get; set; }
|
||||
public string OriginalStreamId { get; set; }
|
||||
|
||||
public LiveStream(MediaSourceInfo mediaSource)
|
||||
{
|
||||
OriginalMediaSource = mediaSource;
|
||||
PublicMediaSource = mediaSource;
|
||||
Id = mediaSource.Id;
|
||||
OpenedMediaSource = mediaSource;
|
||||
}
|
||||
|
||||
public virtual Task Open(CancellationToken cancellationToken)
|
||||
public async Task Open(CancellationToken cancellationToken)
|
||||
{
|
||||
await OpenInternal(cancellationToken).ConfigureAwait(false);
|
||||
DateOpened = DateTime.UtcNow;
|
||||
|
||||
OpenedMediaSource.DateLiveStreamOpened = DateOpened;
|
||||
}
|
||||
|
||||
protected virtual Task OpenInternal(CancellationToken cancellationToken)
|
||||
{
|
||||
return Task.FromResult(true);
|
||||
}
|
||||
|
|
|
@ -9,7 +9,7 @@ using System.Runtime.Serialization;
|
|||
|
||||
namespace MediaBrowser.Controller.LiveTv
|
||||
{
|
||||
public class LiveTvChannel : BaseItem, IHasMediaSources
|
||||
public class LiveTvChannel : BaseItem, IHasMediaSources, IHasProgramAttributes
|
||||
{
|
||||
public override List<string> GetUserDataKeys()
|
||||
{
|
||||
|
@ -137,5 +137,56 @@ namespace MediaBrowser.Controller.LiveTv
|
|||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
[IgnoreDataMember]
|
||||
public bool IsMovie { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets a value indicating whether this instance is sports.
|
||||
/// </summary>
|
||||
/// <value><c>true</c> if this instance is sports; otherwise, <c>false</c>.</value>
|
||||
[IgnoreDataMember]
|
||||
public bool IsSports { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets a value indicating whether this instance is series.
|
||||
/// </summary>
|
||||
/// <value><c>true</c> if this instance is series; otherwise, <c>false</c>.</value>
|
||||
[IgnoreDataMember]
|
||||
public bool IsSeries { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets a value indicating whether this instance is live.
|
||||
/// </summary>
|
||||
/// <value><c>true</c> if this instance is live; otherwise, <c>false</c>.</value>
|
||||
[IgnoreDataMember]
|
||||
public bool IsLive { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets a value indicating whether this instance is news.
|
||||
/// </summary>
|
||||
/// <value><c>true</c> if this instance is news; otherwise, <c>false</c>.</value>
|
||||
[IgnoreDataMember]
|
||||
public bool IsNews { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets a value indicating whether this instance is kids.
|
||||
/// </summary>
|
||||
/// <value><c>true</c> if this instance is kids; otherwise, <c>false</c>.</value>
|
||||
[IgnoreDataMember]
|
||||
public bool IsKids { get; set; }
|
||||
|
||||
[IgnoreDataMember]
|
||||
public bool IsPremiere { get; set; }
|
||||
|
||||
[IgnoreDataMember]
|
||||
public bool IsRepeat { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the episode title.
|
||||
/// </summary>
|
||||
/// <value>The episode title.</value>
|
||||
[IgnoreDataMember]
|
||||
public string EpisodeTitle { get; set; }
|
||||
}
|
||||
}
|
||||
|
|
|
@ -101,6 +101,7 @@ namespace MediaBrowser.Controller.LiveTv
|
|||
public bool IsMovie { get; set; }
|
||||
public bool IsKids { get; set; }
|
||||
public bool IsSports { get; set; }
|
||||
public bool IsNews { get; set; }
|
||||
public int? ProductionYear { get; set; }
|
||||
public string EpisodeTitle { get; set; }
|
||||
public DateTime? OriginalAirDate { get; set; }
|
||||
|
|
|
@ -140,7 +140,7 @@ namespace MediaBrowser.MediaEncoding.Encoder
|
|||
{
|
||||
try
|
||||
{
|
||||
await _mediaSourceManager.CloseLiveStream(MediaSource.LiveStreamId, CancellationToken.None).ConfigureAwait(false);
|
||||
await _mediaSourceManager.CloseLiveStream(MediaSource.LiveStreamId).ConfigureAwait(false);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
|
|
|
@ -1,4 +1,5 @@
|
|||
using MediaBrowser.Model.Entities;
|
||||
using System;
|
||||
using MediaBrowser.Model.Entities;
|
||||
using MediaBrowser.Model.Extensions;
|
||||
using MediaBrowser.Model.MediaInfo;
|
||||
using System.Collections.Generic;
|
||||
|
@ -52,7 +53,9 @@ namespace MediaBrowser.Model.Dto
|
|||
public string TranscodingUrl { get; set; }
|
||||
public string TranscodingSubProtocol { get; set; }
|
||||
public string TranscodingContainer { get; set; }
|
||||
|
||||
|
||||
public DateTime? DateLiveStreamOpened { get; set; }
|
||||
|
||||
public MediaSourceInfo()
|
||||
{
|
||||
Formats = new List<string>();
|
||||
|
|
|
@ -61,6 +61,30 @@ namespace MediaBrowser.Model.LiveTv
|
|||
public bool AddCurrentProgram { get; set; }
|
||||
public bool EnableUserData { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Used to specific whether to return news or not
|
||||
/// </summary>
|
||||
/// <remarks>If set to null, all programs will be returned</remarks>
|
||||
public bool? IsNews { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Used to specific whether to return movies or not
|
||||
/// </summary>
|
||||
/// <remarks>If set to null, all programs will be returned</remarks>
|
||||
public bool? IsMovie { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets a value indicating whether this instance is kids.
|
||||
/// </summary>
|
||||
/// <value><c>null</c> if [is kids] contains no value, <c>true</c> if [is kids]; otherwise, <c>false</c>.</value>
|
||||
public bool? IsKids { get; set; }
|
||||
/// <summary>
|
||||
/// Gets or sets a value indicating whether this instance is sports.
|
||||
/// </summary>
|
||||
/// <value><c>null</c> if [is sports] contains no value, <c>true</c> if [is sports]; otherwise, <c>false</c>.</value>
|
||||
public bool? IsSports { get; set; }
|
||||
public bool? IsSeries { get; set; }
|
||||
|
||||
public LiveTvChannelQuery()
|
||||
{
|
||||
EnableUserData = true;
|
||||
|
|
|
@ -62,6 +62,12 @@ namespace MediaBrowser.Model.LiveTv
|
|||
/// </summary>
|
||||
public DateTime? MaxEndDate { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Used to specific whether to return news or not
|
||||
/// </summary>
|
||||
/// <remarks>If set to null, all programs will be returned</remarks>
|
||||
public bool? IsNews { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Used to specific whether to return movies or not
|
||||
/// </summary>
|
||||
|
@ -83,6 +89,7 @@ namespace MediaBrowser.Model.LiveTv
|
|||
/// Skips over a given number of items within the results. Use for paging.
|
||||
/// </summary>
|
||||
public int? StartIndex { get; set; }
|
||||
public bool? IsSeries { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets a value indicating whether this instance has aired.
|
||||
|
|
|
@ -45,11 +45,17 @@ namespace MediaBrowser.Model.LiveTv
|
|||
/// <value>The limit.</value>
|
||||
public int? Limit { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets a value indicating whether this instance is movie.
|
||||
/// </summary>
|
||||
/// <value><c>null</c> if [is movie] contains no value, <c>true</c> if [is movie]; otherwise, <c>false</c>.</value>
|
||||
public bool? IsNews { get; set; }
|
||||
/// <summary>
|
||||
/// Gets or sets a value indicating whether this instance is movie.
|
||||
/// </summary>
|
||||
/// <value><c>null</c> if [is movie] contains no value, <c>true</c> if [is movie]; otherwise, <c>false</c>.</value>
|
||||
public bool? IsMovie { get; set; }
|
||||
public bool? IsSeries { get; set; }
|
||||
/// <summary>
|
||||
/// Gets or sets a value indicating whether this instance is kids.
|
||||
/// </summary>
|
||||
|
|
|
@ -68,6 +68,7 @@ namespace MediaBrowser.Model.LiveTv
|
|||
/// <value>The fields.</value>
|
||||
public ItemFields[] Fields { get; set; }
|
||||
public bool? EnableImages { get; set; }
|
||||
public bool? IsNews { get; set; }
|
||||
public bool? IsMovie { get; set; }
|
||||
public bool? IsSeries { get; set; }
|
||||
public bool? IsKids { get; set; }
|
||||
|
|
|
@ -35,7 +35,7 @@ namespace MediaBrowser.Server.Implementations.Channels
|
|||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
public Task CloseMediaSource(string liveStreamId, CancellationToken cancellationToken)
|
||||
public Task CloseMediaSource(string liveStreamId)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
|
|
@ -355,7 +355,7 @@ namespace MediaBrowser.Server.Implementations.Library
|
|||
.ToList();
|
||||
}
|
||||
|
||||
private readonly ConcurrentDictionary<string, LiveStreamInfo> _openStreams = new ConcurrentDictionary<string, LiveStreamInfo>(StringComparer.OrdinalIgnoreCase);
|
||||
private readonly Dictionary<string, LiveStreamInfo> _openStreams = new Dictionary<string, LiveStreamInfo>(StringComparer.OrdinalIgnoreCase);
|
||||
private readonly SemaphoreSlim _liveStreamSemaphore = new SemaphoreSlim(1, 1);
|
||||
|
||||
public async Task<LiveStreamResponse> OpenLiveStream(LiveStreamRequest request, bool enableAutoClose, CancellationToken cancellationToken)
|
||||
|
@ -383,7 +383,7 @@ namespace MediaBrowser.Server.Implementations.Library
|
|||
Id = mediaSource.LiveStreamId,
|
||||
MediaSource = mediaSource
|
||||
};
|
||||
_openStreams.AddOrUpdate(mediaSource.LiveStreamId, info, (key, i) => info);
|
||||
_openStreams[mediaSource.LiveStreamId] = info;
|
||||
|
||||
if (enableAutoClose)
|
||||
{
|
||||
|
@ -421,7 +421,7 @@ namespace MediaBrowser.Server.Implementations.Library
|
|||
throw new ArgumentNullException("id");
|
||||
}
|
||||
|
||||
_logger.Debug("Getting live stream {0}", id);
|
||||
_logger.Debug("Getting already opened live stream {0}", id);
|
||||
|
||||
await _liveStreamSemaphore.WaitAsync(cancellationToken).ConfigureAwait(false);
|
||||
|
||||
|
@ -465,17 +465,16 @@ namespace MediaBrowser.Server.Implementations.Library
|
|||
}
|
||||
}
|
||||
|
||||
private async Task CloseLiveStreamWithProvider(IMediaSourceProvider provider, string streamId, CancellationToken cancellationToken)
|
||||
private async Task CloseLiveStreamWithProvider(IMediaSourceProvider provider, string streamId)
|
||||
{
|
||||
_logger.Info("Closing live stream {0} with provider {1}", streamId, provider.GetType().Name);
|
||||
|
||||
try
|
||||
{
|
||||
await provider.CloseMediaSource(streamId, cancellationToken).ConfigureAwait(false);
|
||||
await provider.CloseMediaSource(streamId).ConfigureAwait(false);
|
||||
}
|
||||
catch (NotImplementedException)
|
||||
{
|
||||
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
|
@ -483,37 +482,35 @@ namespace MediaBrowser.Server.Implementations.Library
|
|||
}
|
||||
}
|
||||
|
||||
public async Task CloseLiveStream(string id, CancellationToken cancellationToken)
|
||||
public async Task CloseLiveStream(string id)
|
||||
{
|
||||
if (string.IsNullOrWhiteSpace(id))
|
||||
{
|
||||
throw new ArgumentNullException("id");
|
||||
}
|
||||
|
||||
await _liveStreamSemaphore.WaitAsync(cancellationToken).ConfigureAwait(false);
|
||||
await _liveStreamSemaphore.WaitAsync().ConfigureAwait(false);
|
||||
|
||||
try
|
||||
{
|
||||
LiveStreamInfo current;
|
||||
|
||||
if (_openStreams.TryGetValue(id, out current))
|
||||
{
|
||||
_openStreams.Remove(id);
|
||||
current.Closed = true;
|
||||
|
||||
if (current.MediaSource.RequiresClosing)
|
||||
{
|
||||
var tuple = GetProvider(id);
|
||||
|
||||
await CloseLiveStreamWithProvider(tuple.Item1, tuple.Item2, cancellationToken).ConfigureAwait(false);
|
||||
await CloseLiveStreamWithProvider(tuple.Item1, tuple.Item2).ConfigureAwait(false);
|
||||
}
|
||||
}
|
||||
|
||||
LiveStreamInfo removed;
|
||||
if (_openStreams.TryRemove(id, out removed))
|
||||
{
|
||||
removed.Closed = true;
|
||||
}
|
||||
|
||||
if (_openStreams.Count == 0)
|
||||
{
|
||||
StopCloseTimer();
|
||||
if (_openStreams.Count == 0)
|
||||
{
|
||||
StopCloseTimer();
|
||||
}
|
||||
}
|
||||
}
|
||||
finally
|
||||
|
@ -565,10 +562,20 @@ namespace MediaBrowser.Server.Implementations.Library
|
|||
|
||||
private async void CloseTimerCallback(object state)
|
||||
{
|
||||
var infos = _openStreams
|
||||
.Values
|
||||
.Where(i => i.EnableCloseTimer && DateTime.UtcNow - i.Date > _openStreamMaxAge)
|
||||
.ToList();
|
||||
List<LiveStreamInfo> infos;
|
||||
await _liveStreamSemaphore.WaitAsync().ConfigureAwait(false);
|
||||
|
||||
try
|
||||
{
|
||||
infos = _openStreams
|
||||
.Values
|
||||
.Where(i => i.EnableCloseTimer && DateTime.UtcNow - i.Date > _openStreamMaxAge)
|
||||
.ToList();
|
||||
}
|
||||
finally
|
||||
{
|
||||
_liveStreamSemaphore.Release();
|
||||
}
|
||||
|
||||
foreach (var info in infos)
|
||||
{
|
||||
|
@ -576,7 +583,7 @@ namespace MediaBrowser.Server.Implementations.Library
|
|||
{
|
||||
try
|
||||
{
|
||||
await CloseLiveStream(info.Id, CancellationToken.None).ConfigureAwait(false);
|
||||
await CloseLiveStream(info.Id).ConfigureAwait(false);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
|
@ -608,12 +615,10 @@ namespace MediaBrowser.Server.Implementations.Library
|
|||
{
|
||||
foreach (var key in _openStreams.Keys.ToList())
|
||||
{
|
||||
var task = CloseLiveStream(key, CancellationToken.None);
|
||||
var task = CloseLiveStream(key);
|
||||
|
||||
Task.WaitAll(task);
|
||||
}
|
||||
|
||||
_openStreams.Clear();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -47,19 +47,9 @@ namespace MediaBrowser.Server.Implementations.LiveTv.EmbyTV
|
|||
|
||||
_logger.Info("Copying recording stream to file {0}", targetFile);
|
||||
|
||||
if (mediaSource.RunTimeTicks.HasValue)
|
||||
{
|
||||
// The media source already has a fixed duration
|
||||
// But add another stop 1 minute later just in case the recording gets stuck for any reason
|
||||
var durationToken = new CancellationTokenSource(duration.Add(TimeSpan.FromMinutes(1)));
|
||||
cancellationToken = CancellationTokenSource.CreateLinkedTokenSource(cancellationToken, durationToken.Token).Token;
|
||||
}
|
||||
else
|
||||
{
|
||||
// The media source if infinite so we need to handle stopping ourselves
|
||||
var durationToken = new CancellationTokenSource(duration);
|
||||
cancellationToken = CancellationTokenSource.CreateLinkedTokenSource(cancellationToken, durationToken.Token).Token;
|
||||
}
|
||||
// The media source if infinite so we need to handle stopping ourselves
|
||||
var durationToken = new CancellationTokenSource(duration);
|
||||
cancellationToken = CancellationTokenSource.CreateLinkedTokenSource(cancellationToken, durationToken.Token).Token;
|
||||
|
||||
await CopyUntilCancelled(response.Content, output, cancellationToken).ConfigureAwait(false);
|
||||
}
|
||||
|
|
|
@ -340,22 +340,15 @@ namespace MediaBrowser.Server.Implementations.LiveTv.EmbyTV
|
|||
_timerProvider.Delete(timer);
|
||||
}
|
||||
|
||||
private List<ChannelInfo> _channelCache = null;
|
||||
private async Task<IEnumerable<ChannelInfo>> GetChannelsAsync(bool enableCache, CancellationToken cancellationToken)
|
||||
{
|
||||
if (enableCache && _channelCache != null)
|
||||
{
|
||||
|
||||
return _channelCache.ToList();
|
||||
}
|
||||
|
||||
var list = new List<ChannelInfo>();
|
||||
|
||||
foreach (var hostInstance in _liveTvManager.TunerHosts)
|
||||
{
|
||||
try
|
||||
{
|
||||
var channels = await hostInstance.GetChannels(cancellationToken).ConfigureAwait(false);
|
||||
var channels = await hostInstance.GetChannels(enableCache, cancellationToken).ConfigureAwait(false);
|
||||
|
||||
list.AddRange(channels);
|
||||
}
|
||||
|
@ -388,7 +381,6 @@ namespace MediaBrowser.Server.Implementations.LiveTv.EmbyTV
|
|||
}
|
||||
}
|
||||
|
||||
_channelCache = list.ToList();
|
||||
return list;
|
||||
}
|
||||
|
||||
|
@ -400,7 +392,7 @@ namespace MediaBrowser.Server.Implementations.LiveTv.EmbyTV
|
|||
{
|
||||
try
|
||||
{
|
||||
var channels = await hostInstance.GetChannels(cancellationToken).ConfigureAwait(false);
|
||||
var channels = await hostInstance.GetChannels(false, cancellationToken).ConfigureAwait(false);
|
||||
|
||||
list.AddRange(channels);
|
||||
}
|
||||
|
@ -632,6 +624,7 @@ namespace MediaBrowser.Server.Implementations.LiveTv.EmbyTV
|
|||
existingTimer.Genres = updatedTimer.Genres;
|
||||
existingTimer.HomePageUrl = updatedTimer.HomePageUrl;
|
||||
existingTimer.IsKids = updatedTimer.IsKids;
|
||||
existingTimer.IsNews = updatedTimer.IsNews;
|
||||
existingTimer.IsMovie = updatedTimer.IsMovie;
|
||||
existingTimer.IsProgramSeries = updatedTimer.IsProgramSeries;
|
||||
existingTimer.IsSports = updatedTimer.IsSports;
|
||||
|
@ -836,32 +829,67 @@ namespace MediaBrowser.Server.Implementations.LiveTv.EmbyTV
|
|||
{
|
||||
var result = await GetChannelStreamInternal(channelId, streamId, cancellationToken).ConfigureAwait(false);
|
||||
|
||||
return result.Item1.PublicMediaSource;
|
||||
return result.Item2;
|
||||
}
|
||||
|
||||
private async Task<Tuple<LiveStream, ITunerHost>> GetChannelStreamInternal(string channelId, string streamId, CancellationToken cancellationToken)
|
||||
private MediaSourceInfo CloneMediaSource(MediaSourceInfo mediaSource, int consumerId)
|
||||
{
|
||||
var json = _jsonSerializer.SerializeToString(mediaSource);
|
||||
mediaSource = _jsonSerializer.DeserializeFromString<MediaSourceInfo>(json);
|
||||
|
||||
mediaSource.Id = consumerId.ToString(CultureInfo.InvariantCulture) + "_" + mediaSource.Id;
|
||||
|
||||
return mediaSource;
|
||||
}
|
||||
|
||||
private async Task<Tuple<LiveStream, MediaSourceInfo, ITunerHost>> GetChannelStreamInternal(string channelId, string streamId, CancellationToken cancellationToken)
|
||||
{
|
||||
_logger.Info("Streaming Channel " + channelId);
|
||||
|
||||
foreach (var hostInstance in _liveTvManager.TunerHosts)
|
||||
await _liveStreamsSemaphore.WaitAsync(cancellationToken).ConfigureAwait(false);
|
||||
|
||||
var result = _liveStreams.Values.FirstOrDefault(i => string.Equals(i.OriginalStreamId, streamId, StringComparison.OrdinalIgnoreCase));
|
||||
|
||||
if (result != null)
|
||||
{
|
||||
try
|
||||
{
|
||||
var result = await hostInstance.GetChannelStream(channelId, streamId, cancellationToken).ConfigureAwait(false);
|
||||
//result.ConsumerCount++;
|
||||
|
||||
await _liveStreamsSemaphore.WaitAsync().ConfigureAwait(false);
|
||||
_liveStreams[result.Id] = result;
|
||||
_liveStreamsSemaphore.Release();
|
||||
//_logger.Info("Live stream {0} consumer count is now {1}", streamId, result.ConsumerCount);
|
||||
|
||||
return new Tuple<LiveStream, ITunerHost>(result, hostInstance);
|
||||
}
|
||||
catch (FileNotFoundException)
|
||||
//_liveStreamsSemaphore.Release();
|
||||
//return new Tuple<LiveStream, MediaSourceInfo, ITunerHost>(result, CloneMediaSource(result.OpenedMediaSource, result.ConsumerCount - 1), result.TunerHost);
|
||||
}
|
||||
|
||||
try
|
||||
{
|
||||
foreach (var hostInstance in _liveTvManager.TunerHosts)
|
||||
{
|
||||
try
|
||||
{
|
||||
result = await hostInstance.GetChannelStream(channelId, streamId, cancellationToken).ConfigureAwait(false);
|
||||
|
||||
_liveStreams[result.OpenedMediaSource.Id] = result;
|
||||
|
||||
result.ConsumerCount++;
|
||||
result.TunerHost = hostInstance;
|
||||
result.OriginalStreamId = streamId;
|
||||
|
||||
_logger.Info("Returning mediasource streamId {0}, mediaSource.Id {1}, mediaSource.LiveStreamId {2}",
|
||||
streamId, result.OpenedMediaSource.Id, result.OpenedMediaSource.LiveStreamId);
|
||||
|
||||
return new Tuple<LiveStream, MediaSourceInfo, ITunerHost>(result, CloneMediaSource(result.OpenedMediaSource, 0), hostInstance);
|
||||
}
|
||||
catch (FileNotFoundException)
|
||||
{
|
||||
}
|
||||
catch (OperationCanceledException)
|
||||
{
|
||||
}
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
_logger.ErrorException("Error getting channel stream", e);
|
||||
}
|
||||
}
|
||||
finally
|
||||
{
|
||||
_liveStreamsSemaphore.Release();
|
||||
}
|
||||
|
||||
throw new ApplicationException("Tuner not found.");
|
||||
|
@ -896,25 +924,41 @@ namespace MediaBrowser.Server.Implementations.LiveTv.EmbyTV
|
|||
|
||||
public async Task CloseLiveStream(string id, CancellationToken cancellationToken)
|
||||
{
|
||||
await _liveStreamsSemaphore.WaitAsync().ConfigureAwait(false);
|
||||
// Ignore the consumer id
|
||||
id = id.Substring(id.IndexOf('_') + 1);
|
||||
|
||||
await _liveStreamsSemaphore.WaitAsync(cancellationToken).ConfigureAwait(false);
|
||||
|
||||
try
|
||||
{
|
||||
LiveStream stream;
|
||||
if (_liveStreams.TryGetValue(id, out stream))
|
||||
{
|
||||
_liveStreams.Remove(id);
|
||||
stream.ConsumerCount--;
|
||||
|
||||
try
|
||||
_logger.Info("Live stream {0} consumer count is now {1}", id, stream.ConsumerCount);
|
||||
|
||||
if (stream.ConsumerCount <= 0)
|
||||
{
|
||||
_liveStreams.Remove(id);
|
||||
|
||||
_logger.Info("Closing live stream {0}", id);
|
||||
|
||||
await stream.Close().ConfigureAwait(false);
|
||||
_logger.Info("Live stream {0} closed successfully", id);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
_logger.ErrorException("Error closing live stream", ex);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
_logger.Warn("Live stream not found: {0}, unable to close", id);
|
||||
}
|
||||
}
|
||||
catch (OperationCanceledException)
|
||||
{
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
_logger.ErrorException("Error closing live stream", ex);
|
||||
}
|
||||
finally
|
||||
{
|
||||
|
@ -1095,20 +1139,18 @@ namespace MediaBrowser.Server.Implementations.LiveTv.EmbyTV
|
|||
var recordPath = GetRecordingPath(timer, out seriesPath);
|
||||
var recordingStatus = RecordingStatus.New;
|
||||
|
||||
LiveStream liveStream = null;
|
||||
string liveStreamId = null;
|
||||
|
||||
try
|
||||
{
|
||||
var allMediaSources =
|
||||
await GetChannelStreamMediaSources(timer.ChannelId, CancellationToken.None).ConfigureAwait(false);
|
||||
|
||||
var liveStreamInfo =
|
||||
await
|
||||
GetChannelStreamInternal(timer.ChannelId, allMediaSources[0].Id, CancellationToken.None)
|
||||
var liveStreamInfo = await GetChannelStreamInternal(timer.ChannelId, allMediaSources[0].Id, CancellationToken.None)
|
||||
.ConfigureAwait(false);
|
||||
liveStream = liveStreamInfo.Item1;
|
||||
var mediaStreamInfo = liveStreamInfo.Item1.PublicMediaSource;
|
||||
var tunerHost = liveStreamInfo.Item2;
|
||||
|
||||
var mediaStreamInfo = liveStreamInfo.Item2;
|
||||
liveStreamId = mediaStreamInfo.Id;
|
||||
|
||||
// HDHR doesn't seem to release the tuner right away after first probing with ffmpeg
|
||||
//await Task.Delay(3000, cancellationToken).ConfigureAwait(false);
|
||||
|
@ -1140,15 +1182,6 @@ namespace MediaBrowser.Server.Implementations.LiveTv.EmbyTV
|
|||
EnforceKeepUpTo(timer);
|
||||
};
|
||||
|
||||
var pathWithDuration = tunerHost.ApplyDuration(mediaStreamInfo.Path, duration);
|
||||
|
||||
// If it supports supplying duration via url
|
||||
if (!string.Equals(pathWithDuration, mediaStreamInfo.Path, StringComparison.OrdinalIgnoreCase))
|
||||
{
|
||||
mediaStreamInfo.Path = pathWithDuration;
|
||||
mediaStreamInfo.RunTimeTicks = duration.Ticks;
|
||||
}
|
||||
|
||||
await recorder.Record(mediaStreamInfo, recordPath, duration, onStarted, cancellationToken)
|
||||
.ConfigureAwait(false);
|
||||
|
||||
|
@ -1166,11 +1199,11 @@ namespace MediaBrowser.Server.Implementations.LiveTv.EmbyTV
|
|||
recordingStatus = RecordingStatus.Error;
|
||||
}
|
||||
|
||||
if (liveStream != null)
|
||||
if (!string.IsNullOrWhiteSpace(liveStreamId))
|
||||
{
|
||||
try
|
||||
{
|
||||
await CloseLiveStream(liveStream.Id, CancellationToken.None).ConfigureAwait(false);
|
||||
await CloseLiveStream(liveStreamId, CancellationToken.None).ConfigureAwait(false);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
|
@ -1251,7 +1284,7 @@ namespace MediaBrowser.Server.Implementations.LiveTv.EmbyTV
|
|||
}
|
||||
}
|
||||
|
||||
private readonly SemaphoreSlim _recordingDeleteSemaphore = new SemaphoreSlim(1,1);
|
||||
private readonly SemaphoreSlim _recordingDeleteSemaphore = new SemaphoreSlim(1, 1);
|
||||
private async Task DeleteLibraryItemsForTimers(List<TimerInfo> timers)
|
||||
{
|
||||
foreach (var timer in timers)
|
||||
|
@ -1295,7 +1328,7 @@ namespace MediaBrowser.Server.Implementations.LiveTv.EmbyTV
|
|||
}
|
||||
catch (FileNotFoundException)
|
||||
{
|
||||
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1492,6 +1525,10 @@ namespace MediaBrowser.Server.Implementations.LiveTv.EmbyTV
|
|||
{
|
||||
AddGenre(timer.Genres, "Kids");
|
||||
}
|
||||
if (timer.IsNews)
|
||||
{
|
||||
AddGenre(timer.Genres, "News");
|
||||
}
|
||||
|
||||
foreach (var genre in timer.Genres)
|
||||
{
|
||||
|
|
|
@ -71,38 +71,12 @@ namespace MediaBrowser.Server.Implementations.LiveTv.EmbyTV
|
|||
var durationToken = new CancellationTokenSource(duration);
|
||||
cancellationToken = CancellationTokenSource.CreateLinkedTokenSource(cancellationToken, durationToken.Token).Token;
|
||||
|
||||
await RecordFromFile(mediaSource, mediaSource.Path, targetFile, false, duration, onStarted, cancellationToken).ConfigureAwait(false);
|
||||
await RecordFromFile(mediaSource, mediaSource.Path, targetFile, duration, onStarted, cancellationToken).ConfigureAwait(false);
|
||||
|
||||
_logger.Info("Recording completed to file {0}", targetFile);
|
||||
}
|
||||
|
||||
private async void DeleteTempFile(string path)
|
||||
{
|
||||
for (var i = 0; i < 10; i++)
|
||||
{
|
||||
try
|
||||
{
|
||||
File.Delete(path);
|
||||
return;
|
||||
}
|
||||
catch (FileNotFoundException)
|
||||
{
|
||||
return;
|
||||
}
|
||||
catch (DirectoryNotFoundException)
|
||||
{
|
||||
return;
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
_logger.ErrorException("Error deleting recording temp file", ex);
|
||||
}
|
||||
|
||||
await Task.Delay(1000).ConfigureAwait(false);
|
||||
}
|
||||
}
|
||||
|
||||
private Task RecordFromFile(MediaSourceInfo mediaSource, string inputFile, string targetFile, bool deleteInputFileAfterCompletion, TimeSpan duration, Action onStarted, CancellationToken cancellationToken)
|
||||
private Task RecordFromFile(MediaSourceInfo mediaSource, string inputFile, string targetFile, TimeSpan duration, Action onStarted, CancellationToken cancellationToken)
|
||||
{
|
||||
_targetPath = targetFile;
|
||||
_fileSystem.CreateDirectory(Path.GetDirectoryName(targetFile));
|
||||
|
@ -143,7 +117,7 @@ namespace MediaBrowser.Server.Implementations.LiveTv.EmbyTV
|
|||
var commandLineLogMessageBytes = Encoding.UTF8.GetBytes(_json.SerializeToString(mediaSource) + Environment.NewLine + Environment.NewLine + commandLineLogMessage + Environment.NewLine + Environment.NewLine);
|
||||
_logFileStream.Write(commandLineLogMessageBytes, 0, commandLineLogMessageBytes.Length);
|
||||
|
||||
process.Exited += (sender, args) => OnFfMpegProcessExited(process, inputFile, deleteInputFileAfterCompletion);
|
||||
process.Exited += (sender, args) => OnFfMpegProcessExited(process, inputFile);
|
||||
|
||||
process.Start();
|
||||
|
||||
|
@ -252,7 +226,7 @@ namespace MediaBrowser.Server.Implementations.LiveTv.EmbyTV
|
|||
/// <summary>
|
||||
/// Processes the exited.
|
||||
/// </summary>
|
||||
private void OnFfMpegProcessExited(Process process, string inputFile, bool deleteInputFileAfterCompletion)
|
||||
private void OnFfMpegProcessExited(Process process, string inputFile)
|
||||
{
|
||||
_hasExited = true;
|
||||
|
||||
|
@ -278,11 +252,6 @@ namespace MediaBrowser.Server.Implementations.LiveTv.EmbyTV
|
|||
_logger.Error("FFMpeg recording exited with an error for {0}.", _targetPath);
|
||||
_taskCompletionSource.TrySetException(new Exception(string.Format("Recording for {0} failed", _targetPath)));
|
||||
}
|
||||
|
||||
if (deleteInputFileAfterCompletion)
|
||||
{
|
||||
DeleteTempFile(inputFile);
|
||||
}
|
||||
}
|
||||
|
||||
private void DisposeLogStream()
|
||||
|
|
|
@ -42,6 +42,7 @@ namespace MediaBrowser.Server.Implementations.LiveTv.EmbyTV
|
|||
timerInfo.EpisodeNumber = programInfo.EpisodeNumber;
|
||||
timerInfo.IsMovie = programInfo.IsMovie;
|
||||
timerInfo.IsKids = programInfo.IsKids;
|
||||
timerInfo.IsNews = programInfo.IsNews;
|
||||
timerInfo.IsSports = programInfo.IsSports;
|
||||
timerInfo.ProductionYear = programInfo.ProductionYear;
|
||||
timerInfo.EpisodeTitle = programInfo.EpisodeTitle;
|
||||
|
|
|
@ -62,9 +62,6 @@ namespace MediaBrowser.Server.Implementations.LiveTv
|
|||
|
||||
private readonly List<ILiveTvService> _services = new List<ILiveTvService>();
|
||||
|
||||
private readonly ConcurrentDictionary<string, LiveStreamData> _openStreams =
|
||||
new ConcurrentDictionary<string, LiveStreamData>();
|
||||
|
||||
private readonly SemaphoreSlim _refreshRecordingsLock = new SemaphoreSlim(1, 1);
|
||||
|
||||
private readonly List<ITunerHost> _tunerHosts = new List<ITunerHost>();
|
||||
|
@ -153,6 +150,11 @@ namespace MediaBrowser.Server.Implementations.LiveTv
|
|||
|
||||
var channels = _libraryManager.GetItemList(new InternalItemsQuery
|
||||
{
|
||||
IsMovie = query.IsMovie,
|
||||
IsNews = query.IsNews,
|
||||
IsKids = query.IsKids,
|
||||
IsSports = query.IsSports,
|
||||
IsSeries = query.IsSeries,
|
||||
IncludeItemTypes = new[] { typeof(LiveTvChannel).Name },
|
||||
SortBy = new[] { ItemSortBy.SortName },
|
||||
TopParentIds = new[] { topFolder.Id.ToString("N") }
|
||||
|
@ -407,15 +409,6 @@ namespace MediaBrowser.Server.Implementations.LiveTv
|
|||
_logger.Info("Live stream info: {0}", _jsonSerializer.SerializeToString(info));
|
||||
Normalize(info, service, isVideo);
|
||||
|
||||
var data = new LiveStreamData
|
||||
{
|
||||
Info = info,
|
||||
IsChannel = isChannel,
|
||||
ItemId = id
|
||||
};
|
||||
|
||||
_openStreams.AddOrUpdate(info.Id, data, (key, i) => data);
|
||||
|
||||
return info;
|
||||
}
|
||||
catch (Exception ex)
|
||||
|
@ -937,8 +930,10 @@ namespace MediaBrowser.Server.Implementations.LiveTv
|
|||
MaxStartDate = query.MaxStartDate,
|
||||
ChannelIds = query.ChannelIds,
|
||||
IsMovie = query.IsMovie,
|
||||
IsSeries = query.IsSeries,
|
||||
IsSports = query.IsSports,
|
||||
IsKids = query.IsKids,
|
||||
IsNews = query.IsNews,
|
||||
Genres = query.Genres,
|
||||
StartIndex = query.StartIndex,
|
||||
Limit = query.Limit,
|
||||
|
@ -985,7 +980,9 @@ namespace MediaBrowser.Server.Implementations.LiveTv
|
|||
{
|
||||
IncludeItemTypes = new[] { typeof(LiveTvProgram).Name },
|
||||
IsAiring = query.IsAiring,
|
||||
IsNews = query.IsNews,
|
||||
IsMovie = query.IsMovie,
|
||||
IsSeries = query.IsSeries,
|
||||
IsSports = query.IsSports,
|
||||
IsKids = query.IsKids,
|
||||
EnableTotalRecordCount = query.EnableTotalRecordCount,
|
||||
|
@ -1014,7 +1011,7 @@ namespace MediaBrowser.Server.Implementations.LiveTv
|
|||
|
||||
var programList = programs.ToList();
|
||||
|
||||
var factorChannelWatchCount = (query.IsAiring ?? false) || (query.IsKids ?? false) || (query.IsSports ?? false) || (query.IsMovie ?? false);
|
||||
var factorChannelWatchCount = (query.IsAiring ?? false) || (query.IsKids ?? false) || (query.IsSports ?? false) || (query.IsMovie ?? false) || (query.IsNews ?? false) || (query.IsSeries ?? false);
|
||||
|
||||
programs = programList.OrderBy(i => i.StartDate.Date)
|
||||
.ThenByDescending(i => GetRecommendationScore(i, user.Id, factorChannelWatchCount))
|
||||
|
@ -1305,6 +1302,12 @@ namespace MediaBrowser.Server.Implementations.LiveTv
|
|||
var start = DateTime.UtcNow.AddHours(-1);
|
||||
var end = start.AddDays(guideDays);
|
||||
|
||||
var isMovie = false;
|
||||
var isSports = false;
|
||||
var isNews = false;
|
||||
var isKids = false;
|
||||
var iSSeries = false;
|
||||
|
||||
var channelPrograms = await service.GetProgramsAsync(currentChannel.ExternalId, start, end, cancellationToken).ConfigureAwait(false);
|
||||
|
||||
foreach (var program in channelPrograms)
|
||||
|
@ -1312,7 +1315,40 @@ namespace MediaBrowser.Server.Implementations.LiveTv
|
|||
var programItem = await GetProgram(program, currentChannel, currentChannel.ChannelType, service.Name, cancellationToken).ConfigureAwait(false);
|
||||
|
||||
programs.Add(programItem.Id);
|
||||
|
||||
if (program.IsMovie)
|
||||
{
|
||||
isMovie = true;
|
||||
}
|
||||
|
||||
if (program.IsSeries)
|
||||
{
|
||||
iSSeries = true;
|
||||
}
|
||||
|
||||
if (program.IsSports)
|
||||
{
|
||||
isSports = true;
|
||||
}
|
||||
|
||||
if (program.IsNews)
|
||||
{
|
||||
isNews = true;
|
||||
}
|
||||
|
||||
if (program.IsKids)
|
||||
{
|
||||
isKids = true;
|
||||
}
|
||||
}
|
||||
|
||||
currentChannel.IsMovie = isMovie;
|
||||
currentChannel.IsNews = isNews;
|
||||
currentChannel.IsSports = isSports;
|
||||
currentChannel.IsKids = isKids;
|
||||
currentChannel.IsSeries = iSSeries;
|
||||
|
||||
await currentChannel.UpdateToRepository(ItemUpdateType.MetadataImport, cancellationToken).ConfigureAwait(false);
|
||||
}
|
||||
catch (OperationCanceledException)
|
||||
{
|
||||
|
@ -1647,6 +1683,12 @@ namespace MediaBrowser.Server.Implementations.LiveTv
|
|||
recordings = recordings.Where(i => i.IsMovie == val);
|
||||
}
|
||||
|
||||
if (query.IsNews.HasValue)
|
||||
{
|
||||
var val = query.IsNews.Value;
|
||||
recordings = recordings.Where(i => i.IsNews == val);
|
||||
}
|
||||
|
||||
if (query.IsSeries.HasValue)
|
||||
{
|
||||
var val = query.IsSeries.Value;
|
||||
|
@ -2444,9 +2486,9 @@ namespace MediaBrowser.Server.Implementations.LiveTv
|
|||
internal bool IsChannel;
|
||||
}
|
||||
|
||||
public async Task CloseLiveStream(string id, CancellationToken cancellationToken)
|
||||
public async Task CloseLiveStream(string id)
|
||||
{
|
||||
await _liveStreamSemaphore.WaitAsync(cancellationToken).ConfigureAwait(false);
|
||||
await _liveStreamSemaphore.WaitAsync().ConfigureAwait(false);
|
||||
|
||||
try
|
||||
{
|
||||
|
@ -2461,12 +2503,9 @@ namespace MediaBrowser.Server.Implementations.LiveTv
|
|||
|
||||
id = parts[1];
|
||||
|
||||
LiveStreamData data;
|
||||
_openStreams.TryRemove(id, out data);
|
||||
|
||||
_logger.Info("Closing live stream from {0}, stream Id: {1}", service.Name, id);
|
||||
|
||||
await service.CloseLiveStream(id, cancellationToken).ConfigureAwait(false);
|
||||
await service.CloseLiveStream(id, CancellationToken.None).ConfigureAwait(false);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
|
@ -2500,7 +2539,6 @@ namespace MediaBrowser.Server.Implementations.LiveTv
|
|||
Dispose(true);
|
||||
}
|
||||
|
||||
private readonly object _disposeLock = new object();
|
||||
private bool _isDisposed = false;
|
||||
/// <summary>
|
||||
/// Releases unmanaged and - optionally - managed resources.
|
||||
|
@ -2511,18 +2549,6 @@ namespace MediaBrowser.Server.Implementations.LiveTv
|
|||
if (dispose)
|
||||
{
|
||||
_isDisposed = true;
|
||||
|
||||
lock (_disposeLock)
|
||||
{
|
||||
foreach (var stream in _openStreams.Values.ToList())
|
||||
{
|
||||
var task = CloseLiveStream(stream.Info.Id, CancellationToken.None);
|
||||
|
||||
Task.WaitAll(task);
|
||||
}
|
||||
|
||||
_openStreams.Clear();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -204,9 +204,9 @@ namespace MediaBrowser.Server.Implementations.LiveTv
|
|||
}
|
||||
}
|
||||
|
||||
public Task CloseMediaSource(string liveStreamId, CancellationToken cancellationToken)
|
||||
public Task CloseMediaSource(string liveStreamId)
|
||||
{
|
||||
return _liveTvManager.CloseLiveStream(liveStreamId, cancellationToken);
|
||||
return _liveTvManager.CloseLiveStream(liveStreamId);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -73,7 +73,7 @@ namespace MediaBrowser.Server.Implementations.LiveTv.TunerHosts
|
|||
.ToList();
|
||||
}
|
||||
|
||||
public async Task<IEnumerable<ChannelInfo>> GetChannels(CancellationToken cancellationToken)
|
||||
public async Task<IEnumerable<ChannelInfo>> GetChannels(bool enableCache, CancellationToken cancellationToken)
|
||||
{
|
||||
var list = new List<ChannelInfo>();
|
||||
|
||||
|
@ -83,7 +83,7 @@ namespace MediaBrowser.Server.Implementations.LiveTv.TunerHosts
|
|||
{
|
||||
try
|
||||
{
|
||||
var channels = await GetChannels(host, true, cancellationToken).ConfigureAwait(false);
|
||||
var channels = await GetChannels(host, enableCache, cancellationToken).ConfigureAwait(false);
|
||||
var newChannels = channels.Where(i => !list.Any(l => string.Equals(i.Id, l.Id, StringComparison.OrdinalIgnoreCase))).ToList();
|
||||
|
||||
list.AddRange(newChannels);
|
||||
|
|
|
@ -67,14 +67,6 @@ namespace MediaBrowser.Server.Implementations.LiveTv.TunerHosts.HdHomerun
|
|||
return id;
|
||||
}
|
||||
|
||||
public string ApplyDuration(string streamPath, TimeSpan duration)
|
||||
{
|
||||
streamPath += streamPath.IndexOf('?') == -1 ? "?" : "&";
|
||||
streamPath += "duration=" + Convert.ToInt32(duration.TotalSeconds).ToString(CultureInfo.InvariantCulture);
|
||||
|
||||
return streamPath;
|
||||
}
|
||||
|
||||
private async Task<IEnumerable<Channels>> GetLineup(TunerHostInfo info, CancellationToken cancellationToken)
|
||||
{
|
||||
var options = new HttpRequestOptions
|
||||
|
|
|
@ -34,7 +34,7 @@ namespace MediaBrowser.Server.Implementations.LiveTv.TunerHosts.HdHomerun
|
|||
_appHost = appHost;
|
||||
}
|
||||
|
||||
public override async Task Open(CancellationToken openCancellationToken)
|
||||
protected override async Task OpenInternal(CancellationToken openCancellationToken)
|
||||
{
|
||||
_liveStreamCancellationTokenSource.Token.ThrowIfCancellationRequested();
|
||||
|
||||
|
@ -54,13 +54,14 @@ namespace MediaBrowser.Server.Implementations.LiveTv.TunerHosts.HdHomerun
|
|||
|
||||
await taskCompletionSource.Task.ConfigureAwait(false);
|
||||
|
||||
PublicMediaSource.Path = _appHost.GetLocalApiUrl("localhost") + "/LiveTv/LiveStreamFiles/" + Path.GetFileNameWithoutExtension(tempFile) + "/stream.ts";
|
||||
OpenedMediaSource.Path = _appHost.GetLocalApiUrl("localhost") + "/LiveTv/LiveStreamFiles/" + Path.GetFileNameWithoutExtension(tempFile) + "/stream.ts";
|
||||
|
||||
PublicMediaSource.Protocol = MediaProtocol.Http;
|
||||
OpenedMediaSource.Protocol = MediaProtocol.Http;
|
||||
}
|
||||
|
||||
public override Task Close()
|
||||
{
|
||||
_logger.Info("Closing HDHR live stream");
|
||||
_liveStreamCancellationTokenSource.Cancel();
|
||||
|
||||
return _liveStreamTaskCompletionSource.Task;
|
||||
|
|
|
@ -153,10 +153,5 @@ namespace MediaBrowser.Server.Implementations.LiveTv.TunerHosts
|
|||
{
|
||||
return Task.FromResult(true);
|
||||
}
|
||||
|
||||
public string ApplyDuration(string streamPath, TimeSpan duration)
|
||||
{
|
||||
return streamPath;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -2530,38 +2530,111 @@ namespace MediaBrowser.Server.Implementations.Persistence
|
|||
whereClauses.Add("IsOffline=@IsOffline");
|
||||
cmd.Parameters.Add(cmd, "@IsOffline", DbType.Boolean).Value = query.IsOffline;
|
||||
}
|
||||
if (query.IsMovie.HasValue)
|
||||
{
|
||||
var alternateTypes = new List<string>();
|
||||
if (query.IncludeItemTypes.Length == 0 || query.IncludeItemTypes.Contains(typeof(Movie).Name))
|
||||
{
|
||||
alternateTypes.Add(typeof(Movie).FullName);
|
||||
}
|
||||
if (query.IncludeItemTypes.Length == 0 || query.IncludeItemTypes.Contains(typeof(Trailer).Name))
|
||||
{
|
||||
alternateTypes.Add(typeof(Trailer).FullName);
|
||||
}
|
||||
|
||||
if (alternateTypes.Count == 0)
|
||||
{
|
||||
whereClauses.Add("IsMovie=@IsMovie");
|
||||
}
|
||||
else
|
||||
{
|
||||
whereClauses.Add("(IsMovie is null OR IsMovie=@IsMovie)");
|
||||
}
|
||||
cmd.Parameters.Add(cmd, "@IsMovie", DbType.Boolean).Value = query.IsMovie;
|
||||
}
|
||||
if (query.IsKids.HasValue)
|
||||
var exclusiveProgramAttribtues = !(query.IsMovie ?? true) ||
|
||||
!(query.IsSports ?? true) ||
|
||||
!(query.IsKids ?? true) ||
|
||||
!(query.IsNews ?? true) ||
|
||||
!(query.IsSeries ?? true);
|
||||
|
||||
if (exclusiveProgramAttribtues)
|
||||
{
|
||||
whereClauses.Add("IsKids=@IsKids");
|
||||
cmd.Parameters.Add(cmd, "@IsKids", DbType.Boolean).Value = query.IsKids;
|
||||
if (query.IsMovie.HasValue)
|
||||
{
|
||||
var alternateTypes = new List<string>();
|
||||
if (query.IncludeItemTypes.Length == 0 || query.IncludeItemTypes.Contains(typeof(Movie).Name))
|
||||
{
|
||||
alternateTypes.Add(typeof(Movie).FullName);
|
||||
}
|
||||
if (query.IncludeItemTypes.Length == 0 || query.IncludeItemTypes.Contains(typeof(Trailer).Name))
|
||||
{
|
||||
alternateTypes.Add(typeof(Trailer).FullName);
|
||||
}
|
||||
|
||||
if (alternateTypes.Count == 0)
|
||||
{
|
||||
whereClauses.Add("IsMovie=@IsMovie");
|
||||
cmd.Parameters.Add(cmd, "@IsMovie", DbType.Boolean).Value = query.IsMovie;
|
||||
}
|
||||
else
|
||||
{
|
||||
whereClauses.Add("(IsMovie is null OR IsMovie=@IsMovie)");
|
||||
cmd.Parameters.Add(cmd, "@IsMovie", DbType.Boolean).Value = query.IsMovie;
|
||||
}
|
||||
}
|
||||
if (query.IsSeries.HasValue)
|
||||
{
|
||||
whereClauses.Add("IsSeries=@IsSeries");
|
||||
cmd.Parameters.Add(cmd, "@IsSeries", DbType.Boolean).Value = query.IsSeries;
|
||||
}
|
||||
if (query.IsNews.HasValue)
|
||||
{
|
||||
whereClauses.Add("IsNews=@IsNews");
|
||||
cmd.Parameters.Add(cmd, "@IsNews", DbType.Boolean).Value = query.IsNews;
|
||||
}
|
||||
if (query.IsKids.HasValue)
|
||||
{
|
||||
whereClauses.Add("IsKids=@IsKids");
|
||||
cmd.Parameters.Add(cmd, "@IsKids", DbType.Boolean).Value = query.IsKids;
|
||||
}
|
||||
if (query.IsSports.HasValue)
|
||||
{
|
||||
whereClauses.Add("IsSports=@IsSports");
|
||||
cmd.Parameters.Add(cmd, "@IsSports", DbType.Boolean).Value = query.IsSports;
|
||||
}
|
||||
}
|
||||
if (query.IsSports.HasValue)
|
||||
else
|
||||
{
|
||||
whereClauses.Add("IsSports=@IsSports");
|
||||
cmd.Parameters.Add(cmd, "@IsSports", DbType.Boolean).Value = query.IsSports;
|
||||
var programAttribtues = new List<string>();
|
||||
if (query.IsMovie ?? false)
|
||||
{
|
||||
var alternateTypes = new List<string>();
|
||||
if (query.IncludeItemTypes.Length == 0 || query.IncludeItemTypes.Contains(typeof(Movie).Name))
|
||||
{
|
||||
alternateTypes.Add(typeof(Movie).FullName);
|
||||
}
|
||||
if (query.IncludeItemTypes.Length == 0 || query.IncludeItemTypes.Contains(typeof(Trailer).Name))
|
||||
{
|
||||
alternateTypes.Add(typeof(Trailer).FullName);
|
||||
}
|
||||
|
||||
if (alternateTypes.Count == 0)
|
||||
{
|
||||
programAttribtues.Add("IsMovie=@IsMovie");
|
||||
}
|
||||
else
|
||||
{
|
||||
programAttribtues.Add("(IsMovie is null OR IsMovie=@IsMovie)");
|
||||
}
|
||||
|
||||
cmd.Parameters.Add(cmd, "@IsMovie", DbType.Boolean).Value = true;
|
||||
}
|
||||
if (query.IsSports ?? false)
|
||||
{
|
||||
programAttribtues.Add("IsSports=@IsSports");
|
||||
cmd.Parameters.Add(cmd, "@IsSports", DbType.Boolean).Value = true;
|
||||
}
|
||||
if (query.IsNews ?? false)
|
||||
{
|
||||
programAttribtues.Add("IsNews=@IsNews");
|
||||
cmd.Parameters.Add(cmd, "@IsNews", DbType.Boolean).Value = true;
|
||||
}
|
||||
if (query.IsSeries ?? false)
|
||||
{
|
||||
programAttribtues.Add("IsSeries=@IsSeries");
|
||||
cmd.Parameters.Add(cmd, "@IsSeries", DbType.Boolean).Value = true;
|
||||
}
|
||||
if (query.IsKids ?? false)
|
||||
{
|
||||
programAttribtues.Add("IsKids=@IsKids");
|
||||
cmd.Parameters.Add(cmd, "@IsKids", DbType.Boolean).Value = true;
|
||||
}
|
||||
if (programAttribtues.Count > 0)
|
||||
{
|
||||
whereClauses.Add("("+string.Join(" OR ", programAttribtues.ToArray())+")");
|
||||
}
|
||||
}
|
||||
|
||||
if (query.IsFolder.HasValue)
|
||||
{
|
||||
whereClauses.Add("IsFolder=@IsFolder");
|
||||
|
|
|
@ -818,7 +818,7 @@ namespace MediaBrowser.Server.Implementations.Session
|
|||
{
|
||||
try
|
||||
{
|
||||
await _mediaSourceManager.CloseLiveStream(info.LiveStreamId, CancellationToken.None).ConfigureAwait(false);
|
||||
await _mediaSourceManager.CloseLiveStream(info.LiveStreamId).ConfigureAwait(false);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
|
|
|
@ -150,7 +150,7 @@ namespace MediaBrowser.Server.Implementations.Sync
|
|||
}
|
||||
}
|
||||
|
||||
public Task CloseMediaSource(string liveStreamId, CancellationToken cancellationToken)
|
||||
public Task CloseMediaSource(string liveStreamId)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
|
|
@ -289,7 +289,7 @@ namespace MediaBrowser.WebDashboard.Api
|
|||
return list;
|
||||
}
|
||||
|
||||
private List<Tuple<string,bool>> GetDeployIgnoreFilenames()
|
||||
private List<Tuple<string, bool>> GetDeployIgnoreFilenames()
|
||||
{
|
||||
var list = new List<Tuple<string, bool>>();
|
||||
|
||||
|
@ -313,8 +313,11 @@ namespace MediaBrowser.WebDashboard.Api
|
|||
|
||||
public async Task<object> Get(GetDashboardPackage request)
|
||||
{
|
||||
var path = Path.Combine(_serverConfigurationManager.ApplicationPaths.ProgramDataPath,
|
||||
"webclient-dump");
|
||||
var mode = request.Mode;
|
||||
|
||||
var path = string.Equals(mode, "cordova", StringComparison.OrdinalIgnoreCase) ?
|
||||
Path.Combine(_serverConfigurationManager.ApplicationPaths.ProgramDataPath, "webclient-dump")
|
||||
: "C:\\dev\\emby-web-mobile\\src";
|
||||
|
||||
try
|
||||
{
|
||||
|
@ -333,8 +336,6 @@ namespace MediaBrowser.WebDashboard.Api
|
|||
|
||||
var appVersion = _appHost.ApplicationVersion.ToString();
|
||||
|
||||
var mode = request.Mode;
|
||||
|
||||
// Try to trim the output size a bit
|
||||
var bowerPath = Path.Combine(path, "bower_components");
|
||||
|
||||
|
@ -372,11 +373,6 @@ namespace MediaBrowser.WebDashboard.Api
|
|||
// Delete things that are unneeded in an attempt to keep the output as trim as possible
|
||||
_fileSystem.DeleteDirectory(Path.Combine(path, "css", "images", "tour"), true);
|
||||
}
|
||||
else
|
||||
{
|
||||
MinifyCssDirectory(path);
|
||||
MinifyJsDirectory(path);
|
||||
}
|
||||
|
||||
await DumpHtml(creator.DashboardUIPath, path, mode, culture, appVersion);
|
||||
|
||||
|
@ -444,78 +440,6 @@ namespace MediaBrowser.WebDashboard.Api
|
|||
}
|
||||
}
|
||||
|
||||
private void MinifyCssDirectory(string path)
|
||||
{
|
||||
foreach (var file in Directory.GetFiles(path, "*.css", SearchOption.AllDirectories))
|
||||
{
|
||||
if (file.IndexOf(".min.", StringComparison.OrdinalIgnoreCase) != -1)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
if (file.IndexOf("bower_", StringComparison.OrdinalIgnoreCase) != -1)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
try
|
||||
{
|
||||
var text = _fileSystem.ReadAllText(file, Encoding.UTF8);
|
||||
|
||||
var result = new KristensenCssMinifier().Minify(text, false, Encoding.UTF8);
|
||||
|
||||
if (result.Errors.Count > 0)
|
||||
{
|
||||
Logger.Error("Error minifying css: " + result.Errors[0].Message);
|
||||
}
|
||||
else
|
||||
{
|
||||
text = result.MinifiedContent;
|
||||
_fileSystem.WriteAllText(file, text, Encoding.UTF8);
|
||||
}
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
Logger.ErrorException("Error minifying css", ex);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void MinifyJsDirectory(string path)
|
||||
{
|
||||
foreach (var file in Directory.GetFiles(path, "*.js", SearchOption.AllDirectories))
|
||||
{
|
||||
if (file.IndexOf(".min.", StringComparison.OrdinalIgnoreCase) != -1)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
if (file.IndexOf("bower_", StringComparison.OrdinalIgnoreCase) != -1)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
try
|
||||
{
|
||||
var text = _fileSystem.ReadAllText(file, Encoding.UTF8);
|
||||
|
||||
var result = new CrockfordJsMinifier().Minify(text, false, Encoding.UTF8);
|
||||
|
||||
if (result.Errors.Count > 0)
|
||||
{
|
||||
Logger.Error("Error minifying javascript: " + result.Errors[0].Message);
|
||||
}
|
||||
else
|
||||
{
|
||||
text = result.MinifiedContent;
|
||||
_fileSystem.WriteAllText(file, text, Encoding.UTF8);
|
||||
}
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
Logger.ErrorException("Error minifying css", ex);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private async Task DumpHtml(string source, string destination, string mode, string culture, string appVersion)
|
||||
{
|
||||
foreach (var file in Directory.GetFiles(source, "*", SearchOption.TopDirectoryOnly))
|
||||
|
@ -528,7 +452,7 @@ namespace MediaBrowser.WebDashboard.Api
|
|||
|
||||
private async Task DumpFile(string resourceVirtualPath, string destinationFilePath, string mode, string culture, string appVersion)
|
||||
{
|
||||
using (var stream = await GetPackageCreator().GetResource(resourceVirtualPath, mode, culture, appVersion, true).ConfigureAwait(false))
|
||||
using (var stream = await GetPackageCreator().GetResource(resourceVirtualPath, mode, culture, appVersion, false).ConfigureAwait(false))
|
||||
{
|
||||
using (var fs = _fileSystem.GetFileStream(destinationFilePath, FileMode.Create, FileAccess.Write, FileShare.Read))
|
||||
{
|
||||
|
|
Loading…
Reference in New Issue
Block a user