rework active recordings

pull/1154/head
Luke Pulverenti 7 years ago
parent 82ab91f209
commit afd94407f9

@ -411,6 +411,21 @@ namespace Emby.Server.Implementations.Dto
{ {
liveTvManager.AddInfoToRecordingDto(item, dto, user); liveTvManager.AddInfoToRecordingDto(item, dto, user);
} }
else
{
var activeRecording = liveTvManager.GetActiveRecordingInfo(item.Path);
if (activeRecording != null)
{
dto.Type = "Recording";
dto.CanDownload = false;
if (!string.IsNullOrWhiteSpace(dto.SeriesName))
{
dto.EpisodeTitle = dto.Name;
dto.Name = dto.SeriesName;
}
liveTvManager.AddInfoToRecordingDto(item, dto, activeRecording, user);
}
}
return dto; return dto;
} }

@ -830,6 +830,9 @@ namespace Emby.Server.Implementations.LiveTv.EmbyTV
existingTimer.IsKids = updatedTimer.IsKids; existingTimer.IsKids = updatedTimer.IsKids;
existingTimer.IsNews = updatedTimer.IsNews; existingTimer.IsNews = updatedTimer.IsNews;
existingTimer.IsMovie = updatedTimer.IsMovie; existingTimer.IsMovie = updatedTimer.IsMovie;
existingTimer.IsSeries = updatedTimer.IsSeries;
existingTimer.IsLive = updatedTimer.IsLive;
existingTimer.IsPremiere = updatedTimer.IsPremiere;
existingTimer.IsProgramSeries = updatedTimer.IsProgramSeries; existingTimer.IsProgramSeries = updatedTimer.IsProgramSeries;
existingTimer.IsRepeat = updatedTimer.IsRepeat; existingTimer.IsRepeat = updatedTimer.IsRepeat;
existingTimer.IsSports = updatedTimer.IsSports; existingTimer.IsSports = updatedTimer.IsSports;
@ -861,7 +864,8 @@ namespace Emby.Server.Implementations.LiveTv.EmbyTV
public async Task<IEnumerable<RecordingInfo>> GetRecordingsAsync(CancellationToken cancellationToken) public async Task<IEnumerable<RecordingInfo>> GetRecordingsAsync(CancellationToken cancellationToken)
{ {
return _activeRecordings.Values.ToList().Select(GetRecordingInfo).ToList(); return new List<RecordingInfo>();
//return _activeRecordings.Values.ToList().Select(GetRecordingInfo).ToList();
} }
public string GetActiveRecordingPath(string id) public string GetActiveRecordingPath(string id)
@ -875,6 +879,28 @@ namespace Emby.Server.Implementations.LiveTv.EmbyTV
return null; return null;
} }
public IEnumerable<ActiveRecordingInfo> GetAllActiveRecordings()
{
return _activeRecordings.Values;
}
public ActiveRecordingInfo GetActiveRecordingInfo(string path)
{
if (string.IsNullOrWhiteSpace(path))
{
return null;
}
foreach (var recording in _activeRecordings.Values)
{
if (string.Equals(recording.Path, path, StringComparison.Ordinal))
{
return recording;
}
}
return null;
}
private RecordingInfo GetRecordingInfo(ActiveRecordingInfo info) private RecordingInfo GetRecordingInfo(ActiveRecordingInfo info)
{ {
var timer = info.Timer; var timer = info.Timer;
@ -1245,6 +1271,33 @@ namespace Emby.Server.Implementations.LiveTv.EmbyTV
throw new FileNotFoundException(); throw new FileNotFoundException();
} }
public async Task<List<MediaSourceInfo>> GetRecordingStreamMediaSources(ActiveRecordingInfo info, CancellationToken cancellationToken)
{
var stream = new MediaSourceInfo
{
Path = _appHost.GetLocalApiUrl("127.0.0.1") + "/LiveTv/LiveRecordings/" + info.Id + "/stream",
Id = info.Id,
SupportsDirectPlay = false,
SupportsDirectStream = true,
SupportsTranscoding = true,
IsInfiniteStream = true,
RequiresOpening = false,
RequiresClosing = false,
Protocol = MediaBrowser.Model.MediaInfo.MediaProtocol.Http,
BufferMs = 0,
IgnoreDts = true,
IgnoreIndex = true
};
var isAudio = false;
await new LiveStreamHelper(_mediaEncoder, _logger).AddMediaInfoWithProbe(stream, isAudio, cancellationToken).ConfigureAwait(false);
return new List<MediaSourceInfo>
{
stream
};
}
public async Task CloseLiveStream(string id, CancellationToken cancellationToken) public async Task CloseLiveStream(string id, CancellationToken cancellationToken)
{ {
// Ignore the consumer id // Ignore the consumer id
@ -1327,7 +1380,8 @@ namespace Emby.Server.Implementations.LiveTv.EmbyTV
var activeRecordingInfo = new ActiveRecordingInfo var activeRecordingInfo = new ActiveRecordingInfo
{ {
CancellationTokenSource = new CancellationTokenSource(), CancellationTokenSource = new CancellationTokenSource(),
Timer = timer Timer = timer,
Id = timer.Id
}; };
if (_activeRecordings.TryAdd(timer.Id, activeRecordingInfo)) if (_activeRecordings.TryAdd(timer.Id, activeRecordingInfo))
@ -1493,7 +1547,6 @@ namespace Emby.Server.Implementations.LiveTv.EmbyTV
recordPath = recorder.GetOutputPath(mediaStreamInfo, recordPath); recordPath = recorder.GetOutputPath(mediaStreamInfo, recordPath);
recordPath = EnsureFileUnique(recordPath, timer.Id); recordPath = EnsureFileUnique(recordPath, timer.Id);
_libraryManager.RegisterIgnoredPath(recordPath);
_libraryMonitor.ReportFileSystemChangeBeginning(recordPath); _libraryMonitor.ReportFileSystemChangeBeginning(recordPath);
_fileSystem.CreateDirectory(_fileSystem.GetDirectoryName(recordPath)); _fileSystem.CreateDirectory(_fileSystem.GetDirectoryName(recordPath));
activeRecordingInfo.Path = recordPath; activeRecordingInfo.Path = recordPath;
@ -1512,6 +1565,7 @@ namespace Emby.Server.Implementations.LiveTv.EmbyTV
_timerProvider.AddOrUpdate(timer, false); _timerProvider.AddOrUpdate(timer, false);
SaveRecordingMetadata(timer, recordPath, seriesPath); SaveRecordingMetadata(timer, recordPath, seriesPath);
TriggerRefresh(recordPath);
EnforceKeepUpTo(timer, seriesPath); EnforceKeepUpTo(timer, seriesPath);
}; };
@ -1543,7 +1597,7 @@ namespace Emby.Server.Implementations.LiveTv.EmbyTV
} }
} }
_libraryManager.UnRegisterIgnoredPath(recordPath); TriggerRefresh(recordPath);
_libraryMonitor.ReportFileSystemChangeComplete(recordPath, true); _libraryMonitor.ReportFileSystemChangeComplete(recordPath, true);
ActiveRecordingInfo removed; ActiveRecordingInfo removed;
@ -1574,6 +1628,44 @@ namespace Emby.Server.Implementations.LiveTv.EmbyTV
OnRecordingStatusChanged(); OnRecordingStatusChanged();
} }
private void TriggerRefresh(string path)
{
var item = GetAffectedBaseItem(_fileSystem.GetDirectoryName(path));
if (item != null)
{
item.ChangedExternally();
}
}
private BaseItem GetAffectedBaseItem(string path)
{
BaseItem item = null;
while (item == null && !string.IsNullOrEmpty(path))
{
item = _libraryManager.FindByPath(path, null);
path = _fileSystem.GetDirectoryName(path);
}
if (item != null)
{
// If the item has been deleted find the first valid parent that still exists
while (!_fileSystem.DirectoryExists(item.Path) && !_fileSystem.FileExists(item.Path))
{
item = item.GetParent();
if (item == null)
{
break;
}
}
}
return item;
}
private void OnRecordingStatusChanged() private void OnRecordingStatusChanged()
{ {
EventHelper.FireEventIfNotNull(RecordingStatusChanged, this, new RecordingStatusChangedEventArgs EventHelper.FireEventIfNotNull(RecordingStatusChanged, this, new RecordingStatusChangedEventArgs
@ -2621,14 +2713,6 @@ namespace Emby.Server.Implementations.LiveTv.EmbyTV
return list; return list;
} }
class ActiveRecordingInfo
{
public string Path { get; set; }
public TimerInfo Timer { get; set; }
public ProgramInfo Program { get; set; }
public CancellationTokenSource CancellationTokenSource { get; set; }
}
private const int TunerDiscoveryDurationMs = 3000; private const int TunerDiscoveryDurationMs = 3000;
public async Task<List<TunerHostInfo>> DiscoverTuners(bool newDevicesOnly, CancellationToken cancellationToken) public async Task<List<TunerHostInfo>> DiscoverTuners(bool newDevicesOnly, CancellationToken cancellationToken)

@ -58,6 +58,10 @@ namespace Emby.Server.Implementations.LiveTv.EmbyTV
timerInfo.OriginalAirDate = programInfo.OriginalAirDate; timerInfo.OriginalAirDate = programInfo.OriginalAirDate;
timerInfo.IsProgramSeries = programInfo.IsSeries; timerInfo.IsProgramSeries = programInfo.IsSeries;
timerInfo.IsSeries = programInfo.IsSeries;
timerInfo.IsLive = programInfo.IsLive;
timerInfo.IsPremiere = programInfo.IsPremiere;
timerInfo.HomePageUrl = programInfo.HomePageUrl; timerInfo.HomePageUrl = programInfo.HomePageUrl;
timerInfo.CommunityRating = programInfo.CommunityRating; timerInfo.CommunityRating = programInfo.CommunityRating;
timerInfo.Overview = programInfo.Overview; timerInfo.Overview = programInfo.Overview;

@ -60,7 +60,7 @@ namespace Emby.Server.Implementations.LiveTv
private readonly LiveTvDtoService _tvDtoService; private readonly LiveTvDtoService _tvDtoService;
private readonly List<ILiveTvService> _services = new List<ILiveTvService>(); private ILiveTvService[] _services = new ILiveTvService[] { };
private readonly SemaphoreSlim _refreshRecordingsLock = new SemaphoreSlim(1, 1); private readonly SemaphoreSlim _refreshRecordingsLock = new SemaphoreSlim(1, 1);
@ -124,7 +124,7 @@ namespace Emby.Server.Implementations.LiveTv
/// <param name="listingProviders">The listing providers.</param> /// <param name="listingProviders">The listing providers.</param>
public void AddParts(IEnumerable<ILiveTvService> services, IEnumerable<ITunerHost> tunerHosts, IEnumerable<IListingsProvider> listingProviders) public void AddParts(IEnumerable<ILiveTvService> services, IEnumerable<ITunerHost> tunerHosts, IEnumerable<IListingsProvider> listingProviders)
{ {
_services.AddRange(services); _services = services.ToArray();
_tunerHosts.AddRange(tunerHosts); _tunerHosts.AddRange(tunerHosts);
_listingProviders.AddRange(listingProviders); _listingProviders.AddRange(listingProviders);
@ -1221,9 +1221,9 @@ namespace Emby.Server.Implementations.LiveTv
await EmbyTV.EmbyTV.Current.ScanForTunerDeviceChanges(cancellationToken).ConfigureAwait(false); await EmbyTV.EmbyTV.Current.ScanForTunerDeviceChanges(cancellationToken).ConfigureAwait(false);
var numComplete = 0; var numComplete = 0;
double progressPerService = _services.Count == 0 double progressPerService = _services.Length == 0
? 0 ? 0
: 1 / _services.Count; : 1 / _services.Length;
var newChannelIdList = new List<Guid>(); var newChannelIdList = new List<Guid>();
var newProgramIdList = new List<Guid>(); var newProgramIdList = new List<Guid>();
@ -1255,7 +1255,7 @@ namespace Emby.Server.Implementations.LiveTv
numComplete++; numComplete++;
double percent = numComplete; double percent = numComplete;
percent /= _services.Count; percent /= _services.Length;
progress.Report(100 * percent); progress.Report(100 * percent);
} }
@ -1561,11 +1561,6 @@ namespace Emby.Server.Implementations.LiveTv
return new QueryResult<BaseItem>(); return new QueryResult<BaseItem>();
} }
if ((query.IsInProgress ?? false))
{
return new QueryResult<BaseItem>();
}
var folderIds = EmbyTV.EmbyTV.Current.GetRecordingFolders() var folderIds = EmbyTV.EmbyTV.Current.GetRecordingFolders()
.SelectMany(i => i.Locations) .SelectMany(i => i.Locations)
.Distinct(StringComparer.OrdinalIgnoreCase) .Distinct(StringComparer.OrdinalIgnoreCase)
@ -1577,13 +1572,10 @@ namespace Emby.Server.Implementations.LiveTv
var excludeItemTypes = new List<string>(); var excludeItemTypes = new List<string>();
if (!query.IsInProgress.HasValue)
{
folderIds.Add(internalLiveTvFolderId); folderIds.Add(internalLiveTvFolderId);
excludeItemTypes.Add(typeof(LiveTvChannel).Name); excludeItemTypes.Add(typeof(LiveTvChannel).Name);
excludeItemTypes.Add(typeof(LiveTvProgram).Name); excludeItemTypes.Add(typeof(LiveTvProgram).Name);
}
if (folderIds.Count == 0) if (folderIds.Count == 0)
{ {
@ -1632,6 +1624,19 @@ namespace Emby.Server.Implementations.LiveTv
} }
} }
if ((query.IsInProgress ?? false))
{
// TODO: filter
var allActivePaths = EmbyTV.EmbyTV.Current.GetAllActiveRecordings().Select(i => i.Path).ToArray();
var items = allActivePaths.Select(i => _libraryManager.FindByPath(i, false)).Where(i => i != null).ToArray();
return new QueryResult<BaseItem>
{
Items = items,
TotalRecordCount = items.Length
};
}
return _libraryManager.GetItemsResult(new InternalItemsQuery(user) return _libraryManager.GetItemsResult(new InternalItemsQuery(user)
{ {
MediaTypes = new[] { MediaType.Video }, MediaTypes = new[] { MediaType.Video },
@ -1659,11 +1664,6 @@ namespace Emby.Server.Implementations.LiveTv
return new QueryResult<BaseItemDto>(); return new QueryResult<BaseItemDto>();
} }
if (_services.Count > 1)
{
return new QueryResult<BaseItemDto>();
}
if (user == null || (query.IsInProgress ?? false)) if (user == null || (query.IsInProgress ?? false))
{ {
return new QueryResult<BaseItemDto>(); return new QueryResult<BaseItemDto>();
@ -1722,13 +1722,9 @@ namespace Emby.Server.Implementations.LiveTv
var folder = await GetInternalLiveTvFolder(cancellationToken).ConfigureAwait(false); var folder = await GetInternalLiveTvFolder(cancellationToken).ConfigureAwait(false);
if (_services.Count == 1 && (!query.IsInProgress.HasValue || !query.IsInProgress.Value) && (!query.IsLibraryItem.HasValue || query.IsLibraryItem.Value)) // TODO: Figure out how to merge emby recordings + service recordings
if (_services.Length == 1)
{ {
if (!query.IsInProgress.HasValue)
{
await RefreshRecordings(folder.Id, cancellationToken).ConfigureAwait(false);
}
return GetEmbyRecordings(query, options, folder.Id, user); return GetEmbyRecordings(query, options, folder.Id, user);
} }
@ -1920,6 +1916,11 @@ namespace Emby.Server.Implementations.LiveTv
await AddRecordingInfo(programTuples, CancellationToken.None).ConfigureAwait(false); await AddRecordingInfo(programTuples, CancellationToken.None).ConfigureAwait(false);
} }
public ActiveRecordingInfo GetActiveRecordingInfo(string path)
{
return EmbyTV.EmbyTV.Current.GetActiveRecordingInfo(path);
}
public void AddInfoToRecordingDto(BaseItem item, BaseItemDto dto, User user = null) public void AddInfoToRecordingDto(BaseItem item, BaseItemDto dto, User user = null)
{ {
var recording = (ILiveTvRecording)item; var recording = (ILiveTvRecording)item;
@ -1949,27 +1950,72 @@ namespace Emby.Server.Implementations.LiveTv
dto.IsKids = info.IsKids; dto.IsKids = info.IsKids;
dto.IsPremiere = info.IsPremiere; dto.IsPremiere = info.IsPremiere;
dto.CanDelete = user == null if (info.Status == RecordingStatus.InProgress && info.EndDate.HasValue)
? recording.CanDelete()
: recording.CanDelete(user);
if (dto.MediaSources == null)
{ {
dto.MediaSources = recording.GetMediaSources(true); var now = DateTime.UtcNow.Ticks;
var start = info.StartDate.Ticks;
var end = info.EndDate.Value.Ticks;
var pct = now - start;
pct /= end;
pct *= 100;
dto.CompletionPercentage = pct;
} }
if (dto.MediaStreams == null) if (channel != null)
{
dto.ChannelName = channel.Name;
if (channel.HasImage(ImageType.Primary))
{ {
dto.MediaStreams = dto.MediaSources.SelectMany(i => i.MediaStreams).ToArray(); dto.ChannelPrimaryImageTag = _tvDtoService.GetImageTag(channel);
}
}
} }
if (info.Status == RecordingStatus.InProgress && info.EndDate.HasValue) public void AddInfoToRecordingDto(BaseItem item, BaseItemDto dto, ActiveRecordingInfo activeRecordingInfo, User user = null)
{ {
var service = EmbyTV.EmbyTV.Current;
var info = activeRecordingInfo.Timer;
var channel = string.IsNullOrWhiteSpace(info.ChannelId) ? null : GetInternalChannel(_tvDtoService.GetInternalChannelId(service.Name, info.ChannelId));
dto.SeriesTimerId = string.IsNullOrEmpty(info.SeriesTimerId)
? null
: _tvDtoService.GetInternalSeriesTimerId(service.Name, info.SeriesTimerId).ToString("N");
dto.TimerId = string.IsNullOrEmpty(info.Id)
? null
: _tvDtoService.GetInternalTimerId(service.Name, info.Id).ToString("N");
var startDate = info.StartDate;
var endDate = info.EndDate;
dto.StartDate = startDate;
dto.EndDate = endDate;
dto.Status = info.Status.ToString();
dto.IsRepeat = info.IsRepeat;
dto.EpisodeTitle = info.EpisodeTitle;
dto.IsMovie = info.IsMovie;
dto.IsSeries = info.IsSeries;
dto.IsSports = info.IsSports;
dto.IsLive = info.IsLive;
dto.IsNews = info.IsNews;
dto.IsKids = info.IsKids;
dto.IsPremiere = info.IsPremiere;
if (info.Status == RecordingStatus.InProgress)
{
startDate = info.StartDate.AddSeconds(0 - info.PrePaddingSeconds);
endDate = info.EndDate.AddSeconds(info.PostPaddingSeconds);
var now = DateTime.UtcNow.Ticks; var now = DateTime.UtcNow.Ticks;
var start = info.StartDate.Ticks; var start = startDate.Ticks;
var end = info.EndDate.Value.Ticks; var end = endDate.Ticks;
var pct = now - start; var pct = now - start;
pct /= end; pct /= end;
pct *= 100; pct *= 100;
dto.CompletionPercentage = pct; dto.CompletionPercentage = pct;
@ -2098,7 +2144,6 @@ namespace Emby.Server.Implementations.LiveTv
if (service is EmbyTV.EmbyTV) if (service is EmbyTV.EmbyTV)
{ {
// We can't trust that we'll be able to direct stream it through emby server, no matter what the provider says
return service.DeleteRecordingAsync(GetItemExternalId(recording), CancellationToken.None); return service.DeleteRecordingAsync(GetItemExternalId(recording), CancellationToken.None);
} }
@ -2348,7 +2393,6 @@ namespace Emby.Server.Implementations.LiveTv
var currentChannelsDict = new Dictionary<string, BaseItemDto>(); var currentChannelsDict = new Dictionary<string, BaseItemDto>();
var addCurrentProgram = options.AddCurrentProgram; var addCurrentProgram = options.AddCurrentProgram;
var addMediaSources = options.Fields.Contains(ItemFields.MediaSources);
var addServiceName = options.Fields.Contains(ItemFields.ServiceName); var addServiceName = options.Fields.Contains(ItemFields.ServiceName);
foreach (var tuple in tuples) foreach (var tuple in tuples)
@ -2367,11 +2411,6 @@ namespace Emby.Server.Implementations.LiveTv
currentChannelsDict[dto.Id] = dto; currentChannelsDict[dto.Id] = dto;
if (addMediaSources)
{
dto.MediaSources = channel.GetMediaSources(true);
}
if (addCurrentProgram) if (addCurrentProgram)
{ {
var channelIdString = channel.Id.ToString("N"); var channelIdString = channel.Id.ToString("N");

@ -43,9 +43,11 @@ namespace Emby.Server.Implementations.LiveTv
if (baseItem.SourceType == SourceType.LiveTV) if (baseItem.SourceType == SourceType.LiveTV)
{ {
if (string.IsNullOrWhiteSpace(baseItem.Path)) var activeRecordingInfo = _liveTvManager.GetActiveRecordingInfo(item.Path);
if (string.IsNullOrWhiteSpace(baseItem.Path) || activeRecordingInfo != null)
{ {
return GetMediaSourcesInternal(item, cancellationToken); return GetMediaSourcesInternal(item, activeRecordingInfo, cancellationToken);
} }
} }
@ -56,7 +58,7 @@ namespace Emby.Server.Implementations.LiveTv
private const char StreamIdDelimeter = '_'; private const char StreamIdDelimeter = '_';
private const string StreamIdDelimeterString = "_"; private const string StreamIdDelimeterString = "_";
private async Task<IEnumerable<MediaSourceInfo>> GetMediaSourcesInternal(IHasMediaSources item, CancellationToken cancellationToken) private async Task<IEnumerable<MediaSourceInfo>> GetMediaSourcesInternal(IHasMediaSources item, ActiveRecordingInfo activeRecordingInfo, CancellationToken cancellationToken)
{ {
IEnumerable<MediaSourceInfo> sources; IEnumerable<MediaSourceInfo> sources;
@ -70,11 +72,19 @@ namespace Emby.Server.Implementations.LiveTv
.ConfigureAwait(false); .ConfigureAwait(false);
} }
else else
{
if (activeRecordingInfo != null)
{
sources = await EmbyTV.EmbyTV.Current.GetRecordingStreamMediaSources(activeRecordingInfo, cancellationToken)
.ConfigureAwait(false);
}
else
{ {
sources = await _liveTvManager.GetChannelMediaSources(item, cancellationToken) sources = await _liveTvManager.GetChannelMediaSources(item, cancellationToken)
.ConfigureAwait(false); .ConfigureAwait(false);
} }
} }
}
catch (NotImplementedException) catch (NotImplementedException)
{ {
var hasMediaSources = (IHasMediaSources)item; var hasMediaSources = (IHasMediaSources)item;

@ -4,7 +4,7 @@ using MediaBrowser.Model.Entities;
namespace MediaBrowser.Controller.Entities namespace MediaBrowser.Controller.Entities
{ {
public interface IHasMediaSources : IHasUserData public interface IHasMediaSources : IHasMetadata
{ {
/// <summary> /// <summary>
/// Gets the media sources. /// Gets the media sources.

@ -234,6 +234,35 @@ namespace MediaBrowser.Controller.Entities
return LocalAlternateVersions.Select(i => LibraryManager.GetNewItemId(i, typeof(Video))); return LocalAlternateVersions.Select(i => LibraryManager.GetNewItemId(i, typeof(Video)));
} }
[IgnoreDataMember]
public override SourceType SourceType
{
get
{
if (IsActiveRecording())
{
return SourceType.LiveTV;
}
return base.SourceType;
}
}
protected bool IsActiveRecording()
{
return LiveTvManager.GetActiveRecordingInfo(Path) != null;
}
public override bool CanDelete()
{
if (IsActiveRecording())
{
return false;
}
return base.CanDelete();
}
[IgnoreDataMember] [IgnoreDataMember]
protected virtual bool EnableDefaultVideoUserDataKeys protected virtual bool EnableDefaultVideoUserDataKeys
{ {
@ -616,6 +645,14 @@ namespace MediaBrowser.Controller.Entities
var list = GetAllVideosForMediaSources(); var list = GetAllVideosForMediaSources();
var result = list.Select(i => GetVersionInfo(enablePathSubstitution, i.Item1, i.Item2)).ToList(); var result = list.Select(i => GetVersionInfo(enablePathSubstitution, i.Item1, i.Item2)).ToList();
if (IsActiveRecording())
{
foreach (var mediaSource in result)
{
mediaSource.Type = MediaSourceType.Placeholder;
}
}
return result.OrderBy(i => return result.OrderBy(i =>
{ {
if (i.VideoType == VideoType.VideoFile) if (i.VideoType == VideoType.VideoFile)

@ -384,5 +384,9 @@ namespace MediaBrowser.Controller.LiveTv
string GetEmbyTvActiveRecordingPath(string id); string GetEmbyTvActiveRecordingPath(string id);
Task<LiveStream> GetEmbyTvLiveStream(string id); Task<LiveStream> GetEmbyTvLiveStream(string id);
ActiveRecordingInfo GetActiveRecordingInfo(string path);
void AddInfoToRecordingDto(BaseItem item, BaseItemDto dto, ActiveRecordingInfo activeRecordingInfo, User user = null);
} }
} }

@ -36,4 +36,13 @@ namespace MediaBrowser.Controller.LiveTv
DateTime? EndDate { get; set; } DateTime? EndDate { get; set; }
DateTime DateCreated { get; set; } DateTime DateCreated { get; set; }
} }
public class ActiveRecordingInfo
{
public string Id { get; set; }
public string Path { get; set; }
public TimerInfo Timer { get; set; }
public ProgramInfo Program { get; set; }
public CancellationTokenSource CancellationTokenSource { get; set; }
}
} }

@ -109,6 +109,9 @@ namespace MediaBrowser.Controller.LiveTv
public bool IsKids { get; set; } public bool IsKids { get; set; }
public bool IsSports { get; set; } public bool IsSports { get; set; }
public bool IsNews { get; set; } public bool IsNews { get; set; }
public bool IsSeries { get; set; }
public bool IsLive { get; set; }
public bool IsPremiere { get; set; }
public int? ProductionYear { get; set; } public int? ProductionYear { get; set; }
public string EpisodeTitle { get; set; } public string EpisodeTitle { get; set; }
public DateTime? OriginalAirDate { get; set; } public DateTime? OriginalAirDate { get; set; }

Loading…
Cancel
Save