aboutsummaryrefslogtreecommitdiff
path: root/Emby.Server.Implementations/LiveTv
diff options
context:
space:
mode:
authorLuke <luke.pulverenti@gmail.com>2017-09-20 13:22:39 -0400
committerGitHub <noreply@github.com>2017-09-20 13:22:39 -0400
commiteb2a1330045d802bfe0366df7105c220a36f111f (patch)
tree2c1638c424ee9c0837c5de6d6e08a2398da69cdb /Emby.Server.Implementations/LiveTv
parentec426d5c92875639ceac64477ce10fab3e639335 (diff)
parenta015e1208885bc6a8788db683c4fe47e93dc26b7 (diff)
Merge pull request #2897 from MediaBrowser/beta
Beta
Diffstat (limited to 'Emby.Server.Implementations/LiveTv')
-rw-r--r--Emby.Server.Implementations/LiveTv/EmbyTV/DirectRecorder.cs4
-rw-r--r--Emby.Server.Implementations/LiveTv/EmbyTV/EmbyTV.cs402
-rw-r--r--Emby.Server.Implementations/LiveTv/EmbyTV/EncodedRecorder.cs11
-rw-r--r--Emby.Server.Implementations/LiveTv/EmbyTV/EntryPoint.cs4
-rw-r--r--Emby.Server.Implementations/LiveTv/EmbyTV/RecordingHelper.cs61
-rw-r--r--Emby.Server.Implementations/LiveTv/LiveTvDtoService.cs6
-rw-r--r--Emby.Server.Implementations/LiveTv/LiveTvManager.cs80
-rw-r--r--Emby.Server.Implementations/LiveTv/LiveTvMediaSourceProvider.cs2
-rw-r--r--Emby.Server.Implementations/LiveTv/RefreshChannelsScheduledTask.cs2
-rw-r--r--Emby.Server.Implementations/LiveTv/TunerHosts/HdHomerun/HdHomerunHost.cs2
-rw-r--r--Emby.Server.Implementations/LiveTv/TunerHosts/HdHomerun/HdHomerunHttpStream.cs59
-rw-r--r--Emby.Server.Implementations/LiveTv/TunerHosts/HdHomerun/HdHomerunManager.cs1
-rw-r--r--Emby.Server.Implementations/LiveTv/TunerHosts/HdHomerun/HdHomerunUdpStream.cs73
13 files changed, 328 insertions, 379 deletions
diff --git a/Emby.Server.Implementations/LiveTv/EmbyTV/DirectRecorder.cs b/Emby.Server.Implementations/LiveTv/EmbyTV/DirectRecorder.cs
index 2a2e1886f..f0578d9ef 100644
--- a/Emby.Server.Implementations/LiveTv/EmbyTV/DirectRecorder.cs
+++ b/Emby.Server.Implementations/LiveTv/EmbyTV/DirectRecorder.cs
@@ -42,6 +42,8 @@ namespace Emby.Server.Implementations.LiveTv.EmbyTV
private async Task RecordFromDirectStreamProvider(IDirectStreamProvider directStreamProvider, string targetFile, TimeSpan duration, Action onStarted, CancellationToken cancellationToken)
{
+ _fileSystem.CreateDirectory(_fileSystem.GetDirectoryName(targetFile));
+
using (var output = _fileSystem.GetFileStream(targetFile, FileOpenMode.Create, FileAccessMode.Write, FileShareMode.Read))
{
onStarted();
@@ -76,6 +78,8 @@ namespace Emby.Server.Implementations.LiveTv.EmbyTV
{
_logger.Info("Opened recording stream from tuner provider");
+ _fileSystem.CreateDirectory(_fileSystem.GetDirectoryName(targetFile));
+
using (var output = _fileSystem.GetFileStream(targetFile, FileOpenMode.Create, FileAccessMode.Write, FileShareMode.Read))
{
onStarted();
diff --git a/Emby.Server.Implementations/LiveTv/EmbyTV/EmbyTV.cs b/Emby.Server.Implementations/LiveTv/EmbyTV/EmbyTV.cs
index 2e12f46bf..1975a6b01 100644
--- a/Emby.Server.Implementations/LiveTv/EmbyTV/EmbyTV.cs
+++ b/Emby.Server.Implementations/LiveTv/EmbyTV/EmbyTV.cs
@@ -305,26 +305,9 @@ namespace Emby.Server.Implementations.LiveTv.EmbyTV
{
var seriesTimers = await GetSeriesTimersAsync(cancellationToken).ConfigureAwait(false);
- List<ChannelInfo> channels = null;
-
foreach (var timer in seriesTimers)
{
- List<ProgramInfo> epgData;
-
- if (timer.RecordAnyChannel)
- {
- if (channels == null)
- {
- channels = (await GetChannelsAsync(true, CancellationToken.None).ConfigureAwait(false)).ToList();
- }
- var channelIds = channels.Select(i => i.Id).ToList();
- epgData = GetEpgDataForChannels(channelIds);
- }
- else
- {
- epgData = GetEpgDataForChannel(timer.ChannelId);
- }
- await UpdateTimersForSeriesTimer(epgData, timer, false, true).ConfigureAwait(false);
+ await UpdateTimersForSeriesTimer(timer, false, true).ConfigureAwait(false);
}
}
@@ -332,6 +315,8 @@ namespace Emby.Server.Implementations.LiveTv.EmbyTV
{
var timers = await GetTimersAsync(cancellationToken).ConfigureAwait(false);
+ var tempChannelCache = new Dictionary<string, LiveTvChannel>();
+
foreach (var timer in timers)
{
if (DateTime.UtcNow > timer.EndDate && !_activeRecordings.ContainsKey(timer.Id))
@@ -345,15 +330,14 @@ namespace Emby.Server.Implementations.LiveTv.EmbyTV
continue;
}
- var epg = GetEpgDataForChannel(timer.ChannelId);
- var program = epg.FirstOrDefault(i => string.Equals(i.Id, timer.ProgramId, StringComparison.OrdinalIgnoreCase));
+ var program = GetProgramInfoFromCache(timer);
if (program == null)
{
OnTimerOutOfDate(timer);
continue;
}
- RecordingHelper.CopyProgramInfoToTimerInfo(program, timer);
+ CopyProgramInfoToTimerInfo(program, timer, tempChannelCache);
_timerProvider.Update(timer);
}
}
@@ -621,7 +605,7 @@ namespace Emby.Server.Implementations.LiveTv.EmbyTV
ActiveRecordingInfo activeRecordingInfo;
if (_activeRecordings.TryGetValue(timerId, out activeRecordingInfo))
- {
+ {
activeRecordingInfo.Timer = timer;
activeRecordingInfo.CancellationTokenSource.Cancel();
}
@@ -672,11 +656,11 @@ namespace Emby.Server.Implementations.LiveTv.EmbyTV
timer.Id = Guid.NewGuid().ToString("N");
- ProgramInfo programInfo = null;
+ LiveTvProgram programInfo = null;
if (!string.IsNullOrWhiteSpace(timer.ProgramId))
{
- programInfo = GetProgramInfoFromCache(timer.ChannelId, timer.ProgramId);
+ programInfo = GetProgramInfoFromCache(timer);
}
if (programInfo == null)
{
@@ -686,7 +670,7 @@ namespace Emby.Server.Implementations.LiveTv.EmbyTV
if (programInfo != null)
{
- RecordingHelper.CopyProgramInfoToTimerInfo(programInfo, timer);
+ CopyProgramInfoToTimerInfo(programInfo, timer);
}
timer.IsManual = true;
@@ -698,24 +682,12 @@ namespace Emby.Server.Implementations.LiveTv.EmbyTV
{
info.Id = Guid.NewGuid().ToString("N");
- List<ProgramInfo> epgData;
- if (info.RecordAnyChannel)
- {
- var channels = await GetChannelsAsync(true, CancellationToken.None).ConfigureAwait(false);
- var channelIds = channels.Select(i => i.Id).ToList();
- epgData = GetEpgDataForChannels(channelIds);
- }
- else
- {
- epgData = GetEpgDataForChannel(info.ChannelId);
- }
-
// populate info.seriesID
- var program = epgData.FirstOrDefault(i => string.Equals(i.Id, info.ProgramId, StringComparison.OrdinalIgnoreCase));
+ var program = GetProgramInfoFromCache(info.ProgramId);
if (program != null)
{
- info.SeriesId = program.SeriesId;
+ info.SeriesId = program.ExternalSeriesId;
}
else
{
@@ -750,7 +722,7 @@ namespace Emby.Server.Implementations.LiveTv.EmbyTV
_timerProvider.AddOrUpdate(timer, false);
}
- await UpdateTimersForSeriesTimer(epgData, info, true, false).ConfigureAwait(false);
+ await UpdateTimersForSeriesTimer(info, true, false).ConfigureAwait(false);
return info.Id;
}
@@ -779,19 +751,7 @@ namespace Emby.Server.Implementations.LiveTv.EmbyTV
_seriesTimerProvider.Update(instance);
- List<ProgramInfo> epgData;
- if (instance.RecordAnyChannel)
- {
- var channels = await GetChannelsAsync(true, CancellationToken.None).ConfigureAwait(false);
- var channelIds = channels.Select(i => i.Id).ToList();
- epgData = GetEpgDataForChannels(channelIds);
- }
- else
- {
- epgData = GetEpgDataForChannel(instance.ChannelId);
- }
-
- await UpdateTimersForSeriesTimer(epgData, instance, true, true).ConfigureAwait(false);
+ await UpdateTimersForSeriesTimer(instance, true, true).ConfigureAwait(false);
}
}
@@ -962,23 +922,6 @@ namespace Emby.Server.Implementations.LiveTv.EmbyTV
return Task.FromResult((IEnumerable<SeriesTimerInfo>)_seriesTimerProvider.GetAll());
}
- public async Task<IEnumerable<ProgramInfo>> GetProgramsAsync(string channelId, DateTime startDateUtc, DateTime endDateUtc, CancellationToken cancellationToken)
- {
- try
- {
- return await GetProgramsAsyncInternal(channelId, startDateUtc, endDateUtc, cancellationToken).ConfigureAwait(false);
- }
- catch (OperationCanceledException)
- {
- throw;
- }
- catch (Exception ex)
- {
- _logger.ErrorException("Error getting programs", ex);
- return GetEpgDataForChannel(channelId).Where(i => i.StartDate <= endDateUtc && i.EndDate >= startDateUtc);
- }
- }
-
private bool IsListingProviderEnabledForTuner(ListingsProviderInfo info, string tunerHostId)
{
if (info.EnableAllTuners)
@@ -994,7 +937,7 @@ namespace Emby.Server.Implementations.LiveTv.EmbyTV
return info.EnabledTuners.Contains(tunerHostId, StringComparer.OrdinalIgnoreCase);
}
- private async Task<IEnumerable<ProgramInfo>> GetProgramsAsyncInternal(string channelId, DateTime startDateUtc, DateTime endDateUtc, CancellationToken cancellationToken)
+ public async Task<IEnumerable<ProgramInfo>> GetProgramsAsync(string channelId, DateTime startDateUtc, DateTime endDateUtc, CancellationToken cancellationToken)
{
var channels = await GetChannelsAsync(true, cancellationToken).ConfigureAwait(false);
var channel = channels.First(i => string.Equals(i.Id, channelId, StringComparison.OrdinalIgnoreCase));
@@ -1037,8 +980,6 @@ namespace Emby.Server.Implementations.LiveTv.EmbyTV
if (programs.Count > 0)
{
- SaveEpgDataForChannel(channelId, programs);
-
return programs;
}
}
@@ -1464,11 +1405,11 @@ namespace Emby.Server.Implementations.LiveTv.EmbyTV
throw new ArgumentNullException("timer");
}
- ProgramInfo programInfo = null;
+ LiveTvProgram programInfo = null;
if (!string.IsNullOrWhiteSpace(timer.ProgramId))
{
- programInfo = GetProgramInfoFromCache(timer.ChannelId, timer.ProgramId);
+ programInfo = GetProgramInfoFromCache(timer);
}
if (programInfo == null)
{
@@ -1478,8 +1419,8 @@ namespace Emby.Server.Implementations.LiveTv.EmbyTV
if (programInfo != null)
{
- RecordingHelper.CopyProgramInfoToTimerInfo(programInfo, timer);
- activeRecordingInfo.Program = programInfo;
+ CopyProgramInfoToTimerInfo(programInfo, timer);
+ //activeRecordingInfo.Program = programInfo;
}
string seriesPath = null;
@@ -1488,14 +1429,13 @@ namespace Emby.Server.Implementations.LiveTv.EmbyTV
string liveStreamId = null;
- OnRecordingStatusChanged();
-
try
{
var recorder = await GetRecorder().ConfigureAwait(false);
var allMediaSources = await GetChannelStreamMediaSources(timer.ChannelId, CancellationToken.None).ConfigureAwait(false);
+ _logger.Info("Opening recording stream from tuner provider");
var liveStreamInfo = await GetChannelStreamInternal(timer.ChannelId, allMediaSources[0].Id, CancellationToken.None)
.ConfigureAwait(false);
@@ -1509,23 +1449,20 @@ namespace Emby.Server.Implementations.LiveTv.EmbyTV
recordPath = EnsureFileUnique(recordPath, timer.Id);
_libraryMonitor.ReportFileSystemChangeBeginning(recordPath);
- _fileSystem.CreateDirectory(_fileSystem.GetDirectoryName(recordPath));
activeRecordingInfo.Path = recordPath;
var duration = recordingEndDate - DateTime.UtcNow;
- _logger.Info("Beginning recording. Will record for {0} minutes.",
- duration.TotalMinutes.ToString(CultureInfo.InvariantCulture));
+ _logger.Info("Beginning recording. Will record for {0} minutes.", duration.TotalMinutes.ToString(CultureInfo.InvariantCulture));
_logger.Info("Writing file to path: " + recordPath);
- _logger.Info("Opening recording stream from tuner provider");
- Action onStarted = () =>
+ Action onStarted = async () =>
{
timer.Status = RecordingStatus.InProgress;
_timerProvider.AddOrUpdate(timer, false);
- SaveRecordingMetadata(timer, recordPath, seriesPath);
+ await SaveRecordingMetadata(timer, recordPath, seriesPath).ConfigureAwait(false);
TriggerRefresh(recordPath);
EnforceKeepUpTo(timer, seriesPath);
};
@@ -1559,7 +1496,7 @@ namespace Emby.Server.Implementations.LiveTv.EmbyTV
}
TriggerRefresh(recordPath);
- _libraryMonitor.ReportFileSystemChangeComplete(recordPath, true);
+ _libraryMonitor.ReportFileSystemChangeComplete(recordPath, false);
ActiveRecordingInfo removed;
_activeRecordings.TryRemove(timer.Id, out removed);
@@ -1585,17 +1522,29 @@ namespace Emby.Server.Implementations.LiveTv.EmbyTV
{
_timerProvider.Delete(timer);
}
-
- OnRecordingStatusChanged();
}
private void TriggerRefresh(string path)
{
+ _logger.Debug("Triggering refresh on {0}", path);
+
var item = GetAffectedBaseItem(_fileSystem.GetDirectoryName(path));
if (item != null)
{
- item.ChangedExternally();
+ _logger.Debug("Refreshing recording parent {0}", item.Path);
+
+ _providerManager.QueueRefresh(item.Id, new MetadataRefreshOptions(_fileSystem)
+ {
+ ValidateChildren = true,
+ RefreshPaths = new List<string>
+ {
+ path,
+ _fileSystem.GetDirectoryName(path),
+ _fileSystem.GetDirectoryName(_fileSystem.GetDirectoryName(path))
+ }
+
+ }, RefreshPriority.High);
}
}
@@ -1603,6 +1552,8 @@ namespace Emby.Server.Implementations.LiveTv.EmbyTV
{
BaseItem item = null;
+ var parentPath = _fileSystem.GetDirectoryName(path);
+
while (item == null && !string.IsNullOrEmpty(path))
{
item = _libraryManager.FindByPath(path, null);
@@ -1612,14 +1563,12 @@ namespace Emby.Server.Implementations.LiveTv.EmbyTV
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))
+ if (item.GetType() == typeof(Folder) && string.Equals(item.Path, parentPath, StringComparison.OrdinalIgnoreCase))
{
- item = item.GetParent();
-
- if (item == null)
+ var parentItem = item.GetParent();
+ if (parentItem != null && !(parentItem is AggregateFolder))
{
- break;
+ item = parentItem;
}
}
}
@@ -1627,14 +1576,6 @@ namespace Emby.Server.Implementations.LiveTv.EmbyTV
return item;
}
- private void OnRecordingStatusChanged()
- {
- EventHelper.FireEventIfNotNull(RecordingStatusChanged, this, new RecordingStatusChangedEventArgs
- {
-
- }, _logger);
- }
-
private async void EnforceKeepUpTo(TimerInfo timer, string seriesPath)
{
if (string.IsNullOrWhiteSpace(timer.SeriesTimerId))
@@ -1687,8 +1628,7 @@ namespace Emby.Server.Implementations.LiveTv.EmbyTV
var episodesToDelete = (librarySeries.GetItemList(new InternalItemsQuery
{
- SortBy = new[] { ItemSortBy.DateCreated },
- SortOrder = SortOrder.Descending,
+ OrderBy = new[] { new Tuple<string, SortOrder>(ItemSortBy.DateCreated, SortOrder.Descending) },
IsVirtualItem = false,
IsFolder = false,
Recursive = true,
@@ -1810,7 +1750,7 @@ namespace Emby.Server.Implementations.LiveTv.EmbyTV
{
var config = GetConfiguration();
- var regInfo = await _liveTvManager.GetRegistrationInfo("embytvrecordingconversion").ConfigureAwait(false);
+ var regInfo = await _liveTvManager.GetRegistrationInfo("dvr").ConfigureAwait(false);
if (regInfo.IsValid)
{
@@ -2020,7 +1960,7 @@ namespace Emby.Server.Implementations.LiveTv.EmbyTV
}
}
- private async void SaveRecordingMetadata(TimerInfo timer, string recordingPath, string seriesPath)
+ private async Task SaveRecordingMetadata(TimerInfo timer, string recordingPath, string seriesPath)
{
try
{
@@ -2337,18 +2277,49 @@ namespace Emby.Server.Implementations.LiveTv.EmbyTV
}
}
- private ProgramInfo GetProgramInfoFromCache(string channelId, string programId)
+ private LiveTvProgram GetProgramInfoFromCache(string programId)
{
- var epgData = GetEpgDataForChannel(channelId);
- return epgData.FirstOrDefault(p => string.Equals(p.Id, programId, StringComparison.OrdinalIgnoreCase));
+ var query = new InternalItemsQuery
+ {
+ ItemIds = new[] { _liveTvManager.GetInternalProgramId(Name, programId).ToString("N") },
+ Limit = 1,
+ DtoOptions = new DtoOptions()
+ };
+
+ return _libraryManager.GetItemList(query).Cast<LiveTvProgram>().FirstOrDefault();
}
- private ProgramInfo GetProgramInfoFromCache(string channelId, DateTime startDateUtc)
+ private LiveTvProgram GetProgramInfoFromCache(TimerInfo timer)
{
- var epgData = GetEpgDataForChannel(channelId);
- var startDateTicks = startDateUtc.Ticks;
- // Find the first program that starts within 3 minutes
- return epgData.FirstOrDefault(p => Math.Abs(startDateTicks - p.StartDate.Ticks) <= TimeSpan.FromMinutes(3).Ticks);
+ return GetProgramInfoFromCache(timer.ProgramId, timer.ChannelId);
+ }
+
+ private LiveTvProgram GetProgramInfoFromCache(string programId, string channelId)
+ {
+ return GetProgramInfoFromCache(programId);
+ }
+
+ private LiveTvProgram GetProgramInfoFromCache(string channelId, DateTime startDateUtc)
+ {
+ var query = new InternalItemsQuery
+ {
+ IncludeItemTypes = new string[] { typeof(LiveTvProgram).Name },
+ Limit = 1,
+ DtoOptions = new DtoOptions(true)
+ {
+ EnableImages = false
+ },
+ MinStartDate = startDateUtc.AddMinutes(-3),
+ MaxStartDate = startDateUtc.AddMinutes(3),
+ OrderBy = new[] { new Tuple<string, SortOrder>(ItemSortBy.StartDate, SortOrder.Ascending) }
+ };
+
+ if (!string.IsNullOrWhiteSpace(channelId))
+ {
+ query.ChannelIds = new[] { _liveTvManager.GetInternalChannelId(Name, channelId).ToString("N") };
+ }
+
+ return _libraryManager.GetItemList(query).Cast<LiveTvProgram>().FirstOrDefault();
}
private LiveTvOptions GetConfiguration()
@@ -2422,9 +2393,9 @@ namespace Emby.Server.Implementations.LiveTv.EmbyTV
}
}
- private async Task UpdateTimersForSeriesTimer(List<ProgramInfo> epgData, SeriesTimerInfo seriesTimer, bool updateTimerSettings, bool deleteInvalidTimers)
+ private async Task UpdateTimersForSeriesTimer(SeriesTimerInfo seriesTimer, bool updateTimerSettings, bool deleteInvalidTimers)
{
- var allTimers = GetTimersForSeries(seriesTimer, epgData)
+ var allTimers = GetTimersForSeries(seriesTimer)
.ToList();
var registration = await _liveTvManager.GetRegistrationInfo("seriesrecordings").ConfigureAwait(false);
@@ -2521,23 +2492,160 @@ namespace Emby.Server.Implementations.LiveTv.EmbyTV
}
}
- private IEnumerable<TimerInfo> GetTimersForSeries(SeriesTimerInfo seriesTimer, IEnumerable<ProgramInfo> allPrograms)
+ private IEnumerable<TimerInfo> GetTimersForSeries(SeriesTimerInfo seriesTimer)
{
if (seriesTimer == null)
{
throw new ArgumentNullException("seriesTimer");
}
- if (allPrograms == null)
+
+ if (string.IsNullOrWhiteSpace(seriesTimer.SeriesId))
{
- throw new ArgumentNullException("allPrograms");
+ return new List<TimerInfo>();
}
- // Exclude programs that have already ended
- allPrograms = allPrograms.Where(i => i.EndDate > DateTime.UtcNow);
+ var query = new InternalItemsQuery
+ {
+ IncludeItemTypes = new string[] { typeof(LiveTvProgram).Name },
+ ExternalSeriesId = seriesTimer.SeriesId,
+ DtoOptions = new DtoOptions(true)
+ {
+ EnableImages = false
+ },
+ MinEndDate = DateTime.UtcNow
+ };
- allPrograms = GetProgramsForSeries(seriesTimer, allPrograms);
+ if (!seriesTimer.RecordAnyChannel)
+ {
+ query.ChannelIds = new[] { _liveTvManager.GetInternalChannelId(Name, seriesTimer.ChannelId).ToString("N") };
+ }
- return allPrograms.Select(i => RecordingHelper.CreateTimer(i, seriesTimer));
+ var tempChannelCache = new Dictionary<string, LiveTvChannel>();
+
+ return _libraryManager.GetItemList(query).Cast<LiveTvProgram>().Select(i => CreateTimer(i, seriesTimer, tempChannelCache));
+ }
+
+ private TimerInfo CreateTimer(LiveTvProgram parent, SeriesTimerInfo seriesTimer, Dictionary<string, LiveTvChannel> tempChannelCache)
+ {
+ string channelId = seriesTimer.RecordAnyChannel ? null : seriesTimer.ChannelId;
+
+ if (string.IsNullOrWhiteSpace(channelId) && !string.IsNullOrWhiteSpace(parent.ChannelId))
+ {
+ LiveTvChannel channel;
+
+ if (!tempChannelCache.TryGetValue(parent.ChannelId, out channel))
+ {
+ channel = _libraryManager.GetItemList(new InternalItemsQuery
+ {
+ IncludeItemTypes = new string[] { typeof(LiveTvChannel).Name },
+ ItemIds = new[] { parent.ChannelId },
+ DtoOptions = new DtoOptions()
+
+ }).Cast<LiveTvChannel>().FirstOrDefault();
+
+ if (channel != null && !string.IsNullOrWhiteSpace(channel.ExternalId))
+ {
+ tempChannelCache[parent.ChannelId] = channel;
+ }
+ }
+
+ if (channel != null || tempChannelCache.TryGetValue(parent.ChannelId, out channel))
+ {
+ channelId = channel.ExternalId;
+ }
+ }
+
+ var timer = new TimerInfo
+ {
+ ChannelId = channelId,
+ Id = (seriesTimer.Id + parent.ExternalId).GetMD5().ToString("N"),
+ StartDate = parent.StartDate,
+ EndDate = parent.EndDate.Value,
+ ProgramId = parent.ExternalId,
+ PrePaddingSeconds = seriesTimer.PrePaddingSeconds,
+ PostPaddingSeconds = seriesTimer.PostPaddingSeconds,
+ IsPostPaddingRequired = seriesTimer.IsPostPaddingRequired,
+ IsPrePaddingRequired = seriesTimer.IsPrePaddingRequired,
+ KeepUntil = seriesTimer.KeepUntil,
+ Priority = seriesTimer.Priority,
+ Name = parent.Name,
+ Overview = parent.Overview,
+ SeriesId = parent.ExternalSeriesId,
+ SeriesTimerId = seriesTimer.Id,
+ ShowId = parent.ShowId
+ };
+
+ CopyProgramInfoToTimerInfo(parent, timer, tempChannelCache);
+
+ return timer;
+ }
+
+ private void CopyProgramInfoToTimerInfo(LiveTvProgram programInfo, TimerInfo timerInfo)
+ {
+ var tempChannelCache = new Dictionary<string, LiveTvChannel>();
+ CopyProgramInfoToTimerInfo(programInfo, timerInfo, tempChannelCache);
+ }
+
+ private void CopyProgramInfoToTimerInfo(LiveTvProgram programInfo, TimerInfo timerInfo, Dictionary<string, LiveTvChannel> tempChannelCache)
+ {
+ string channelId = null;
+
+ if (!string.IsNullOrWhiteSpace(programInfo.ChannelId))
+ {
+ LiveTvChannel channel;
+
+ if (!tempChannelCache.TryGetValue(programInfo.ChannelId, out channel))
+ {
+ channel = _libraryManager.GetItemList(new InternalItemsQuery
+ {
+ IncludeItemTypes = new string[] { typeof(LiveTvChannel).Name },
+ ItemIds = new[] { programInfo.ChannelId },
+ DtoOptions = new DtoOptions()
+
+ }).Cast<LiveTvChannel>().FirstOrDefault();
+
+ if (channel != null && !string.IsNullOrWhiteSpace(channel.ExternalId))
+ {
+ tempChannelCache[programInfo.ChannelId] = channel;
+ }
+ }
+
+ if (channel != null || tempChannelCache.TryGetValue(programInfo.ChannelId, out channel))
+ {
+ channelId = channel.ExternalId;
+ }
+ }
+
+ timerInfo.Name = programInfo.Name;
+ timerInfo.StartDate = programInfo.StartDate;
+ timerInfo.EndDate = programInfo.EndDate.Value;
+
+ if (!string.IsNullOrWhiteSpace(channelId))
+ {
+ timerInfo.ChannelId = channelId;
+ }
+
+ timerInfo.SeasonNumber = programInfo.ParentIndexNumber;
+ timerInfo.EpisodeNumber = programInfo.IndexNumber;
+ timerInfo.IsMovie = programInfo.IsMovie;
+ timerInfo.IsKids = programInfo.IsKids;
+ timerInfo.IsNews = programInfo.IsNews;
+ timerInfo.IsSports = programInfo.IsSports;
+ timerInfo.ProductionYear = programInfo.ProductionYear;
+ timerInfo.EpisodeTitle = programInfo.EpisodeTitle;
+ timerInfo.OriginalAirDate = programInfo.PremiereDate;
+ timerInfo.IsProgramSeries = programInfo.IsSeries;
+
+ timerInfo.IsSeries = programInfo.IsSeries;
+ timerInfo.IsLive = programInfo.IsLive;
+ timerInfo.IsPremiere = programInfo.IsPremiere;
+
+ timerInfo.HomePageUrl = programInfo.HomePageUrl;
+ timerInfo.CommunityRating = programInfo.CommunityRating;
+ timerInfo.Overview = programInfo.Overview;
+ timerInfo.OfficialRating = programInfo.OfficialRating;
+ timerInfo.IsRepeat = programInfo.IsRepeat;
+ timerInfo.SeriesId = programInfo.ExternalSeriesId;
}
private bool IsProgramAlreadyInLibrary(TimerInfo program)
@@ -2578,51 +2686,6 @@ namespace Emby.Server.Implementations.LiveTv.EmbyTV
return false;
}
- private IEnumerable<ProgramInfo> GetProgramsForSeries(SeriesTimerInfo seriesTimer, IEnumerable<ProgramInfo> allPrograms)
- {
- if (string.IsNullOrWhiteSpace(seriesTimer.SeriesId))
- {
- _logger.Error("seriesTimer.SeriesId is null. Cannot find programs for series");
- return new List<ProgramInfo>();
- }
-
- return allPrograms.Where(i => string.Equals(i.SeriesId, seriesTimer.SeriesId, StringComparison.OrdinalIgnoreCase));
- }
-
- private string GetChannelEpgCachePath(string channelId)
- {
- return Path.Combine(_config.CommonApplicationPaths.CachePath, "embytvepg", channelId + ".json");
- }
-
- private readonly object _epgLock = new object();
- private void SaveEpgDataForChannel(string channelId, List<ProgramInfo> epgData)
- {
- var path = GetChannelEpgCachePath(channelId);
- _fileSystem.CreateDirectory(_fileSystem.GetDirectoryName(path));
- lock (_epgLock)
- {
- _jsonSerializer.SerializeToFile(epgData, path);
- }
- }
- private List<ProgramInfo> GetEpgDataForChannel(string channelId)
- {
- try
- {
- lock (_epgLock)
- {
- return _jsonSerializer.DeserializeFromFile<List<ProgramInfo>>(GetChannelEpgCachePath(channelId));
- }
- }
- catch
- {
- return new List<ProgramInfo>();
- }
- }
- private List<ProgramInfo> GetEpgDataForChannels(List<string> channelIds)
- {
- return channelIds.SelectMany(GetEpgDataForChannel).ToList();
- }
-
private bool _disposed;
public void Dispose()
{
@@ -2631,6 +2694,7 @@ namespace Emby.Server.Implementations.LiveTv.EmbyTV
{
pair.Value.CancellationTokenSource.Cancel();
}
+ GC.SuppressFinalize(this);
}
public List<VirtualFolderInfo> GetRecordingFolders()
diff --git a/Emby.Server.Implementations/LiveTv/EmbyTV/EncodedRecorder.cs b/Emby.Server.Implementations/LiveTv/EmbyTV/EncodedRecorder.cs
index 48eba4117..149f69e5b 100644
--- a/Emby.Server.Implementations/LiveTv/EmbyTV/EncodedRecorder.cs
+++ b/Emby.Server.Implementations/LiveTv/EmbyTV/EncodedRecorder.cs
@@ -284,8 +284,15 @@ namespace Emby.Server.Implementations.LiveTv.EmbyTV
protected string GetOutputSizeParam()
{
var filters = new List<string>();
-
- filters.Add("yadif=0:-1:0");
+
+ if (string.Equals(GetEncodingOptions().DeinterlaceMethod, "bobandweave", StringComparison.OrdinalIgnoreCase))
+ {
+ filters.Add("yadif=1:-1:0");
+ }
+ else
+ {
+ filters.Add("yadif=0:-1:0");
+ }
var output = string.Empty;
diff --git a/Emby.Server.Implementations/LiveTv/EmbyTV/EntryPoint.cs b/Emby.Server.Implementations/LiveTv/EmbyTV/EntryPoint.cs
index 139cf570e..7c5f630a7 100644
--- a/Emby.Server.Implementations/LiveTv/EmbyTV/EntryPoint.cs
+++ b/Emby.Server.Implementations/LiveTv/EmbyTV/EntryPoint.cs
@@ -1,4 +1,5 @@
-using MediaBrowser.Controller.Plugins;
+using System;
+using MediaBrowser.Controller.Plugins;
namespace Emby.Server.Implementations.LiveTv.EmbyTV
{
@@ -11,6 +12,7 @@ namespace Emby.Server.Implementations.LiveTv.EmbyTV
public void Dispose()
{
+ GC.SuppressFinalize(this);
}
}
}
diff --git a/Emby.Server.Implementations/LiveTv/EmbyTV/RecordingHelper.cs b/Emby.Server.Implementations/LiveTv/EmbyTV/RecordingHelper.cs
index b5de6ef01..a5712b480 100644
--- a/Emby.Server.Implementations/LiveTv/EmbyTV/RecordingHelper.cs
+++ b/Emby.Server.Implementations/LiveTv/EmbyTV/RecordingHelper.cs
@@ -1,8 +1,6 @@
-using MediaBrowser.Common.Extensions;
-using MediaBrowser.Controller.LiveTv;
+using MediaBrowser.Controller.LiveTv;
using System;
using System.Globalization;
-using MediaBrowser.Model.LiveTv;
namespace Emby.Server.Implementations.LiveTv.EmbyTV
{
@@ -13,63 +11,6 @@ namespace Emby.Server.Implementations.LiveTv.EmbyTV
return timer.StartDate.AddSeconds(-timer.PrePaddingSeconds);
}
- public static TimerInfo CreateTimer(ProgramInfo parent, SeriesTimerInfo seriesTimer)
- {
- var timer = new TimerInfo
- {
- ChannelId = parent.ChannelId,
- Id = (seriesTimer.Id + parent.Id).GetMD5().ToString("N"),
- StartDate = parent.StartDate,
- EndDate = parent.EndDate,
- ProgramId = parent.Id,
- PrePaddingSeconds = seriesTimer.PrePaddingSeconds,
- PostPaddingSeconds = seriesTimer.PostPaddingSeconds,
- IsPostPaddingRequired = seriesTimer.IsPostPaddingRequired,
- IsPrePaddingRequired = seriesTimer.IsPrePaddingRequired,
- KeepUntil = seriesTimer.KeepUntil,
- Priority = seriesTimer.Priority,
- Name = parent.Name,
- Overview = parent.Overview,
- SeriesId = parent.SeriesId,
- SeriesTimerId = seriesTimer.Id,
- ShowId = parent.ShowId
- };
-
- CopyProgramInfoToTimerInfo(parent, timer);
-
- return timer;
- }
-
- public static void CopyProgramInfoToTimerInfo(ProgramInfo programInfo, TimerInfo timerInfo)
- {
- timerInfo.Name = programInfo.Name;
- timerInfo.StartDate = programInfo.StartDate;
- timerInfo.EndDate = programInfo.EndDate;
- timerInfo.ChannelId = programInfo.ChannelId;
-
- timerInfo.SeasonNumber = programInfo.SeasonNumber;
- 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;
- timerInfo.OriginalAirDate = programInfo.OriginalAirDate;
- timerInfo.IsProgramSeries = programInfo.IsSeries;
-
- timerInfo.IsSeries = programInfo.IsSeries;
- timerInfo.IsLive = programInfo.IsLive;
- timerInfo.IsPremiere = programInfo.IsPremiere;
-
- timerInfo.HomePageUrl = programInfo.HomePageUrl;
- timerInfo.CommunityRating = programInfo.CommunityRating;
- timerInfo.Overview = programInfo.Overview;
- timerInfo.OfficialRating = programInfo.OfficialRating;
- timerInfo.IsRepeat = programInfo.IsRepeat;
- timerInfo.SeriesId = programInfo.SeriesId;
- }
-
public static string GetRecordingName(TimerInfo info)
{
var name = info.Name;
diff --git a/Emby.Server.Implementations/LiveTv/LiveTvDtoService.cs b/Emby.Server.Implementations/LiveTv/LiveTvDtoService.cs
index eff2909fd..e6479feaa 100644
--- a/Emby.Server.Implementations/LiveTv/LiveTvDtoService.cs
+++ b/Emby.Server.Implementations/LiveTv/LiveTvDtoService.cs
@@ -9,14 +9,12 @@ using MediaBrowser.Model.Entities;
using MediaBrowser.Model.LiveTv;
using MediaBrowser.Model.Logging;
using System;
-using System.Collections.Generic;
using System.Linq;
using System.Threading;
using System.Threading.Tasks;
using MediaBrowser.Controller.Entities.TV;
using MediaBrowser.Model.Dto;
using MediaBrowser.Model.Extensions;
-using MediaBrowser.Model.Querying;
namespace Emby.Server.Implementations.LiveTv
{
@@ -25,15 +23,13 @@ namespace Emby.Server.Implementations.LiveTv
private readonly ILogger _logger;
private readonly IImageProcessor _imageProcessor;
- private readonly IUserDataManager _userDataManager;
private readonly IDtoService _dtoService;
private readonly IApplicationHost _appHost;
private readonly ILibraryManager _libraryManager;
- public LiveTvDtoService(IDtoService dtoService, IUserDataManager userDataManager, IImageProcessor imageProcessor, ILogger logger, IApplicationHost appHost, ILibraryManager libraryManager)
+ public LiveTvDtoService(IDtoService dtoService, IImageProcessor imageProcessor, ILogger logger, IApplicationHost appHost, ILibraryManager libraryManager)
{
_dtoService = dtoService;
- _userDataManager = userDataManager;
_imageProcessor = imageProcessor;
_logger = logger;
_appHost = appHost;
diff --git a/Emby.Server.Implementations/LiveTv/LiveTvManager.cs b/Emby.Server.Implementations/LiveTv/LiveTvManager.cs
index ac98d1043..38d2fd3c6 100644
--- a/Emby.Server.Implementations/LiveTv/LiveTvManager.cs
+++ b/Emby.Server.Implementations/LiveTv/LiveTvManager.cs
@@ -99,7 +99,7 @@ namespace Emby.Server.Implementations.LiveTv
_dtoService = dtoService;
_userDataManager = userDataManager;
- _tvDtoService = new LiveTvDtoService(dtoService, userDataManager, imageProcessor, logger, appHost, _libraryManager);
+ _tvDtoService = new LiveTvDtoService(dtoService, imageProcessor, logger, appHost, _libraryManager);
}
/// <summary>
@@ -187,7 +187,6 @@ namespace Emby.Server.Implementations.LiveTv
IsSports = query.IsSports,
IsSeries = query.IsSeries,
IncludeItemTypes = new[] { typeof(LiveTvChannel).Name },
- SortOrder = query.SortOrder ?? SortOrder.Ascending,
TopParentIds = new[] { topFolder.Id.ToString("N") },
IsFavorite = query.IsFavorite,
IsLiked = query.IsLiked,
@@ -196,18 +195,22 @@ namespace Emby.Server.Implementations.LiveTv
DtoOptions = dtoOptions
};
- internalQuery.OrderBy.AddRange(query.SortBy.Select(i => new Tuple<string, SortOrder>(i, query.SortOrder ?? SortOrder.Ascending)));
+ var orderBy = internalQuery.OrderBy.ToList();
+
+ orderBy.AddRange(query.SortBy.Select(i => new Tuple<string, SortOrder>(i, query.SortOrder ?? SortOrder.Ascending)));
if (query.EnableFavoriteSorting)
{
- internalQuery.OrderBy.Insert(0, new Tuple<string, SortOrder>(ItemSortBy.IsFavoriteOrLiked, SortOrder.Descending));
+ orderBy.Insert(0, new Tuple<string, SortOrder>(ItemSortBy.IsFavoriteOrLiked, SortOrder.Descending));
}
if (!internalQuery.OrderBy.Any(i => string.Equals(i.Item1, ItemSortBy.SortName, StringComparison.OrdinalIgnoreCase)))
{
- internalQuery.OrderBy.Add(new Tuple<string, SortOrder>(ItemSortBy.SortName, SortOrder.Ascending));
+ orderBy.Add(new Tuple<string, SortOrder>(ItemSortBy.SortName, SortOrder.Ascending));
}
+ internalQuery.OrderBy = orderBy.ToArray();
+
return _libraryManager.GetItemsResult(internalQuery);
}
@@ -597,6 +600,12 @@ namespace Emby.Server.Implementations.LiveTv
};
}
+ if (!string.Equals(info.ShowId, item.ShowId, StringComparison.OrdinalIgnoreCase))
+ {
+ item.ShowId = info.ShowId;
+ forceUpdate = true;
+ }
+
var seriesId = info.SeriesId;
if (!item.ParentId.Equals(channel.Id))
@@ -743,6 +752,11 @@ namespace Emby.Server.Implementations.LiveTv
}
}
+ if (isNew || isUpdated)
+ {
+ item.OnMetadataChanged();
+ }
+
return new Tuple<LiveTvProgram, bool, bool>(item, isNew, isUpdated);
}
@@ -829,8 +843,7 @@ namespace Emby.Server.Implementations.LiveTv
item.SetImage(new ItemImageInfo
{
Path = info.ImagePath,
- Type = ImageType.Primary,
- IsPlaceholder = true
+ Type = ImageType.Primary
}, 0);
}
else if (!string.IsNullOrWhiteSpace(info.ImageUrl))
@@ -838,8 +851,7 @@ namespace Emby.Server.Implementations.LiveTv
item.SetImage(new ItemImageInfo
{
Path = info.ImageUrl,
- Type = ImageType.Primary,
- IsPlaceholder = true
+ Type = ImageType.Primary
}, 0);
}
}
@@ -918,10 +930,10 @@ namespace Emby.Server.Implementations.LiveTv
var topFolder = await GetInternalLiveTvFolder(cancellationToken).ConfigureAwait(false);
- if (query.SortBy.Length == 0)
+ if (query.OrderBy.Length == 0)
{
// Unless something else was specified, order by start date to take advantage of a specialized index
- query.SortBy = new[] { ItemSortBy.StartDate };
+ query.OrderBy = new Tuple<string, SortOrder>[] { new Tuple<string, SortOrder>(ItemSortBy.StartDate, SortOrder.Ascending) };
}
RemoveFields(options);
@@ -942,8 +954,7 @@ namespace Emby.Server.Implementations.LiveTv
Genres = query.Genres,
StartIndex = query.StartIndex,
Limit = query.Limit,
- SortBy = query.SortBy,
- SortOrder = query.SortOrder ?? SortOrder.Ascending,
+ OrderBy = query.OrderBy,
EnableTotalRecordCount = query.EnableTotalRecordCount,
TopParentIds = new[] { topFolder.Id.ToString("N") },
Name = query.Name,
@@ -985,8 +996,7 @@ namespace Emby.Server.Implementations.LiveTv
var queryResult = _libraryManager.QueryItems(internalQuery);
- var returnArray = (await _dtoService.GetBaseItemDtos(queryResult.Items, options, user)
- .ConfigureAwait(false));
+ var returnArray = _dtoService.GetBaseItemDtos(queryResult.Items, options, user);
var result = new QueryResult<BaseItemDto>
{
@@ -1013,7 +1023,7 @@ namespace Emby.Server.Implementations.LiveTv
IsSports = query.IsSports,
IsKids = query.IsKids,
EnableTotalRecordCount = query.EnableTotalRecordCount,
- SortBy = new[] { ItemSortBy.StartDate },
+ OrderBy = new[] { new Tuple<string, SortOrder>(ItemSortBy.StartDate, SortOrder.Ascending) },
TopParentIds = new[] { topFolder.Id.ToString("N") },
DtoOptions = options
};
@@ -1070,8 +1080,7 @@ namespace Emby.Server.Implementations.LiveTv
var user = _userManager.GetUserById(query.UserId);
- var returnArray = (await _dtoService.GetBaseItemDtos(internalResult.Items, options, user)
- .ConfigureAwait(false));
+ var returnArray = _dtoService.GetBaseItemDtos(internalResult.Items, options, user);
var result = new QueryResult<BaseItemDto>
{
@@ -1646,8 +1655,7 @@ namespace Emby.Server.Implementations.LiveTv
IsVirtualItem = false,
Limit = query.Limit,
StartIndex = query.StartIndex,
- SortBy = new[] { ItemSortBy.DateCreated },
- SortOrder = SortOrder.Descending,
+ OrderBy = new[] { new Tuple<string, SortOrder>(ItemSortBy.DateCreated, SortOrder.Descending) },
EnableTotalRecordCount = query.EnableTotalRecordCount,
IncludeItemTypes = includeItemTypes.ToArray(includeItemTypes.Count),
ExcludeItemTypes = excludeItemTypes.ToArray(excludeItemTypes.Count),
@@ -1656,7 +1664,7 @@ namespace Emby.Server.Implementations.LiveTv
});
}
- public async Task<QueryResult<BaseItemDto>> GetRecordingSeries(RecordingQuery query, DtoOptions options, CancellationToken cancellationToken)
+ public QueryResult<BaseItemDto> GetRecordingSeries(RecordingQuery query, DtoOptions options, CancellationToken cancellationToken)
{
var user = string.IsNullOrEmpty(query.UserId) ? null : _userManager.GetUserById(query.UserId);
if (user != null && !IsLiveTvEnabled(user))
@@ -1694,16 +1702,14 @@ namespace Emby.Server.Implementations.LiveTv
Recursive = true,
AncestorIds = folders.Select(i => i.Id.ToString("N")).ToArray(folders.Count),
Limit = query.Limit,
- SortBy = new[] { ItemSortBy.DateCreated },
- SortOrder = SortOrder.Descending,
+ OrderBy = new[] { new Tuple<string, SortOrder>(ItemSortBy.DateCreated, SortOrder.Descending) },
EnableTotalRecordCount = query.EnableTotalRecordCount,
IncludeItemTypes = includeItemTypes.ToArray(includeItemTypes.Count),
ExcludeItemTypes = excludeItemTypes.ToArray(excludeItemTypes.Count),
DtoOptions = options
});
- var returnArray = (await _dtoService.GetBaseItemDtos(internalResult.Items, options, user)
- .ConfigureAwait(false));
+ var returnArray = _dtoService.GetBaseItemDtos(internalResult.Items, options, user);
return new QueryResult<BaseItemDto>
{
@@ -1930,11 +1936,11 @@ namespace Emby.Server.Implementations.LiveTv
var info = recording;
- dto.SeriesTimerId = string.IsNullOrEmpty(info.SeriesTimerId)
+ dto.SeriesTimerId = string.IsNullOrEmpty(info.SeriesTimerId) || service == null
? null
: _tvDtoService.GetInternalSeriesTimerId(service.Name, info.SeriesTimerId).ToString("N");
- dto.TimerId = string.IsNullOrEmpty(info.TimerId)
+ dto.TimerId = string.IsNullOrEmpty(info.TimerId) || service == null
? null
: _tvDtoService.GetInternalTimerId(service.Name, info.TimerId).ToString("N");
@@ -2040,8 +2046,7 @@ namespace Emby.Server.Implementations.LiveTv
var internalResult = await GetInternalRecordings(query, options, cancellationToken).ConfigureAwait(false);
- var returnArray = (await _dtoService.GetBaseItemDtos(internalResult.Items, options, user)
- .ConfigureAwait(false));
+ var returnArray = _dtoService.GetBaseItemDtos(internalResult.Items, options, user);
return new QueryResult<BaseItemDto>
{
@@ -2368,7 +2373,7 @@ namespace Emby.Server.Implementations.LiveTv
};
}
- public async Task AddChannelInfo(List<Tuple<BaseItemDto, LiveTvChannel>> tuples, DtoOptions options, User user)
+ public void AddChannelInfo(List<Tuple<BaseItemDto, LiveTvChannel>> tuples, DtoOptions options, User user)
{
var now = DateTime.UtcNow;
@@ -2381,7 +2386,7 @@ namespace Emby.Server.Implementations.LiveTv
MaxStartDate = now,
MinEndDate = now,
Limit = channelIds.Length,
- SortBy = new[] { "StartDate" },
+ OrderBy = new[] { new Tuple<string, SortOrder>(ItemSortBy.StartDate, SortOrder.Ascending) },
TopParentIds = new[] { GetInternalLiveTvFolder(CancellationToken.None).Result.Id.ToString("N") },
DtoOptions = options
@@ -2425,7 +2430,7 @@ namespace Emby.Server.Implementations.LiveTv
if (addCurrentProgram)
{
- var currentProgramDtos = await _dtoService.GetBaseItemDtos(currentProgramsList, options, user).ConfigureAwait(false);
+ var currentProgramDtos = _dtoService.GetBaseItemDtos(currentProgramsList, options, user);
foreach (var programDto in currentProgramDtos)
{
@@ -2783,6 +2788,7 @@ namespace Emby.Server.Implementations.LiveTv
public void Dispose()
{
Dispose(true);
+ GC.SuppressFinalize(this);
}
private bool _isDisposed = false;
@@ -3146,5 +3152,15 @@ namespace Emby.Server.Implementations.LiveTv
var provider = _listingProviders.First(i => string.Equals(i.Type, info.Type, StringComparison.OrdinalIgnoreCase));
return provider.GetChannels(info, cancellationToken);
}
+
+ public Guid GetInternalChannelId(string serviceName, string externalId)
+ {
+ return _tvDtoService.GetInternalChannelId(serviceName, externalId);
+ }
+
+ public Guid GetInternalProgramId(string serviceName, string externalId)
+ {
+ return _tvDtoService.GetInternalProgramId(serviceName, externalId);
+ }
}
} \ No newline at end of file
diff --git a/Emby.Server.Implementations/LiveTv/LiveTvMediaSourceProvider.cs b/Emby.Server.Implementations/LiveTv/LiveTvMediaSourceProvider.cs
index 0e52f874d..ed8b3074b 100644
--- a/Emby.Server.Implementations/LiveTv/LiveTvMediaSourceProvider.cs
+++ b/Emby.Server.Implementations/LiveTv/LiveTvMediaSourceProvider.cs
@@ -142,6 +142,8 @@ namespace Emby.Server.Implementations.LiveTv
var info = await _liveTvManager.GetChannelStream(keys[1], mediaSourceId, cancellationToken).ConfigureAwait(false);
stream = info.Item1;
directStreamProvider = info.Item2;
+
+ //allowLiveStreamProbe = false;
}
else
{
diff --git a/Emby.Server.Implementations/LiveTv/RefreshChannelsScheduledTask.cs b/Emby.Server.Implementations/LiveTv/RefreshChannelsScheduledTask.cs
index cad28c809..225360159 100644
--- a/Emby.Server.Implementations/LiveTv/RefreshChannelsScheduledTask.cs
+++ b/Emby.Server.Implementations/LiveTv/RefreshChannelsScheduledTask.cs
@@ -51,7 +51,7 @@ namespace Emby.Server.Implementations.LiveTv
return new[] {
// Every so often
- new TaskTriggerInfo { Type = TaskTriggerInfo.TriggerInterval, IntervalTicks = TimeSpan.FromHours(12).Ticks}
+ new TaskTriggerInfo { Type = TaskTriggerInfo.TriggerInterval, IntervalTicks = TimeSpan.FromHours(24).Ticks}
};
}
diff --git a/Emby.Server.Implementations/LiveTv/TunerHosts/HdHomerun/HdHomerunHost.cs b/Emby.Server.Implementations/LiveTv/TunerHosts/HdHomerun/HdHomerunHost.cs
index eae29bee7..f974b5c2c 100644
--- a/Emby.Server.Implementations/LiveTv/TunerHosts/HdHomerun/HdHomerunHost.cs
+++ b/Emby.Server.Implementations/LiveTv/TunerHosts/HdHomerun/HdHomerunHost.cs
@@ -422,7 +422,7 @@ namespace Emby.Server.Implementations.LiveTv.TunerHosts.HdHomerun
SupportsTranscoding = true,
IsInfiniteStream = true,
IgnoreDts = true,
- //SupportsProbing = false,
+ SupportsProbing = false,
//AnalyzeDurationMs = 2000000
//IgnoreIndex = true,
//ReadAtNativeFramerate = true
diff --git a/Emby.Server.Implementations/LiveTv/TunerHosts/HdHomerun/HdHomerunHttpStream.cs b/Emby.Server.Implementations/LiveTv/TunerHosts/HdHomerun/HdHomerunHttpStream.cs
index d2e9c8bf0..af064755d 100644
--- a/Emby.Server.Implementations/LiveTv/TunerHosts/HdHomerun/HdHomerunHttpStream.cs
+++ b/Emby.Server.Implementations/LiveTv/TunerHosts/HdHomerun/HdHomerunHttpStream.cs
@@ -26,10 +26,7 @@ namespace Emby.Server.Implementations.LiveTv.TunerHosts.HdHomerun
private readonly CancellationTokenSource _liveStreamCancellationTokenSource = new CancellationTokenSource();
private readonly TaskCompletionSource<bool> _liveStreamTaskCompletionSource = new TaskCompletionSource<bool>();
- private readonly MulticastStream _multicastStream;
-
private readonly string _tempFilePath;
- private bool _enableFileBuffer = false;
public HdHomerunHttpStream(MediaSourceInfo mediaSource, string originalStreamId, IFileSystem fileSystem, IHttpClient httpClient, ILogger logger, IServerApplicationPaths appPaths, IServerApplicationHost appHost, IEnvironmentInfo environment)
: base(mediaSource, environment, fileSystem)
@@ -39,7 +36,6 @@ namespace Emby.Server.Implementations.LiveTv.TunerHosts.HdHomerun
_appHost = appHost;
OriginalStreamId = originalStreamId;
- _multicastStream = new MulticastStream(_logger);
_tempFilePath = Path.Combine(appPaths.TranscodingTempPath, UniqueId + ".ts");
}
@@ -63,6 +59,9 @@ namespace Emby.Server.Implementations.LiveTv.TunerHosts.HdHomerun
OpenedMediaSource.Path = _appHost.GetLocalApiUrl("127.0.0.1") + "/LiveTv/LiveStreamFiles/" + UniqueId + "/stream.ts";
OpenedMediaSource.Protocol = MediaProtocol.Http;
+
+ //OpenedMediaSource.Path = _tempFilePath;
+ //OpenedMediaSource.Protocol = MediaProtocol.File;
//OpenedMediaSource.SupportsDirectPlay = false;
//OpenedMediaSource.SupportsDirectStream = true;
//OpenedMediaSource.SupportsTranscoding = true;
@@ -107,19 +106,10 @@ namespace Emby.Server.Implementations.LiveTv.TunerHosts.HdHomerun
{
_logger.Info("Beginning multicastStream.CopyUntilCancelled");
- if (_enableFileBuffer)
+ FileSystem.CreateDirectory(FileSystem.GetDirectoryName(_tempFilePath));
+ using (var fileStream = FileSystem.GetFileStream(_tempFilePath, FileOpenMode.Create, FileAccessMode.Write, FileShareMode.Read, FileOpenOptions.None))
{
- FileSystem.CreateDirectory(FileSystem.GetDirectoryName(_tempFilePath));
- using (var fileStream = FileSystem.GetFileStream(_tempFilePath, FileOpenMode.Create, FileAccessMode.Write, FileShareMode.Read, FileOpenOptions.None))
- {
- StreamHelper.CopyTo(response.Content, fileStream, 81920, () => Resolve(openTaskCompletionSource), cancellationToken);
- }
- }
- else
- {
- Resolve(openTaskCompletionSource);
-
- await _multicastStream.CopyUntilCancelled(response.Content, null, cancellationToken).ConfigureAwait(false);
+ StreamHelper.CopyTo(response.Content, fileStream, 81920, () => Resolve(openTaskCompletionSource), cancellationToken);
}
}
}
@@ -144,7 +134,7 @@ namespace Emby.Server.Implementations.LiveTv.TunerHosts.HdHomerun
}
_liveStreamTaskCompletionSource.TrySetResult(true);
- //await DeleteTempFile(_tempFilePath).ConfigureAwait(false);
+ await DeleteTempFile(_tempFilePath).ConfigureAwait(false);
});
}
@@ -158,56 +148,31 @@ namespace Emby.Server.Implementations.LiveTv.TunerHosts.HdHomerun
public Task CopyToAsync(Stream stream, CancellationToken cancellationToken)
{
- if (_enableFileBuffer)
- {
- return CopyFileTo(_tempFilePath, stream, cancellationToken);
- }
- return _multicastStream.CopyToAsync(stream, cancellationToken);
- //return CopyFileTo(_tempFilePath, stream, cancellationToken);
+ return CopyFileTo(_tempFilePath, stream, cancellationToken);
}
protected async Task CopyFileTo(string path, Stream outputStream, CancellationToken cancellationToken)
{
long startPosition = -20000;
- if (startPosition < 0)
- {
- var length = FileSystem.GetFileInfo(path).Length;
- startPosition = Math.Max(length - startPosition, 0);
- }
_logger.Info("Live stream starting position is {0} bytes", startPosition.ToString(CultureInfo.InvariantCulture));
- var allowAsync = Environment.OperatingSystem != MediaBrowser.Model.System.OperatingSystem.Windows;
+ var allowAsync = false;//Environment.OperatingSystem != MediaBrowser.Model.System.OperatingSystem.Windows;
// use non-async filestream along with read due to https://github.com/dotnet/corefx/issues/6039
- using (var inputStream = GetInputStream(path, startPosition, allowAsync))
+ using (var inputStream = (FileStream)GetInputStream(path, allowAsync))
{
if (startPosition > 0)
{
- inputStream.Position = startPosition;
+ inputStream.Seek(-20000, SeekOrigin.End);
}
while (!cancellationToken.IsCancellationRequested)
{
- long bytesRead;
-
- if (allowAsync)
- {
- bytesRead = await AsyncStreamCopier.CopyStream(inputStream, outputStream, 81920, 2, cancellationToken).ConfigureAwait(false);
- }
- else
- {
- StreamHelper.CopyTo(inputStream, outputStream, 81920, cancellationToken);
- bytesRead = 1;
- }
+ StreamHelper.CopyTo(inputStream, outputStream, 81920, cancellationToken);
//var position = fs.Position;
//_logger.Debug("Streamed {0} bytes to position {1} from file {2}", bytesRead, position, path);
-
- if (bytesRead == 0)
- {
- await Task.Delay(100, cancellationToken).ConfigureAwait(false);
- }
}
}
}
diff --git a/Emby.Server.Implementations/LiveTv/TunerHosts/HdHomerun/HdHomerunManager.cs b/Emby.Server.Implementations/LiveTv/TunerHosts/HdHomerun/HdHomerunManager.cs
index 41b058baf..c737c4cba 100644
--- a/Emby.Server.Implementations/LiveTv/TunerHosts/HdHomerun/HdHomerunManager.cs
+++ b/Emby.Server.Implementations/LiveTv/TunerHosts/HdHomerun/HdHomerunManager.cs
@@ -99,6 +99,7 @@ namespace Emby.Server.Implementations.LiveTv.TunerHosts.HdHomerun
var task = StopStreaming();
Task.WaitAll(task);
+ GC.SuppressFinalize(this);
}
public async Task<bool> CheckTunerAvailability(IpAddressInfo remoteIp, int tuner, CancellationToken cancellationToken)
diff --git a/Emby.Server.Implementations/LiveTv/TunerHosts/HdHomerun/HdHomerunUdpStream.cs b/Emby.Server.Implementations/LiveTv/TunerHosts/HdHomerun/HdHomerunUdpStream.cs
index 5ad6e2e16..6c21066fb 100644
--- a/Emby.Server.Implementations/LiveTv/TunerHosts/HdHomerun/HdHomerunUdpStream.cs
+++ b/Emby.Server.Implementations/LiveTv/TunerHosts/HdHomerun/HdHomerunUdpStream.cs
@@ -34,8 +34,6 @@ namespace Emby.Server.Implementations.LiveTv.TunerHosts.HdHomerun
private readonly INetworkManager _networkManager;
private readonly string _tempFilePath;
- private bool _enableFileBuffer = false;
- private readonly MulticastStream _multicastStream;
public HdHomerunUdpStream(MediaSourceInfo mediaSource, string originalStreamId, IHdHomerunChannelCommands channelCommands, int numTuners, IFileSystem fileSystem, IHttpClient httpClient, ILogger logger, IServerApplicationPaths appPaths, IServerApplicationHost appHost, ISocketFactory socketFactory, INetworkManager networkManager, IEnvironmentInfo environment)
: base(mediaSource, environment, fileSystem)
@@ -48,7 +46,6 @@ namespace Emby.Server.Implementations.LiveTv.TunerHosts.HdHomerun
_channelCommands = channelCommands;
_numTuners = numTuners;
_tempFilePath = Path.Combine(appPaths.TranscodingTempPath, UniqueId + ".ts");
- _multicastStream = new MulticastStream(_logger);
}
protected override async Task OpenInternal(CancellationToken openCancellationToken)
@@ -126,17 +123,10 @@ namespace Emby.Server.Implementations.LiveTv.TunerHosts.HdHomerun
if (!cancellationToken.IsCancellationRequested)
{
- if (_enableFileBuffer)
+ FileSystem.CreateDirectory(FileSystem.GetDirectoryName(_tempFilePath));
+ using (var fileStream = FileSystem.GetFileStream(_tempFilePath, FileOpenMode.Create, FileAccessMode.Write, FileShareMode.Read, FileOpenOptions.None))
{
- FileSystem.CreateDirectory(FileSystem.GetDirectoryName(_tempFilePath));
- using (var fileStream = FileSystem.GetFileStream(_tempFilePath, FileOpenMode.Create, FileAccessMode.Write, FileShareMode.Read, FileOpenOptions.None))
- {
- CopyTo(udpClient, fileStream, openTaskCompletionSource, cancellationToken);
- }
- }
- else
- {
- await _multicastStream.CopyUntilCancelled(new UdpClientStream(udpClient), () => Resolve(openTaskCompletionSource), cancellationToken).ConfigureAwait(false);
+ CopyTo(udpClient, fileStream, openTaskCompletionSource, cancellationToken);
}
}
}
@@ -178,56 +168,33 @@ namespace Emby.Server.Implementations.LiveTv.TunerHosts.HdHomerun
});
}
- public async Task CopyToAsync(Stream outputStream, CancellationToken cancellationToken)
+ public Task CopyToAsync(Stream stream, CancellationToken cancellationToken)
{
- if (!_enableFileBuffer)
- {
- await _multicastStream.CopyToAsync(outputStream, cancellationToken).ConfigureAwait(false);
- return;
- }
-
- var path = _tempFilePath;
+ return CopyFileTo(_tempFilePath, stream, cancellationToken);
+ }
+ protected async Task CopyFileTo(string path, Stream outputStream, CancellationToken cancellationToken)
+ {
long startPosition = -20000;
- if (startPosition < 0)
- {
- var length = FileSystem.GetFileInfo(path).Length;
- startPosition = Math.Max(length - startPosition, 0);
- }
_logger.Info("Live stream starting position is {0} bytes", startPosition.ToString(CultureInfo.InvariantCulture));
- var allowAsync = Environment.OperatingSystem != MediaBrowser.Model.System.OperatingSystem.Windows;
+ var allowAsync = false;//Environment.OperatingSystem != MediaBrowser.Model.System.OperatingSystem.Windows;
// use non-async filestream along with read due to https://github.com/dotnet/corefx/issues/6039
- using (var inputStream = GetInputStream(path, startPosition, allowAsync))
+ using (var inputStream = (FileStream)GetInputStream(path, allowAsync))
{
if (startPosition > 0)
{
- inputStream.Position = startPosition;
+ inputStream.Seek(-20000, SeekOrigin.End);
}
while (!cancellationToken.IsCancellationRequested)
{
- long bytesRead;
-
- if (allowAsync)
- {
- bytesRead = await AsyncStreamCopier.CopyStream(inputStream, outputStream, 81920, 2, cancellationToken).ConfigureAwait(false);
- }
- else
- {
- StreamHelper.CopyTo(inputStream, outputStream, 81920, cancellationToken);
- bytesRead = 1;
- }
+ StreamHelper.CopyTo(inputStream, outputStream, 81920, cancellationToken);
//var position = fs.Position;
//_logger.Debug("Streamed {0} bytes to position {1} from file {2}", bytesRead, position, path);
-
- if (bytesRead == 0)
- {
- await Task.Delay(100, cancellationToken).ConfigureAwait(false);
- }
}
}
}
@@ -285,22 +252,6 @@ namespace Emby.Server.Implementations.LiveTv.TunerHosts.HdHomerun
//return taskCompletion.Task;
}
- private void StreamCopyCallback(IAsyncResult result)
- {
- var copier = (AsyncStreamCopier)result.AsyncState;
- var taskCompletion = copier.TaskCompletionSource;
-
- try
- {
- copier.EndCopy(result);
- taskCompletion.TrySetResult(0);
- }
- catch (Exception ex)
- {
- taskCompletion.TrySetException(ex);
- }
- }
-
public class UdpClientStream : Stream
{
private static int RtpHeaderBytes = 12;