diff options
| author | Luke Pulverenti <luke.pulverenti@gmail.com> | 2016-10-09 03:18:43 -0400 |
|---|---|---|
| committer | Luke Pulverenti <luke.pulverenti@gmail.com> | 2016-10-09 03:18:43 -0400 |
| commit | daaae69df575f1d7692ba29d6f5ddd4c59516f82 (patch) | |
| tree | 24c818ece042d36808fd0a68834b2853bf4512e1 /MediaBrowser.Server.Implementations/LiveTv | |
| parent | b3595eab6a94fda4f81f637007b2ac79e8a85065 (diff) | |
add playback of in-progress recordings
Diffstat (limited to 'MediaBrowser.Server.Implementations/LiveTv')
4 files changed, 154 insertions, 26 deletions
diff --git a/MediaBrowser.Server.Implementations/LiveTv/EmbyTV/EmbyTV.cs b/MediaBrowser.Server.Implementations/LiveTv/EmbyTV/EmbyTV.cs index 23066149a..ee8d40797 100644 --- a/MediaBrowser.Server.Implementations/LiveTv/EmbyTV/EmbyTV.cs +++ b/MediaBrowser.Server.Implementations/LiveTv/EmbyTV/EmbyTV.cs @@ -28,6 +28,7 @@ using System.Threading.Tasks; using System.Xml; using CommonIO; using MediaBrowser.Common.Extensions; +using MediaBrowser.Controller; using MediaBrowser.Controller.Entities; using MediaBrowser.Controller.Entities.TV; using MediaBrowser.Model.Configuration; @@ -38,7 +39,7 @@ namespace MediaBrowser.Server.Implementations.LiveTv.EmbyTV { public class EmbyTV : ILiveTvService, ISupportsDirectStreamProvider, ISupportsNewTimerIds, IDisposable { - private readonly IApplicationHost _appHpst; + private readonly IServerApplicationHost _appHost; private readonly ILogger _logger; private readonly IHttpClient _httpClient; private readonly IServerConfigurationManager _config; @@ -64,11 +65,11 @@ namespace MediaBrowser.Server.Implementations.LiveTv.EmbyTV private readonly ConcurrentDictionary<string, ActiveRecordingInfo> _activeRecordings = new ConcurrentDictionary<string, ActiveRecordingInfo>(StringComparer.OrdinalIgnoreCase); - public EmbyTV(IApplicationHost appHost, ILogger logger, IJsonSerializer jsonSerializer, IHttpClient httpClient, IServerConfigurationManager config, ILiveTvManager liveTvManager, IFileSystem fileSystem, ILibraryManager libraryManager, ILibraryMonitor libraryMonitor, IProviderManager providerManager, IFileOrganizationService organizationService, IMediaEncoder mediaEncoder) + public EmbyTV(IServerApplicationHost appHost, ILogger logger, IJsonSerializer jsonSerializer, IHttpClient httpClient, IServerConfigurationManager config, ILiveTvManager liveTvManager, IFileSystem fileSystem, ILibraryManager libraryManager, ILibraryMonitor libraryMonitor, IProviderManager providerManager, IFileOrganizationService organizationService, IMediaEncoder mediaEncoder) { Current = this; - _appHpst = appHost; + _appHost = appHost; _logger = logger; _httpClient = httpClient; _config = config; @@ -293,7 +294,7 @@ namespace MediaBrowser.Server.Implementations.LiveTv.EmbyTV status.Tuners = list; status.Status = LiveTvServiceStatus.Ok; - status.Version = _appHpst.ApplicationVersion.ToString(); + status.Version = _appHost.ApplicationVersion.ToString(); status.IsVisible = false; return status; } @@ -659,7 +660,63 @@ namespace MediaBrowser.Server.Implementations.LiveTv.EmbyTV public async Task<IEnumerable<RecordingInfo>> GetRecordingsAsync(CancellationToken cancellationToken) { - return new List<RecordingInfo>(); + return _activeRecordings.Values.ToList().Select(GetRecordingInfo).ToList(); + } + + public string GetActiveRecordingPath(string id) + { + ActiveRecordingInfo info; + + if (_activeRecordings.TryGetValue(id, out info)) + { + return info.Path; + } + return null; + } + + private RecordingInfo GetRecordingInfo(ActiveRecordingInfo info) + { + var timer = info.Timer; + var program = info.Program; + + var result = new RecordingInfo + { + ChannelId = timer.ChannelId, + CommunityRating = timer.CommunityRating, + DateLastUpdated = DateTime.UtcNow, + EndDate = timer.EndDate, + EpisodeTitle = timer.EpisodeTitle, + Genres = timer.Genres, + Id = "recording" + timer.Id, + IsKids = timer.IsKids, + IsMovie = timer.IsMovie, + IsNews = timer.IsNews, + IsRepeat = timer.IsRepeat, + IsSeries = timer.IsProgramSeries, + IsSports = timer.IsSports, + Name = timer.Name, + OfficialRating = timer.OfficialRating, + OriginalAirDate = timer.OriginalAirDate, + Overview = timer.Overview, + ProgramId = timer.ProgramId, + SeriesTimerId = timer.SeriesTimerId, + StartDate = timer.StartDate, + Status = RecordingStatus.InProgress, + TimerId = timer.Id + }; + + if (program != null) + { + result.Audio = program.Audio; + result.ImagePath = program.ImagePath; + result.ImageUrl = program.ImageUrl; + result.IsHD = program.IsHD; + result.IsLive = program.IsLive; + result.IsPremiere = program.IsPremiere; + result.ShowId = program.ShowId; + } + + return result; } public Task<IEnumerable<TimerInfo>> GetTimersAsync(CancellationToken cancellationToken) @@ -954,7 +1011,31 @@ namespace MediaBrowser.Server.Implementations.LiveTv.EmbyTV public Task<List<MediaSourceInfo>> GetRecordingStreamMediaSources(string recordingId, CancellationToken cancellationToken) { - throw new NotImplementedException(); + ActiveRecordingInfo info; + + recordingId = recordingId.Replace("recording", string.Empty); + + if (_activeRecordings.TryGetValue(recordingId, out info)) + { + return Task.FromResult(new List<MediaSourceInfo> + { + new MediaSourceInfo + { + Path = _appHost.GetLocalApiUrl("localhost") + "/LiveTv/LiveRecordings/" + recordingId + "/stream", + Id = recordingId, + SupportsDirectPlay = false, + SupportsDirectStream = true, + SupportsTranscoding = true, + IsInfiniteStream = true, + RequiresOpening = false, + RequiresClosing = false, + Protocol = Model.MediaInfo.MediaProtocol.Http, + BufferMs = 0 + } + }); + } + + throw new FileNotFoundException(); } public async Task CloseLiveStream(string id, CancellationToken cancellationToken) @@ -1031,7 +1112,7 @@ namespace MediaBrowser.Server.Implementations.LiveTv.EmbyTV var activeRecordingInfo = new ActiveRecordingInfo { CancellationTokenSource = new CancellationTokenSource(), - TimerId = timer.Id + Timer = timer }; if (_activeRecordings.TryAdd(timer.Id, activeRecordingInfo)) @@ -1168,6 +1249,7 @@ namespace MediaBrowser.Server.Implementations.LiveTv.EmbyTV if (programInfo != null) { RecordingHelper.CopyProgramInfoToTimerInfo(programInfo, timer); + activeRecordingInfo.Program = programInfo; } string seriesPath = null; @@ -1394,7 +1476,10 @@ namespace MediaBrowser.Server.Implementations.LiveTv.EmbyTV return true; } - var hasRecordingAtPath = _activeRecordings.Values.ToList().Any(i => string.Equals(i.Path, path, StringComparison.OrdinalIgnoreCase) && !string.Equals(i.TimerId, timerId, StringComparison.OrdinalIgnoreCase)); + var hasRecordingAtPath = _activeRecordings + .Values + .ToList() + .Any(i => string.Equals(i.Path, path, StringComparison.OrdinalIgnoreCase) && !string.Equals(i.Timer.Id, timerId, StringComparison.OrdinalIgnoreCase)); if (hasRecordingAtPath) { @@ -1878,7 +1963,8 @@ namespace MediaBrowser.Server.Implementations.LiveTv.EmbyTV class ActiveRecordingInfo { public string Path { get; set; } - public string TimerId { get; set; } + public TimerInfo Timer { get; set; } + public ProgramInfo Program { get; set; } public CancellationTokenSource CancellationTokenSource { get; set; } } } diff --git a/MediaBrowser.Server.Implementations/LiveTv/LiveTvDtoService.cs b/MediaBrowser.Server.Implementations/LiveTv/LiveTvDtoService.cs index 2189cf627..8c46b4597 100644 --- a/MediaBrowser.Server.Implementations/LiveTv/LiveTvDtoService.cs +++ b/MediaBrowser.Server.Implementations/LiveTv/LiveTvDtoService.cs @@ -10,6 +10,7 @@ using MediaBrowser.Model.LiveTv; using MediaBrowser.Model.Logging; using System; using System.Collections.Generic; +using System.Linq; using System.Threading; using System.Threading.Tasks; @@ -125,6 +126,34 @@ namespace MediaBrowser.Server.Implementations.LiveTv dto.DayPattern = info.Days == null ? null : GetDayPattern(info.Days); + if (!string.IsNullOrWhiteSpace(info.SeriesId)) + { + var program = _libraryManager.GetItemList(new InternalItemsQuery + { + IncludeItemTypes = new string[] { typeof(LiveTvProgram).Name }, + ExternalSeriesId = info.SeriesId, + Limit = 1, + ImageTypes = new ImageType[] { ImageType.Primary } + + }).FirstOrDefault(); + + if (program != null) + { + var image = program.GetImageInfo(ImageType.Primary, 0); + if (image != null) + { + try + { + dto.ParentPrimaryImageTag = _imageProcessor.GetImageCacheTag(program, image); + dto.ParentPrimaryImageItemId = program.Id.ToString("N"); + } + catch (Exception ex) + { + } + } + } + } + return dto; } diff --git a/MediaBrowser.Server.Implementations/LiveTv/LiveTvManager.cs b/MediaBrowser.Server.Implementations/LiveTv/LiveTvManager.cs index 93d8f8ef4..cf441f58e 100644 --- a/MediaBrowser.Server.Implementations/LiveTv/LiveTvManager.cs +++ b/MediaBrowser.Server.Implementations/LiveTv/LiveTvManager.cs @@ -235,20 +235,20 @@ namespace MediaBrowser.Server.Implementations.LiveTv return await GetLiveStream(id, mediaSourceId, true, cancellationToken).ConfigureAwait(false); } - public async Task<IEnumerable<MediaSourceInfo>> GetRecordingMediaSources(string id, CancellationToken cancellationToken) + public async Task<IEnumerable<MediaSourceInfo>> GetRecordingMediaSources(IHasMediaSources item, CancellationToken cancellationToken) { - var item = await GetInternalRecording(id, cancellationToken).ConfigureAwait(false); - var service = GetService(item); + var baseItem = (BaseItem)item; + var service = GetService(baseItem); - return await service.GetRecordingStreamMediaSources(id, cancellationToken).ConfigureAwait(false); + return await service.GetRecordingStreamMediaSources(baseItem.ExternalId, cancellationToken).ConfigureAwait(false); } - public async Task<IEnumerable<MediaSourceInfo>> GetChannelMediaSources(string id, CancellationToken cancellationToken) + public async Task<IEnumerable<MediaSourceInfo>> GetChannelMediaSources(IHasMediaSources item, CancellationToken cancellationToken) { - var item = GetInternalChannel(id); - var service = GetService(item); + var baseItem = (LiveTvChannel)item; + var service = GetService(baseItem); - var sources = await service.GetChannelStreamMediaSources(item.ExternalId, cancellationToken).ConfigureAwait(false); + var sources = await service.GetChannelStreamMediaSources(baseItem.ExternalId, cancellationToken).ConfigureAwait(false); if (sources.Count == 0) { @@ -259,7 +259,7 @@ namespace MediaBrowser.Server.Implementations.LiveTv foreach (var source in list) { - Normalize(source, service, item.ChannelType == ChannelType.TV); + Normalize(source, service, baseItem.ChannelType == ChannelType.TV); } return list; @@ -738,6 +738,7 @@ namespace MediaBrowser.Server.Implementations.LiveTv recording.IsRepeat = info.IsRepeat; recording.IsSports = info.IsSports; recording.SeriesTimerId = info.SeriesTimerId; + recording.TimerId = info.TimerId; recording.StartDate = info.StartDate; if (!dataChanged) @@ -1083,10 +1084,13 @@ namespace MediaBrowser.Server.Implementations.LiveTv if (timer != null) { - program.TimerId = _tvDtoService.GetInternalTimerId(serviceName, timer.Id) - .ToString("N"); + if (timer.Status != RecordingStatus.Cancelled && timer.Status != RecordingStatus.Error) + { + program.TimerId = _tvDtoService.GetInternalTimerId(serviceName, timer.Id) + .ToString("N"); - program.TimerStatus = timer.Status; + program.Status = timer.Status.ToString(); + } if (!string.IsNullOrEmpty(timer.SeriesTimerId)) { @@ -1432,7 +1436,7 @@ namespace MediaBrowser.Server.Implementations.LiveTv private DateTime _lastRecordingRefreshTime; private async Task RefreshRecordings(CancellationToken cancellationToken) { - const int cacheMinutes = 5; + const int cacheMinutes = 3; if ((DateTime.UtcNow - _lastRecordingRefreshTime).TotalMinutes < cacheMinutes) { @@ -1482,7 +1486,12 @@ namespace MediaBrowser.Server.Implementations.LiveTv private QueryResult<BaseItem> GetEmbyRecordings(RecordingQuery query, DtoOptions dtoOptions, User user) { - if (user == null || (query.IsInProgress ?? false)) + if (user == null) + { + return new QueryResult<BaseItem>(); + } + + if ((query.IsInProgress ?? false)) { return new QueryResult<BaseItem>(); } @@ -1628,7 +1637,7 @@ namespace MediaBrowser.Server.Implementations.LiveTv return new QueryResult<BaseItem>(); } - if (_services.Count == 1) + if (_services.Count == 1 && !(query.IsInProgress ?? false)) { return GetEmbyRecordings(query, new DtoOptions(), user); } @@ -1824,6 +1833,10 @@ namespace MediaBrowser.Server.Implementations.LiveTv ? null : _tvDtoService.GetInternalSeriesTimerId(service.Name, info.SeriesTimerId).ToString("N"); + dto.TimerId = string.IsNullOrEmpty(info.TimerId) + ? null + : _tvDtoService.GetInternalTimerId(service.Name, info.TimerId).ToString("N"); + dto.StartDate = info.StartDate; dto.RecordingStatus = info.Status; dto.IsRepeat = info.IsRepeat; diff --git a/MediaBrowser.Server.Implementations/LiveTv/LiveTvMediaSourceProvider.cs b/MediaBrowser.Server.Implementations/LiveTv/LiveTvMediaSourceProvider.cs index ff9b2a143..521f33e1c 100644 --- a/MediaBrowser.Server.Implementations/LiveTv/LiveTvMediaSourceProvider.cs +++ b/MediaBrowser.Server.Implementations/LiveTv/LiveTvMediaSourceProvider.cs @@ -65,12 +65,12 @@ namespace MediaBrowser.Server.Implementations.LiveTv { if (item is ILiveTvRecording) { - sources = await _liveTvManager.GetRecordingMediaSources(item.Id.ToString("N"), cancellationToken) + sources = await _liveTvManager.GetRecordingMediaSources(item, cancellationToken) .ConfigureAwait(false); } else { - sources = await _liveTvManager.GetChannelMediaSources(item.Id.ToString("N"), cancellationToken) + sources = await _liveTvManager.GetChannelMediaSources(item, cancellationToken) .ConfigureAwait(false); } } |
