aboutsummaryrefslogtreecommitdiff
path: root/Emby.Server.Implementations/LiveTv
diff options
context:
space:
mode:
Diffstat (limited to 'Emby.Server.Implementations/LiveTv')
-rw-r--r--Emby.Server.Implementations/LiveTv/EmbyTV/DirectRecorder.cs6
-rw-r--r--Emby.Server.Implementations/LiveTv/EmbyTV/EmbyTV.cs84
-rw-r--r--Emby.Server.Implementations/LiveTv/EmbyTV/EncodedRecorder.cs35
-rw-r--r--Emby.Server.Implementations/LiveTv/EmbyTV/IRecorder.cs7
-rw-r--r--Emby.Server.Implementations/LiveTv/EmbyTV/ItemDataProvider.cs14
-rw-r--r--Emby.Server.Implementations/LiveTv/Listings/SchedulesDirect.cs143
-rw-r--r--Emby.Server.Implementations/LiveTv/Listings/SchedulesDirectDtos/BroadcasterDto.cs10
-rw-r--r--Emby.Server.Implementations/LiveTv/Listings/SchedulesDirectDtos/CaptionDto.cs6
-rw-r--r--Emby.Server.Implementations/LiveTv/Listings/SchedulesDirectDtos/CastDto.cs14
-rw-r--r--Emby.Server.Implementations/LiveTv/Listings/SchedulesDirectDtos/ChannelDto.cs9
-rw-r--r--Emby.Server.Implementations/LiveTv/Listings/SchedulesDirectDtos/ContentRatingDto.cs6
-rw-r--r--Emby.Server.Implementations/LiveTv/Listings/SchedulesDirectDtos/CrewDto.cs12
-rw-r--r--Emby.Server.Implementations/LiveTv/Listings/SchedulesDirectDtos/DayDto.cs17
-rw-r--r--Emby.Server.Implementations/LiveTv/Listings/SchedulesDirectDtos/Description1000Dto.cs6
-rw-r--r--Emby.Server.Implementations/LiveTv/Listings/SchedulesDirectDtos/Description100Dto.cs6
-rw-r--r--Emby.Server.Implementations/LiveTv/Listings/SchedulesDirectDtos/DescriptionsProgramDto.cs7
-rw-r--r--Emby.Server.Implementations/LiveTv/Listings/SchedulesDirectDtos/EventDetailsDto.cs4
-rw-r--r--Emby.Server.Implementations/LiveTv/Listings/SchedulesDirectDtos/GracenoteDto.cs2
-rw-r--r--Emby.Server.Implementations/LiveTv/Listings/SchedulesDirectDtos/HeadendsDto.cs11
-rw-r--r--Emby.Server.Implementations/LiveTv/Listings/SchedulesDirectDtos/ImageDataDto.cs22
-rw-r--r--Emby.Server.Implementations/LiveTv/Listings/SchedulesDirectDtos/LineupDto.cs18
-rw-r--r--Emby.Server.Implementations/LiveTv/Listings/SchedulesDirectDtos/LineupsDto.cs9
-rw-r--r--Emby.Server.Implementations/LiveTv/Listings/SchedulesDirectDtos/LogoDto.cs6
-rw-r--r--Emby.Server.Implementations/LiveTv/Listings/SchedulesDirectDtos/MapDto.cs20
-rw-r--r--Emby.Server.Implementations/LiveTv/Listings/SchedulesDirectDtos/MetadataDto.cs8
-rw-r--r--Emby.Server.Implementations/LiveTv/Listings/SchedulesDirectDtos/MetadataProgramsDto.cs6
-rw-r--r--Emby.Server.Implementations/LiveTv/Listings/SchedulesDirectDtos/MetadataScheduleDto.cs11
-rw-r--r--Emby.Server.Implementations/LiveTv/Listings/SchedulesDirectDtos/MovieDto.cs7
-rw-r--r--Emby.Server.Implementations/LiveTv/Listings/SchedulesDirectDtos/MultipartDto.cs2
-rw-r--r--Emby.Server.Implementations/LiveTv/Listings/SchedulesDirectDtos/ProgramDetailsDto.cs49
-rw-r--r--Emby.Server.Implementations/LiveTv/Listings/SchedulesDirectDtos/ProgramDto.cs21
-rw-r--r--Emby.Server.Implementations/LiveTv/Listings/SchedulesDirectDtos/QualityRatingDto.cs12
-rw-r--r--Emby.Server.Implementations/LiveTv/Listings/SchedulesDirectDtos/RatingDto.cs6
-rw-r--r--Emby.Server.Implementations/LiveTv/Listings/SchedulesDirectDtos/RecommendationDto.cs6
-rw-r--r--Emby.Server.Implementations/LiveTv/Listings/SchedulesDirectDtos/RequestScheduleForChannelDto.cs7
-rw-r--r--Emby.Server.Implementations/LiveTv/Listings/SchedulesDirectDtos/ShowImagesDto.cs7
-rw-r--r--Emby.Server.Implementations/LiveTv/Listings/SchedulesDirectDtos/StationDto.cs103
-rw-r--r--Emby.Server.Implementations/LiveTv/Listings/SchedulesDirectDtos/TitleDto.cs4
-rw-r--r--Emby.Server.Implementations/LiveTv/Listings/SchedulesDirectDtos/TokenDto.cs21
-rw-r--r--Emby.Server.Implementations/LiveTv/Listings/XmlTvListingsProvider.cs32
-rw-r--r--Emby.Server.Implementations/LiveTv/LiveTvDtoService.cs14
-rw-r--r--Emby.Server.Implementations/LiveTv/LiveTvManager.cs73
-rw-r--r--Emby.Server.Implementations/LiveTv/LiveTvMediaSourceProvider.cs2
-rw-r--r--Emby.Server.Implementations/LiveTv/TunerHosts/HdHomerun/HdHomerunChannelCommands.cs35
-rw-r--r--Emby.Server.Implementations/LiveTv/TunerHosts/HdHomerun/HdHomerunHost.cs12
-rw-r--r--Emby.Server.Implementations/LiveTv/TunerHosts/HdHomerun/HdHomerunManager.cs76
-rw-r--r--Emby.Server.Implementations/LiveTv/TunerHosts/HdHomerun/HdHomerunUdpStream.cs9
-rw-r--r--Emby.Server.Implementations/LiveTv/TunerHosts/HdHomerun/IHdHomerunChannelCommands.cs11
-rw-r--r--Emby.Server.Implementations/LiveTv/TunerHosts/HdHomerun/LegacyHdHomerunChannelCommands.cs38
-rw-r--r--Emby.Server.Implementations/LiveTv/TunerHosts/M3UTunerHost.cs5
-rw-r--r--Emby.Server.Implementations/LiveTv/TunerHosts/M3uParser.cs2
-rw-r--r--Emby.Server.Implementations/LiveTv/TunerHosts/SharedHttpStream.cs2
52 files changed, 518 insertions, 537 deletions
diff --git a/Emby.Server.Implementations/LiveTv/EmbyTV/DirectRecorder.cs b/Emby.Server.Implementations/LiveTv/EmbyTV/DirectRecorder.cs
index 41381d55b..6937cc097 100644
--- a/Emby.Server.Implementations/LiveTv/EmbyTV/DirectRecorder.cs
+++ b/Emby.Server.Implementations/LiveTv/EmbyTV/DirectRecorder.cs
@@ -46,8 +46,7 @@ namespace Emby.Server.Implementations.LiveTv.EmbyTV
{
Directory.CreateDirectory(Path.GetDirectoryName(targetFile) ?? throw new ArgumentException("Path can't be a root directory.", nameof(targetFile)));
- // use FileShare.None as this bypasses dotnet bug dotnet/runtime#42790 .
- using (var output = new FileStream(targetFile, FileMode.Create, FileAccess.Write, FileShare.None, IODefaults.FileStreamBufferSize, FileOptions.Asynchronous))
+ using (var output = new FileStream(targetFile, FileMode.CreateNew, FileAccess.Write, FileShare.Read, IODefaults.FileStreamBufferSize, FileOptions.Asynchronous))
{
onStarted();
@@ -79,8 +78,7 @@ namespace Emby.Server.Implementations.LiveTv.EmbyTV
Directory.CreateDirectory(Path.GetDirectoryName(targetFile) ?? throw new ArgumentException("Path can't be a root directory.", nameof(targetFile)));
- // use FileShare.None as this bypasses dotnet bug dotnet/runtime#42790 .
- await using var output = new FileStream(targetFile, FileMode.Create, FileAccess.Write, FileShare.None, IODefaults.CopyToBufferSize, FileOptions.Asynchronous);
+ await using var output = new FileStream(targetFile, FileMode.CreateNew, FileAccess.Write, FileShare.Read, IODefaults.CopyToBufferSize, FileOptions.Asynchronous);
onStarted();
diff --git a/Emby.Server.Implementations/LiveTv/EmbyTV/EmbyTV.cs b/Emby.Server.Implementations/LiveTv/EmbyTV/EmbyTV.cs
index 64e54aa99..e7834ffd6 100644
--- a/Emby.Server.Implementations/LiveTv/EmbyTV/EmbyTV.cs
+++ b/Emby.Server.Implementations/LiveTv/EmbyTV/EmbyTV.cs
@@ -17,6 +17,7 @@ using System.Xml;
using Emby.Server.Implementations.Library;
using Jellyfin.Data.Enums;
using Jellyfin.Data.Events;
+using Jellyfin.Extensions;
using MediaBrowser.Common.Configuration;
using MediaBrowser.Common.Extensions;
using MediaBrowser.Common.Progress;
@@ -227,7 +228,7 @@ namespace Emby.Server.Implementations.LiveTv.EmbyTV
foreach (var virtualFolder in virtualFolders)
{
- if (!virtualFolder.Locations.Contains(path, StringComparer.OrdinalIgnoreCase))
+ if (!virtualFolder.Locations.Contains(path, StringComparison.OrdinalIgnoreCase))
{
continue;
}
@@ -397,7 +398,7 @@ namespace Emby.Server.Implementations.LiveTv.EmbyTV
}
result = new EpgChannelData(channels);
- _epgChannels.AddOrUpdate(info.Id, result, (k, v) => result);
+ _epgChannels.AddOrUpdate(info.Id, result, (_, _) => result);
}
return result;
@@ -891,7 +892,7 @@ namespace Emby.Server.Implementations.LiveTv.EmbyTV
throw new ArgumentNullException(nameof(tunerHostId));
}
- return info.EnabledTuners.Contains(tunerHostId, StringComparer.OrdinalIgnoreCase);
+ return info.EnabledTuners.Contains(tunerHostId, StringComparison.OrdinalIgnoreCase);
}
public async Task<IEnumerable<ProgramInfo>> GetProgramsAsync(string channelId, DateTime startDateUtc, DateTime endDateUtc, CancellationToken cancellationToken)
@@ -957,7 +958,7 @@ namespace Emby.Server.Implementations.LiveTv.EmbyTV
public async Task<ILiveStream> GetChannelStreamWithDirectStreamProvider(string channelId, string streamId, List<ILiveStream> currentLiveStreams, CancellationToken cancellationToken)
{
- _logger.LogInformation("Streaming Channel " + channelId);
+ _logger.LogInformation("Streaming Channel {Id}", channelId);
var result = string.IsNullOrEmpty(streamId) ?
null :
@@ -1027,7 +1028,7 @@ namespace Emby.Server.Implementations.LiveTv.EmbyTV
{
var stream = new MediaSourceInfo
{
- EncoderPath = _appHost.GetLoopbackHttpApiUrl() + "/LiveTv/LiveRecordings/" + info.Id + "/stream",
+ EncoderPath = _appHost.GetApiUrlForLocalAccess() + "/LiveTv/LiveRecordings/" + info.Id + "/stream",
EncoderProtocol = MediaProtocol.Http,
Path = info.Path,
Protocol = MediaProtocol.File,
@@ -1247,12 +1248,11 @@ namespace Emby.Server.Implementations.LiveTv.EmbyTV
var remoteMetadata = await FetchInternetMetadata(timer, CancellationToken.None).ConfigureAwait(false);
var recordPath = GetRecordingPath(timer, remoteMetadata, out string seriesPath);
- var recordingStatus = RecordingStatus.New;
-
- string liveStreamId = null;
var channelItem = _liveTvManager.GetLiveTvChannel(timer, this);
+ string liveStreamId = null;
+ RecordingStatus recordingStatus;
try
{
var allMediaSources = await _mediaSourceManager.GetPlaybackMediaSources(channelItem, null, true, false, CancellationToken.None).ConfigureAwait(false);
@@ -1308,16 +1308,16 @@ namespace Emby.Server.Implementations.LiveTv.EmbyTV
await recorder.Record(directStreamProvider, mediaStreamInfo, recordPath, duration, onStarted, activeRecordingInfo.CancellationTokenSource.Token).ConfigureAwait(false);
recordingStatus = RecordingStatus.Completed;
- _logger.LogInformation("Recording completed: {recordPath}", recordPath);
+ _logger.LogInformation("Recording completed: {RecordPath}", recordPath);
}
catch (OperationCanceledException)
{
- _logger.LogInformation("Recording stopped: {recordPath}", recordPath);
+ _logger.LogInformation("Recording stopped: {RecordPath}", recordPath);
recordingStatus = RecordingStatus.Completed;
}
catch (Exception ex)
{
- _logger.LogError(ex, "Error recording to {recordPath}", recordPath);
+ _logger.LogError(ex, "Error recording to {RecordPath}", recordPath);
recordingStatus = RecordingStatus.Error;
}
@@ -1338,7 +1338,7 @@ namespace Emby.Server.Implementations.LiveTv.EmbyTV
TriggerRefresh(recordPath);
_libraryMonitor.ReportFileSystemChangeComplete(recordPath, false);
- _activeRecordings.TryRemove(timer.Id, out var removed);
+ _activeRecordings.TryRemove(timer.Id, out _);
if (recordingStatus != RecordingStatus.Completed && DateTime.UtcNow < timer.EndDate && timer.RetryCount < 10)
{
@@ -1404,7 +1404,7 @@ namespace Emby.Server.Implementations.LiveTv.EmbyTV
}
catch (Exception ex)
{
- _logger.LogError(ex, "Error deleting 0-byte failed recording file {path}", path);
+ _logger.LogError(ex, "Error deleting 0-byte failed recording file {Path}", path);
}
}
}
@@ -1778,7 +1778,7 @@ namespace Emby.Server.Implementations.LiveTv.EmbyTV
{
var program = string.IsNullOrWhiteSpace(timer.ProgramId) ? null : _libraryManager.GetItemList(new InternalItemsQuery
{
- IncludeItemTypes = new[] { nameof(LiveTvProgram) },
+ IncludeItemTypes = new[] { BaseItemKind.LiveTvProgram },
Limit = 1,
ExternalId = timer.ProgramId,
DtoOptions = new DtoOptions(true)
@@ -1848,14 +1848,12 @@ namespace Emby.Server.Implementations.LiveTv.EmbyTV
return;
}
- // use FileShare.None as this bypasses dotnet bug dotnet/runtime#42790 .
- using (var stream = new FileStream(nfoPath, FileMode.Create, FileAccess.Write, FileShare.None))
+ using (var stream = new FileStream(nfoPath, FileMode.CreateNew, FileAccess.Write, FileShare.None))
{
var settings = new XmlWriterSettings
{
Indent = true,
- Encoding = Encoding.UTF8,
- CloseOutput = false
+ Encoding = Encoding.UTF8
};
using (var writer = XmlWriter.Create(stream, settings))
@@ -1913,14 +1911,12 @@ namespace Emby.Server.Implementations.LiveTv.EmbyTV
return;
}
- // use FileShare.None as this bypasses dotnet bug dotnet/runtime#42790 .
- using (var stream = new FileStream(nfoPath, FileMode.Create, FileAccess.Write, FileShare.None))
+ using (var stream = new FileStream(nfoPath, FileMode.CreateNew, FileAccess.Write, FileShare.None))
{
var settings = new XmlWriterSettings
{
Indent = true,
- Encoding = Encoding.UTF8,
- CloseOutput = false
+ Encoding = Encoding.UTF8
};
var options = _config.GetNfoConfiguration();
@@ -1940,7 +1936,7 @@ namespace Emby.Server.Implementations.LiveTv.EmbyTV
writer.WriteElementString("title", timer.EpisodeTitle);
}
- var premiereDate = item.PremiereDate ?? (!timer.IsRepeat ? DateTime.UtcNow : (DateTime?)null);
+ var premiereDate = item.PremiereDate ?? (!timer.IsRepeat ? DateTime.UtcNow : null);
if (premiereDate.HasValue)
{
@@ -2129,19 +2125,14 @@ namespace Emby.Server.Implementations.LiveTv.EmbyTV
private LiveTvProgram GetProgramInfoFromCache(TimerInfo timer)
{
- return GetProgramInfoFromCache(timer.ProgramId, timer.ChannelId);
- }
-
- private LiveTvProgram GetProgramInfoFromCache(string programId, string channelId)
- {
- return GetProgramInfoFromCache(programId);
+ return GetProgramInfoFromCache(timer.ProgramId);
}
private LiveTvProgram GetProgramInfoFromCache(string channelId, DateTime startDateUtc)
{
var query = new InternalItemsQuery
{
- IncludeItemTypes = new string[] { nameof(LiveTvProgram) },
+ IncludeItemTypes = new[] { BaseItemKind.LiveTvProgram },
Limit = 1,
DtoOptions = new DtoOptions(true)
{
@@ -2280,7 +2271,7 @@ namespace Emby.Server.Implementations.LiveTv.EmbyTV
{
// Only update if not currently active - test both new timer and existing in case Id's are different
// Id's could be different if the timer was created manually prior to series timer creation
- if (!_activeRecordings.TryGetValue(timer.Id, out var activeRecordingInfo) && !_activeRecordings.TryGetValue(existingTimer.Id, out activeRecordingInfo))
+ if (!_activeRecordings.TryGetValue(timer.Id, out _) && !_activeRecordings.TryGetValue(existingTimer.Id, out _))
{
UpdateExistingTimerWithNewMetadata(existingTimer, timer);
@@ -2301,17 +2292,14 @@ namespace Emby.Server.Implementations.LiveTv.EmbyTV
enabledTimersForSeries.Add(existingTimer);
}
- if (updateTimerSettings)
- {
- existingTimer.KeepUntil = seriesTimer.KeepUntil;
- existingTimer.IsPostPaddingRequired = seriesTimer.IsPostPaddingRequired;
- existingTimer.IsPrePaddingRequired = seriesTimer.IsPrePaddingRequired;
- existingTimer.PostPaddingSeconds = seriesTimer.PostPaddingSeconds;
- existingTimer.PrePaddingSeconds = seriesTimer.PrePaddingSeconds;
- existingTimer.Priority = seriesTimer.Priority;
- }
-
+ existingTimer.KeepUntil = seriesTimer.KeepUntil;
+ existingTimer.IsPostPaddingRequired = seriesTimer.IsPostPaddingRequired;
+ existingTimer.IsPrePaddingRequired = seriesTimer.IsPrePaddingRequired;
+ existingTimer.PostPaddingSeconds = seriesTimer.PostPaddingSeconds;
+ existingTimer.PrePaddingSeconds = seriesTimer.PrePaddingSeconds;
+ existingTimer.Priority = seriesTimer.Priority;
existingTimer.SeriesTimerId = seriesTimer.Id;
+
_timerProvider.Update(existingTimer);
}
}
@@ -2336,7 +2324,7 @@ namespace Emby.Server.Implementations.LiveTv.EmbyTV
var deletes = _timerProvider.GetAll()
.Where(i => string.Equals(i.SeriesTimerId, seriesTimer.Id, StringComparison.OrdinalIgnoreCase))
- .Where(i => !allTimerIds.Contains(i.Id, StringComparer.OrdinalIgnoreCase) && i.StartDate > DateTime.UtcNow)
+ .Where(i => !allTimerIds.Contains(i.Id, StringComparison.OrdinalIgnoreCase) && i.StartDate > DateTime.UtcNow)
.Where(i => deleteStatuses.Contains(i.Status))
.ToList();
@@ -2356,7 +2344,7 @@ namespace Emby.Server.Implementations.LiveTv.EmbyTV
var query = new InternalItemsQuery
{
- IncludeItemTypes = new string[] { nameof(LiveTvProgram) },
+ IncludeItemTypes = new[] { BaseItemKind.LiveTvProgram },
ExternalSeriesId = seriesTimer.SeriesId,
DtoOptions = new DtoOptions(true)
{
@@ -2391,7 +2379,7 @@ namespace Emby.Server.Implementations.LiveTv.EmbyTV
channel = _libraryManager.GetItemList(
new InternalItemsQuery
{
- IncludeItemTypes = new string[] { nameof(LiveTvChannel) },
+ IncludeItemTypes = new[] { BaseItemKind.LiveTvChannel },
ItemIds = new[] { parent.ChannelId },
DtoOptions = new DtoOptions()
}).FirstOrDefault() as LiveTvChannel;
@@ -2450,7 +2438,7 @@ namespace Emby.Server.Implementations.LiveTv.EmbyTV
channel = _libraryManager.GetItemList(
new InternalItemsQuery
{
- IncludeItemTypes = new string[] { nameof(LiveTvChannel) },
+ IncludeItemTypes = new[] { BaseItemKind.LiveTvChannel },
ItemIds = new[] { programInfo.ChannelId },
DtoOptions = new DtoOptions()
}).FirstOrDefault() as LiveTvChannel;
@@ -2515,7 +2503,7 @@ namespace Emby.Server.Implementations.LiveTv.EmbyTV
var seriesIds = _libraryManager.GetItemIds(
new InternalItemsQuery
{
- IncludeItemTypes = new[] { nameof(Series) },
+ IncludeItemTypes = new[] { BaseItemKind.Series },
Name = program.Name
}).ToArray();
@@ -2528,7 +2516,7 @@ namespace Emby.Server.Implementations.LiveTv.EmbyTV
{
var result = _libraryManager.GetItemIds(new InternalItemsQuery
{
- IncludeItemTypes = new[] { nameof(Episode) },
+ IncludeItemTypes = new[] { BaseItemKind.Episode },
ParentIndexNumber = program.SeasonNumber.Value,
IndexNumber = program.EpisodeNumber.Value,
AncestorIds = seriesIds,
@@ -2625,7 +2613,7 @@ namespace Emby.Server.Implementations.LiveTv.EmbyTV
if (newDevicesOnly)
{
- discoveredDevices = discoveredDevices.Where(d => !configuredDeviceIds.Contains(d.DeviceId, StringComparer.OrdinalIgnoreCase))
+ discoveredDevices = discoveredDevices.Where(d => !configuredDeviceIds.Contains(d.DeviceId, StringComparison.OrdinalIgnoreCase))
.ToList();
}
diff --git a/Emby.Server.Implementations/LiveTv/EmbyTV/EncodedRecorder.cs b/Emby.Server.Implementations/LiveTv/EmbyTV/EncodedRecorder.cs
index 3633fa3e1..7fa47e7db 100644
--- a/Emby.Server.Implementations/LiveTv/EmbyTV/EncodedRecorder.cs
+++ b/Emby.Server.Implementations/LiveTv/EmbyTV/EncodedRecorder.cs
@@ -62,12 +62,12 @@ namespace Emby.Server.Implementations.LiveTv.EmbyTV
using var durationToken = new CancellationTokenSource(duration);
using var cancellationTokenSource = CancellationTokenSource.CreateLinkedTokenSource(cancellationToken, durationToken.Token);
- await RecordFromFile(mediaSource, mediaSource.Path, targetFile, duration, onStarted, cancellationTokenSource.Token).ConfigureAwait(false);
+ await RecordFromFile(mediaSource, mediaSource.Path, targetFile, onStarted, cancellationTokenSource.Token).ConfigureAwait(false);
_logger.LogInformation("Recording completed to file {0}", targetFile);
}
- private async Task RecordFromFile(MediaSourceInfo mediaSource, string inputFile, string targetFile, TimeSpan duration, Action onStarted, CancellationToken cancellationToken)
+ private async Task RecordFromFile(MediaSourceInfo mediaSource, string inputFile, string targetFile, Action onStarted, CancellationToken cancellationToken)
{
_targetPath = targetFile;
Directory.CreateDirectory(Path.GetDirectoryName(targetFile));
@@ -81,30 +81,29 @@ namespace Emby.Server.Implementations.LiveTv.EmbyTV
RedirectStandardInput = true,
FileName = _mediaEncoder.EncoderPath,
- Arguments = GetCommandLineArgs(mediaSource, inputFile, targetFile, duration),
+ Arguments = GetCommandLineArgs(mediaSource, inputFile, targetFile),
WindowStyle = ProcessWindowStyle.Hidden,
ErrorDialog = false
};
- var commandLineLogMessage = processStartInfo.FileName + " " + processStartInfo.Arguments;
- _logger.LogInformation(commandLineLogMessage);
+ _logger.LogInformation("{Filename} {Arguments}", processStartInfo.FileName, processStartInfo.Arguments);
var logFilePath = Path.Combine(_appPaths.LogDirectoryPath, "record-transcode-" + Guid.NewGuid() + ".txt");
Directory.CreateDirectory(Path.GetDirectoryName(logFilePath));
// FFMpeg writes debug/error info to stderr. This is useful when debugging so let's put it in the log directory.
- _logFileStream = new FileStream(logFilePath, FileMode.Create, FileAccess.Write, FileShare.Read, IODefaults.FileStreamBufferSize, FileOptions.Asynchronous);
+ _logFileStream = new FileStream(logFilePath, FileMode.CreateNew, FileAccess.Write, FileShare.Read, IODefaults.FileStreamBufferSize, FileOptions.Asynchronous);
await JsonSerializer.SerializeAsync(_logFileStream, mediaSource, _jsonOptions, cancellationToken).ConfigureAwait(false);
- await _logFileStream.WriteAsync(Encoding.UTF8.GetBytes(Environment.NewLine + Environment.NewLine + commandLineLogMessage + Environment.NewLine + Environment.NewLine), cancellationToken).ConfigureAwait(false);
+ await _logFileStream.WriteAsync(Encoding.UTF8.GetBytes(Environment.NewLine + Environment.NewLine + processStartInfo.FileName + " " + processStartInfo.Arguments + Environment.NewLine + Environment.NewLine), cancellationToken).ConfigureAwait(false);
_process = new Process
{
StartInfo = processStartInfo,
EnableRaisingEvents = true
};
- _process.Exited += (sender, args) => OnFfMpegProcessExited(_process);
+ _process.Exited += (_, _) => OnFfMpegProcessExited(_process);
_process.Start();
@@ -118,7 +117,7 @@ namespace Emby.Server.Implementations.LiveTv.EmbyTV
_logger.LogInformation("ffmpeg recording process started for {0}", _targetPath);
}
- private string GetCommandLineArgs(MediaSourceInfo mediaSource, string inputTempFile, string targetFile, TimeSpan duration)
+ private string GetCommandLineArgs(MediaSourceInfo mediaSource, string inputTempFile, string targetFile)
{
string videoArgs;
if (EncodeVideo(mediaSource))
@@ -188,7 +187,7 @@ namespace Emby.Server.Implementations.LiveTv.EmbyTV
CultureInfo.InvariantCulture,
"-i \"{0}\" {2} -map_metadata -1 -threads {6} {3}{4}{5} -y \"{1}\"",
inputTempFile,
- targetFile.Replace("\"", "\\\""), // Escape quotes in filename
+ targetFile.Replace("\"", "\\\"", StringComparison.Ordinal), // Escape quotes in filename
videoArgs,
GetAudioArgs(mediaSource),
subtitleArgs,
@@ -205,9 +204,9 @@ namespace Emby.Server.Implementations.LiveTv.EmbyTV
// var audioChannels = 2;
// var audioStream = mediaStreams.FirstOrDefault(i => i.Type == MediaStreamType.Audio);
// if (audioStream != null)
- //{
+ // {
// audioChannels = audioStream.Channels ?? audioChannels;
- //}
+ // }
// return "-codec:a:0 aac -strict experimental -ab 320000";
}
@@ -225,13 +224,13 @@ namespace Emby.Server.Implementations.LiveTv.EmbyTV
{
try
{
- _logger.LogInformation("Stopping ffmpeg recording process for {path}", _targetPath);
+ _logger.LogInformation("Stopping ffmpeg recording process for {Path}", _targetPath);
_process.StandardInput.WriteLine("q");
}
catch (Exception ex)
{
- _logger.LogError(ex, "Error stopping recording transcoding job for {path}", _targetPath);
+ _logger.LogError(ex, "Error stopping recording transcoding job for {Path}", _targetPath);
}
if (_hasExited)
@@ -241,7 +240,7 @@ namespace Emby.Server.Implementations.LiveTv.EmbyTV
try
{
- _logger.LogInformation("Calling recording process.WaitForExit for {path}", _targetPath);
+ _logger.LogInformation("Calling recording process.WaitForExit for {Path}", _targetPath);
if (_process.WaitForExit(10000))
{
@@ -250,7 +249,7 @@ namespace Emby.Server.Implementations.LiveTv.EmbyTV
}
catch (Exception ex)
{
- _logger.LogError(ex, "Error waiting for recording process to exit for {path}", _targetPath);
+ _logger.LogError(ex, "Error waiting for recording process to exit for {Path}", _targetPath);
}
if (_hasExited)
@@ -260,13 +259,13 @@ namespace Emby.Server.Implementations.LiveTv.EmbyTV
try
{
- _logger.LogInformation("Killing ffmpeg recording process for {path}", _targetPath);
+ _logger.LogInformation("Killing ffmpeg recording process for {Path}", _targetPath);
_process.Kill();
}
catch (Exception ex)
{
- _logger.LogError(ex, "Error killing recording transcoding job for {path}", _targetPath);
+ _logger.LogError(ex, "Error killing recording transcoding job for {Path}", _targetPath);
}
}
}
diff --git a/Emby.Server.Implementations/LiveTv/EmbyTV/IRecorder.cs b/Emby.Server.Implementations/LiveTv/EmbyTV/IRecorder.cs
index dfe3517b2..7705132da 100644
--- a/Emby.Server.Implementations/LiveTv/EmbyTV/IRecorder.cs
+++ b/Emby.Server.Implementations/LiveTv/EmbyTV/IRecorder.cs
@@ -13,6 +13,13 @@ namespace Emby.Server.Implementations.LiveTv.EmbyTV
/// <summary>
/// Records the specified media source.
/// </summary>
+ /// <param name="directStreamProvider">The direct stream provider, or <c>null</c>.</param>
+ /// <param name="mediaSource">The media source.</param>
+ /// <param name="targetFile">The target file.</param>
+ /// <param name="duration">The duration to record.</param>
+ /// <param name="onStarted">An action to perform when recording starts.</param>
+ /// <param name="cancellationToken">The cancellation token.</param>
+ /// <returns>A <see cref="Task"/> that represents the recording operation.</returns>
Task Record(IDirectStreamProvider? directStreamProvider, MediaSourceInfo mediaSource, string targetFile, TimeSpan duration, Action onStarted, CancellationToken cancellationToken);
string GetOutputPath(MediaSourceInfo mediaSource, string targetFile);
diff --git a/Emby.Server.Implementations/LiveTv/EmbyTV/ItemDataProvider.cs b/Emby.Server.Implementations/LiveTv/EmbyTV/ItemDataProvider.cs
index 4a031e475..46979bfc5 100644
--- a/Emby.Server.Implementations/LiveTv/EmbyTV/ItemDataProvider.cs
+++ b/Emby.Server.Implementations/LiveTv/EmbyTV/ItemDataProvider.cs
@@ -1,9 +1,8 @@
-#nullable disable
-
#pragma warning disable CS1591
using System;
using System.Collections.Generic;
+using System.Diagnostics.CodeAnalysis;
using System.IO;
using System.Linq;
using System.Text.Json;
@@ -18,7 +17,7 @@ namespace Emby.Server.Implementations.LiveTv.EmbyTV
private readonly string _dataPath;
private readonly object _fileDataLock = new object();
private readonly JsonSerializerOptions _jsonOptions = JsonDefaults.Options;
- private T[] _items;
+ private T[]? _items;
public ItemDataProvider(
ILogger logger,
@@ -34,6 +33,7 @@ namespace Emby.Server.Implementations.LiveTv.EmbyTV
protected Func<T, T, bool> EqualityComparer { get; }
+ [MemberNotNull(nameof(_items))]
private void EnsureLoaded()
{
if (_items != null)
@@ -49,6 +49,12 @@ namespace Emby.Server.Implementations.LiveTv.EmbyTV
{
var bytes = File.ReadAllBytes(_dataPath);
_items = JsonSerializer.Deserialize<T[]>(bytes, _jsonOptions);
+ if (_items == null)
+ {
+ Logger.LogError("Error deserializing {Path}, data was null", _dataPath);
+ _items = Array.Empty<T>();
+ }
+
return;
}
catch (JsonException ex)
@@ -62,7 +68,7 @@ namespace Emby.Server.Implementations.LiveTv.EmbyTV
private void SaveList()
{
- Directory.CreateDirectory(Path.GetDirectoryName(_dataPath));
+ Directory.CreateDirectory(Path.GetDirectoryName(_dataPath) ?? throw new ArgumentException("Path can't be a root directory.", nameof(_dataPath)));
var jsonString = JsonSerializer.Serialize(_items, _jsonOptions);
File.WriteAllText(_dataPath, jsonString);
}
diff --git a/Emby.Server.Implementations/LiveTv/Listings/SchedulesDirect.cs b/Emby.Server.Implementations/LiveTv/Listings/SchedulesDirect.cs
index 8125ed57d..a8440102d 100644
--- a/Emby.Server.Implementations/LiveTv/Listings/SchedulesDirect.cs
+++ b/Emby.Server.Implementations/LiveTv/Listings/SchedulesDirect.cs
@@ -9,17 +9,18 @@ using System.Globalization;
using System.Linq;
using System.Net;
using System.Net.Http;
+using System.Net.Http.Json;
using System.Net.Mime;
+using System.Security.Cryptography;
using System.Text;
using System.Text.Json;
using System.Threading;
using System.Threading.Tasks;
using Emby.Server.Implementations.LiveTv.Listings.SchedulesDirectDtos;
+using Jellyfin.Extensions;
using Jellyfin.Extensions.Json;
-using MediaBrowser.Common;
using MediaBrowser.Common.Net;
using MediaBrowser.Controller.LiveTv;
-using MediaBrowser.Model.Cryptography;
using MediaBrowser.Model.Dto;
using MediaBrowser.Model.Entities;
using MediaBrowser.Model.LiveTv;
@@ -34,8 +35,6 @@ namespace Emby.Server.Implementations.LiveTv.Listings
private readonly ILogger<SchedulesDirect> _logger;
private readonly IHttpClientFactory _httpClientFactory;
private readonly SemaphoreSlim _tokenSemaphore = new SemaphoreSlim(1, 1);
- private readonly IApplicationHost _appHost;
- private readonly ICryptoProvider _cryptoProvider;
private readonly ConcurrentDictionary<string, NameValuePair> _tokens = new ConcurrentDictionary<string, NameValuePair>();
private readonly JsonSerializerOptions _jsonOptions = JsonDefaults.Options;
@@ -43,14 +42,10 @@ namespace Emby.Server.Implementations.LiveTv.Listings
public SchedulesDirect(
ILogger<SchedulesDirect> logger,
- IHttpClientFactory httpClientFactory,
- IApplicationHost appHost,
- ICryptoProvider cryptoProvider)
+ IHttpClientFactory httpClientFactory)
{
_logger = logger;
_httpClientFactory = httpClientFactory;
- _appHost = appHost;
- _cryptoProvider = cryptoProvider;
}
/// <inheritdoc />
@@ -106,26 +101,35 @@ namespace Emby.Server.Implementations.LiveTv.Listings
}
};
- var requestString = JsonSerializer.Serialize(requestList, _jsonOptions);
- _logger.LogDebug("Request string for schedules is: {RequestString}", requestString);
+ _logger.LogDebug("Request string for schedules is: {@RequestString}", requestList);
using var options = new HttpRequestMessage(HttpMethod.Post, ApiUrl + "/schedules");
- options.Content = new StringContent(requestString, Encoding.UTF8, MediaTypeNames.Application.Json);
+ options.Content = JsonContent.Create(requestList, options: _jsonOptions);
options.Headers.TryAddWithoutValidation("token", token);
using var response = await Send(options, true, info, cancellationToken).ConfigureAwait(false);
await using var responseStream = await response.Content.ReadAsStreamAsync(cancellationToken).ConfigureAwait(false);
- var dailySchedules = await JsonSerializer.DeserializeAsync<List<DayDto>>(responseStream, _jsonOptions, cancellationToken).ConfigureAwait(false);
+ var dailySchedules = await JsonSerializer.DeserializeAsync<IReadOnlyList<DayDto>>(responseStream, _jsonOptions, cancellationToken).ConfigureAwait(false);
+ if (dailySchedules == null)
+ {
+ return Array.Empty<ProgramInfo>();
+ }
+
_logger.LogDebug("Found {ScheduleCount} programs on {ChannelID} ScheduleDirect", dailySchedules.Count, channelId);
using var programRequestOptions = new HttpRequestMessage(HttpMethod.Post, ApiUrl + "/programs");
programRequestOptions.Headers.TryAddWithoutValidation("token", token);
- var programsID = dailySchedules.SelectMany(d => d.Programs.Select(s => s.ProgramId)).Distinct();
- programRequestOptions.Content = new StringContent("[\"" + string.Join("\", \"", programsID) + "\"]", Encoding.UTF8, MediaTypeNames.Application.Json);
+ var programIds = dailySchedules.SelectMany(d => d.Programs.Select(s => s.ProgramId)).Distinct();
+ programRequestOptions.Content = JsonContent.Create(programIds, options: _jsonOptions);
using var innerResponse = await Send(programRequestOptions, true, info, cancellationToken).ConfigureAwait(false);
await using var innerResponseStream = await innerResponse.Content.ReadAsStreamAsync(cancellationToken).ConfigureAwait(false);
- var programDetails = await JsonSerializer.DeserializeAsync<List<ProgramDetailsDto>>(innerResponseStream, _jsonOptions, cancellationToken).ConfigureAwait(false);
+ var programDetails = await JsonSerializer.DeserializeAsync<IReadOnlyList<ProgramDetailsDto>>(innerResponseStream, _jsonOptions, cancellationToken).ConfigureAwait(false);
+ if (programDetails == null)
+ {
+ return Array.Empty<ProgramInfo>();
+ }
+
var programDict = programDetails.ToDictionary(p => p.ProgramId, y => y);
var programIdsWithImages = programDetails
@@ -142,6 +146,11 @@ namespace Emby.Server.Implementations.LiveTv.Listings
// schedule.ProgramId + " which says it has images? " +
// programDict[schedule.ProgramId].hasImageArtwork);
+ if (string.IsNullOrEmpty(schedule.ProgramId))
+ {
+ continue;
+ }
+
if (images != null)
{
var imageIndex = images.FindIndex(i => i.ProgramId == schedule.ProgramId[..10]);
@@ -149,18 +158,18 @@ namespace Emby.Server.Implementations.LiveTv.Listings
{
var programEntry = programDict[schedule.ProgramId];
- var allImages = images[imageIndex].Data ?? new List<ImageDataDto>();
- var imagesWithText = allImages.Where(i => string.Equals(i.Text, "yes", StringComparison.OrdinalIgnoreCase));
- var imagesWithoutText = allImages.Where(i => string.Equals(i.Text, "no", StringComparison.OrdinalIgnoreCase));
+ var allImages = images[imageIndex].Data;
+ var imagesWithText = allImages.Where(i => string.Equals(i.Text, "yes", StringComparison.OrdinalIgnoreCase)).ToList();
+ var imagesWithoutText = allImages.Where(i => string.Equals(i.Text, "no", StringComparison.OrdinalIgnoreCase)).ToList();
const double DesiredAspect = 2.0 / 3;
- programEntry.PrimaryImage = GetProgramImage(ApiUrl, imagesWithText, true, DesiredAspect) ??
- GetProgramImage(ApiUrl, allImages, true, DesiredAspect);
+ programEntry.PrimaryImage = GetProgramImage(ApiUrl, imagesWithText, DesiredAspect) ??
+ GetProgramImage(ApiUrl, allImages, DesiredAspect);
const double WideAspect = 16.0 / 9;
- programEntry.ThumbImage = GetProgramImage(ApiUrl, imagesWithText, true, WideAspect);
+ programEntry.ThumbImage = GetProgramImage(ApiUrl, imagesWithText, WideAspect);
// Don't supply the same image twice
if (string.Equals(programEntry.PrimaryImage, programEntry.ThumbImage, StringComparison.Ordinal))
@@ -168,7 +177,7 @@ namespace Emby.Server.Implementations.LiveTv.Listings
programEntry.ThumbImage = null;
}
- programEntry.BackdropImage = GetProgramImage(ApiUrl, imagesWithoutText, true, WideAspect);
+ programEntry.BackdropImage = GetProgramImage(ApiUrl, imagesWithoutText, WideAspect);
// programEntry.bannerImage = GetProgramImage(ApiUrl, data, "Banner", false) ??
// GetProgramImage(ApiUrl, data, "Banner-L1", false) ??
@@ -217,7 +226,12 @@ namespace Emby.Server.Implementations.LiveTv.Listings
private ProgramInfo GetProgram(string channelId, ProgramDto programInfo, ProgramDetailsDto details)
{
- var startAt = GetDate(programInfo.AirDateTime);
+ if (programInfo.AirDateTime == null)
+ {
+ return null;
+ }
+
+ var startAt = programInfo.AirDateTime.Value;
var endAt = startAt.AddSeconds(programInfo.Duration);
var audioType = ProgramAudio.Stereo;
@@ -225,21 +239,21 @@ namespace Emby.Server.Implementations.LiveTv.Listings
string newID = programId + "T" + startAt.Ticks + "C" + channelId;
- if (programInfo.AudioProperties != null)
+ if (programInfo.AudioProperties.Count != 0)
{
- if (programInfo.AudioProperties.Exists(item => string.Equals(item, "atmos", StringComparison.OrdinalIgnoreCase)))
+ if (programInfo.AudioProperties.Contains("atmos", StringComparison.OrdinalIgnoreCase))
{
audioType = ProgramAudio.Atmos;
}
- else if (programInfo.AudioProperties.Exists(item => string.Equals(item, "dd 5.1", StringComparison.OrdinalIgnoreCase)))
+ else if (programInfo.AudioProperties.Contains("dd 5.1", StringComparison.OrdinalIgnoreCase))
{
audioType = ProgramAudio.DolbyDigital;
}
- else if (programInfo.AudioProperties.Exists(item => string.Equals(item, "dd", StringComparison.OrdinalIgnoreCase)))
+ else if (programInfo.AudioProperties.Contains("dd", StringComparison.OrdinalIgnoreCase))
{
audioType = ProgramAudio.DolbyDigital;
}
- else if (programInfo.AudioProperties.Exists(item => string.Equals(item, "stereo", StringComparison.OrdinalIgnoreCase)))
+ else if (programInfo.AudioProperties.Contains("stereo", StringComparison.OrdinalIgnoreCase))
{
audioType = ProgramAudio.Stereo;
}
@@ -301,8 +315,8 @@ namespace Emby.Server.Implementations.LiveTv.Listings
if (programInfo.VideoProperties != null)
{
- info.IsHD = programInfo.VideoProperties.Contains("hdtv", StringComparer.OrdinalIgnoreCase);
- info.Is3D = programInfo.VideoProperties.Contains("3d", StringComparer.OrdinalIgnoreCase);
+ info.IsHD = programInfo.VideoProperties.Contains("hdtv", StringComparison.OrdinalIgnoreCase);
+ info.Is3D = programInfo.VideoProperties.Contains("3d", StringComparison.OrdinalIgnoreCase);
}
if (details.ContentRating != null && details.ContentRating.Count > 0)
@@ -311,7 +325,7 @@ namespace Emby.Server.Implementations.LiveTv.Listings
.Replace("--", "-", StringComparison.Ordinal);
var invalid = new[] { "N/A", "Approved", "Not Rated", "Passed" };
- if (invalid.Contains(info.OfficialRating, StringComparer.OrdinalIgnoreCase))
+ if (invalid.Contains(info.OfficialRating, StringComparison.OrdinalIgnoreCase))
{
info.OfficialRating = null;
}
@@ -355,9 +369,9 @@ namespace Emby.Server.Implementations.LiveTv.Listings
}
}
- if (!string.IsNullOrWhiteSpace(details.OriginalAirDate))
+ if (details.OriginalAirDate != null)
{
- info.OriginalAirDate = DateTime.Parse(details.OriginalAirDate, CultureInfo.InvariantCulture);
+ info.OriginalAirDate = details.OriginalAirDate;
info.ProductionYear = info.OriginalAirDate.Value.Year;
}
@@ -373,9 +387,9 @@ namespace Emby.Server.Implementations.LiveTv.Listings
if (details.Genres != null)
{
info.Genres = details.Genres.Where(g => !string.IsNullOrWhiteSpace(g)).ToList();
- info.IsNews = details.Genres.Contains("news", StringComparer.OrdinalIgnoreCase);
+ info.IsNews = details.Genres.Contains("news", StringComparison.OrdinalIgnoreCase);
- if (info.Genres.Contains("children", StringComparer.OrdinalIgnoreCase))
+ if (info.Genres.Contains("children", StringComparison.OrdinalIgnoreCase))
{
info.IsKids = true;
}
@@ -384,19 +398,7 @@ namespace Emby.Server.Implementations.LiveTv.Listings
return info;
}
- private static DateTime GetDate(string value)
- {
- var date = DateTime.ParseExact(value, "yyyy'-'MM'-'dd'T'HH':'mm':'ss'Z'", CultureInfo.InvariantCulture);
-
- if (date.Kind != DateTimeKind.Utc)
- {
- date = DateTime.SpecifyKind(date, DateTimeKind.Utc);
- }
-
- return date;
- }
-
- private string GetProgramImage(string apiUrl, IEnumerable<ImageDataDto> images, bool returnDefaultImage, double desiredAspect)
+ private static string GetProgramImage(string apiUrl, IEnumerable<ImageDataDto> images, double desiredAspect)
{
var match = images
.OrderBy(i => Math.Abs(desiredAspect - GetAspectRatio(i)))
@@ -449,14 +451,14 @@ namespace Emby.Server.Implementations.LiveTv.Listings
return result;
}
- private async Task<List<ShowImagesDto>> GetImageForPrograms(
+ private async Task<IReadOnlyList<ShowImagesDto>> GetImageForPrograms(
ListingsProviderInfo info,
IReadOnlyList<string> programIds,
CancellationToken cancellationToken)
{
if (programIds.Count == 0)
{
- return new List<ShowImagesDto>();
+ return Array.Empty<ShowImagesDto>();
}
StringBuilder str = new StringBuilder("[", 1 + (programIds.Count * 13));
@@ -480,13 +482,13 @@ namespace Emby.Server.Implementations.LiveTv.Listings
{
using var innerResponse2 = await Send(message, true, info, cancellationToken).ConfigureAwait(false);
await using var response = await innerResponse2.Content.ReadAsStreamAsync(cancellationToken).ConfigureAwait(false);
- return await JsonSerializer.DeserializeAsync<List<ShowImagesDto>>(response, _jsonOptions, cancellationToken).ConfigureAwait(false);
+ return await JsonSerializer.DeserializeAsync<IReadOnlyList<ShowImagesDto>>(response, _jsonOptions, cancellationToken).ConfigureAwait(false);
}
catch (Exception ex)
{
_logger.LogError(ex, "Error getting image info from schedules direct");
- return new List<ShowImagesDto>();
+ return Array.Empty<ShowImagesDto>();
}
}
@@ -509,7 +511,7 @@ namespace Emby.Server.Implementations.LiveTv.Listings
using var httpResponse = await Send(options, false, info, cancellationToken).ConfigureAwait(false);
await using var response = await httpResponse.Content.ReadAsStreamAsync(cancellationToken).ConfigureAwait(false);
- var root = await JsonSerializer.DeserializeAsync<List<HeadendsDto>>(response, _jsonOptions, cancellationToken).ConfigureAwait(false);
+ var root = await JsonSerializer.DeserializeAsync<IReadOnlyList<HeadendsDto>>(response, _jsonOptions, cancellationToken).ConfigureAwait(false);
if (root != null)
{
@@ -520,7 +522,7 @@ namespace Emby.Server.Implementations.LiveTv.Listings
lineups.Add(new NameIdPair
{
Name = string.IsNullOrWhiteSpace(lineup.Name) ? lineup.Lineup : lineup.Name,
- Id = lineup.Uri[18..]
+ Id = lineup.Uri?[18..]
});
}
}
@@ -641,7 +643,9 @@ namespace Emby.Server.Implementations.LiveTv.Listings
CancellationToken cancellationToken)
{
using var options = new HttpRequestMessage(HttpMethod.Post, ApiUrl + "/token");
- var hashedPasswordBytes = _cryptoProvider.ComputeHash("SHA1", Encoding.ASCII.GetBytes(password), Array.Empty<byte>());
+#pragma warning disable CA5350 // SchedulesDirect is always SHA1.
+ var hashedPasswordBytes = SHA1.HashData(Encoding.ASCII.GetBytes(password));
+#pragma warning restore CA5350
// TODO: remove ToLower when Convert.ToHexString supports lowercase
// Schedules Direct requires the hex to be lowercase
string hashedPassword = Convert.ToHexString(hashedPasswordBytes).ToLowerInvariant();
@@ -651,7 +655,7 @@ namespace Emby.Server.Implementations.LiveTv.Listings
response.EnsureSuccessStatusCode();
await using var stream = await response.Content.ReadAsStreamAsync(cancellationToken).ConfigureAwait(false);
var root = await JsonSerializer.DeserializeAsync<TokenDto>(stream, _jsonOptions, cancellationToken).ConfigureAwait(false);
- if (string.Equals(root.Message, "OK", StringComparison.Ordinal))
+ if (string.Equals(root?.Message, "OK", StringComparison.Ordinal))
{
_logger.LogInformation("Authenticated with Schedules Direct token: {Token}", root.Token);
return root.Token;
@@ -708,12 +712,12 @@ namespace Emby.Server.Implementations.LiveTv.Listings
using var response = httpResponse.Content;
var root = await JsonSerializer.DeserializeAsync<LineupsDto>(stream, _jsonOptions, cancellationToken).ConfigureAwait(false);
- return root.Lineups.Any(i => string.Equals(info.ListingsId, i.Lineup, StringComparison.OrdinalIgnoreCase));
+ return root?.Lineups.Any(i => string.Equals(info.ListingsId, i.Lineup, StringComparison.OrdinalIgnoreCase)) ?? false;
}
catch (HttpRequestException ex)
{
// SchedulesDirect returns 400 if no lineups are configured.
- if (ex.StatusCode.HasValue && ex.StatusCode.Value == HttpStatusCode.BadRequest)
+ if (ex.StatusCode is HttpStatusCode.BadRequest)
{
return false;
}
@@ -779,10 +783,15 @@ namespace Emby.Server.Implementations.LiveTv.Listings
using var httpResponse = await Send(options, true, info, cancellationToken).ConfigureAwait(false);
await using var stream = await httpResponse.Content.ReadAsStreamAsync(cancellationToken).ConfigureAwait(false);
var root = await JsonSerializer.DeserializeAsync<ChannelDto>(stream, _jsonOptions, cancellationToken).ConfigureAwait(false);
+ if (root == null)
+ {
+ return new List<ChannelInfo>();
+ }
+
_logger.LogInformation("Found {ChannelCount} channels on the lineup on ScheduleDirect", root.Map.Count);
_logger.LogInformation("Mapping Stations to Channel");
- var allStations = root.Stations ?? new List<StationDto>();
+ var allStations = root.Stations;
var map = root.Map;
var list = new List<ChannelInfo>(map.Count);
@@ -790,11 +799,10 @@ namespace Emby.Server.Implementations.LiveTv.Listings
{
var channelNumber = GetChannelNumber(channel);
- var station = allStations.Find(item => string.Equals(item.StationId, channel.StationId, StringComparison.OrdinalIgnoreCase))
- ?? new StationDto
- {
- StationId = channel.StationId
- };
+ var stationIndex = allStations.FindIndex(item => string.Equals(item.StationId, channel.StationId, StringComparison.OrdinalIgnoreCase));
+ var station = stationIndex == -1
+ ? new StationDto { StationId = channel.StationId }
+ : allStations[stationIndex];
var channelInfo = new ChannelInfo
{
@@ -814,10 +822,5 @@ namespace Emby.Server.Implementations.LiveTv.Listings
return list;
}
-
- private static string NormalizeName(string value)
- {
- return value.Replace(" ", string.Empty, StringComparison.Ordinal).Replace("-", string.Empty, StringComparison.Ordinal);
- }
}
}
diff --git a/Emby.Server.Implementations/LiveTv/Listings/SchedulesDirectDtos/BroadcasterDto.cs b/Emby.Server.Implementations/LiveTv/Listings/SchedulesDirectDtos/BroadcasterDto.cs
index b881b307c..95ac996e0 100644
--- a/Emby.Server.Implementations/LiveTv/Listings/SchedulesDirectDtos/BroadcasterDto.cs
+++ b/Emby.Server.Implementations/LiveTv/Listings/SchedulesDirectDtos/BroadcasterDto.cs
@@ -1,5 +1,3 @@
-#nullable disable
-
using System.Text.Json.Serialization;
namespace Emby.Server.Implementations.LiveTv.Listings.SchedulesDirectDtos
@@ -13,24 +11,24 @@ namespace Emby.Server.Implementations.LiveTv.Listings.SchedulesDirectDtos
/// Gets or sets the city.
/// </summary>
[JsonPropertyName("city")]
- public string City { get; set; }
+ public string? City { get; set; }
/// <summary>
/// Gets or sets the state.
/// </summary>
[JsonPropertyName("state")]
- public string State { get; set; }
+ public string? State { get; set; }
/// <summary>
/// Gets or sets the postal code.
/// </summary>
[JsonPropertyName("postalCode")]
- public string Postalcode { get; set; }
+ public string? Postalcode { get; set; }
/// <summary>
/// Gets or sets the country.
/// </summary>
[JsonPropertyName("country")]
- public string Country { get; set; }
+ public string? Country { get; set; }
}
}
diff --git a/Emby.Server.Implementations/LiveTv/Listings/SchedulesDirectDtos/CaptionDto.cs b/Emby.Server.Implementations/LiveTv/Listings/SchedulesDirectDtos/CaptionDto.cs
index 96b67d1eb..f6251b9ad 100644
--- a/Emby.Server.Implementations/LiveTv/Listings/SchedulesDirectDtos/CaptionDto.cs
+++ b/Emby.Server.Implementations/LiveTv/Listings/SchedulesDirectDtos/CaptionDto.cs
@@ -1,5 +1,3 @@
-#nullable disable
-
using System.Text.Json.Serialization;
namespace Emby.Server.Implementations.LiveTv.Listings.SchedulesDirectDtos
@@ -13,12 +11,12 @@ namespace Emby.Server.Implementations.LiveTv.Listings.SchedulesDirectDtos
/// Gets or sets the content.
/// </summary>
[JsonPropertyName("content")]
- public string Content { get; set; }
+ public string? Content { get; set; }
/// <summary>
/// Gets or sets the lang.
/// </summary>
[JsonPropertyName("lang")]
- public string Lang { get; set; }
+ public string? Lang { get; set; }
}
}
diff --git a/Emby.Server.Implementations/LiveTv/Listings/SchedulesDirectDtos/CastDto.cs b/Emby.Server.Implementations/LiveTv/Listings/SchedulesDirectDtos/CastDto.cs
index dac6f5f3e..0b7a2c63a 100644
--- a/Emby.Server.Implementations/LiveTv/Listings/SchedulesDirectDtos/CastDto.cs
+++ b/Emby.Server.Implementations/LiveTv/Listings/SchedulesDirectDtos/CastDto.cs
@@ -1,5 +1,3 @@
-#nullable disable
-
using System.Text.Json.Serialization;
namespace Emby.Server.Implementations.LiveTv.Listings.SchedulesDirectDtos
@@ -13,36 +11,36 @@ namespace Emby.Server.Implementations.LiveTv.Listings.SchedulesDirectDtos
/// Gets or sets the billing order.
/// </summary>
[JsonPropertyName("billingOrder")]
- public string BillingOrder { get; set; }
+ public string? BillingOrder { get; set; }
/// <summary>
/// Gets or sets the role.
/// </summary>
[JsonPropertyName("role")]
- public string Role { get; set; }
+ public string? Role { get; set; }
/// <summary>
/// Gets or sets the name id.
/// </summary>
[JsonPropertyName("nameId")]
- public string NameId { get; set; }
+ public string? NameId { get; set; }
/// <summary>
/// Gets or sets the person id.
/// </summary>
[JsonPropertyName("personId")]
- public string PersonId { get; set; }
+ public string? PersonId { get; set; }
/// <summary>
/// Gets or sets the name.
/// </summary>
[JsonPropertyName("name")]
- public string Name { get; set; }
+ public string? Name { get; set; }
/// <summary>
/// Gets or sets the character name.
/// </summary>
[JsonPropertyName("characterName")]
- public string CharacterName { get; set; }
+ public string? CharacterName { get; set; }
}
}
diff --git a/Emby.Server.Implementations/LiveTv/Listings/SchedulesDirectDtos/ChannelDto.cs b/Emby.Server.Implementations/LiveTv/Listings/SchedulesDirectDtos/ChannelDto.cs
index 8c9c2c1fc..87c327ed8 100644
--- a/Emby.Server.Implementations/LiveTv/Listings/SchedulesDirectDtos/ChannelDto.cs
+++ b/Emby.Server.Implementations/LiveTv/Listings/SchedulesDirectDtos/ChannelDto.cs
@@ -1,5 +1,4 @@
-#nullable disable
-
+using System;
using System.Collections.Generic;
using System.Text.Json.Serialization;
@@ -14,18 +13,18 @@ namespace Emby.Server.Implementations.LiveTv.Listings.SchedulesDirectDtos
/// Gets or sets the list of maps.
/// </summary>
[JsonPropertyName("map")]
- public List<MapDto> Map { get; set; }
+ public IReadOnlyList<MapDto> Map { get; set; } = Array.Empty<MapDto>();
/// <summary>
/// Gets or sets the list of stations.
/// </summary>
[JsonPropertyName("stations")]
- public List<StationDto> Stations { get; set; }
+ public IReadOnlyList<StationDto> Stations { get; set; } = Array.Empty<StationDto>();
/// <summary>
/// Gets or sets the metadata.
/// </summary>
[JsonPropertyName("metadata")]
- public MetadataDto Metadata { get; set; }
+ public MetadataDto? Metadata { get; set; }
}
}
diff --git a/Emby.Server.Implementations/LiveTv/Listings/SchedulesDirectDtos/ContentRatingDto.cs b/Emby.Server.Implementations/LiveTv/Listings/SchedulesDirectDtos/ContentRatingDto.cs
index 135b5bb08..c19cd2e48 100644
--- a/Emby.Server.Implementations/LiveTv/Listings/SchedulesDirectDtos/ContentRatingDto.cs
+++ b/Emby.Server.Implementations/LiveTv/Listings/SchedulesDirectDtos/ContentRatingDto.cs
@@ -1,5 +1,3 @@
-#nullable disable
-
using System.Text.Json.Serialization;
namespace Emby.Server.Implementations.LiveTv.Listings.SchedulesDirectDtos
@@ -13,12 +11,12 @@ namespace Emby.Server.Implementations.LiveTv.Listings.SchedulesDirectDtos
/// Gets or sets the body.
/// </summary>
[JsonPropertyName("body")]
- public string Body { get; set; }
+ public string? Body { get; set; }
/// <summary>
/// Gets or sets the code.
/// </summary>
[JsonPropertyName("code")]
- public string Code { get; set; }
+ public string? Code { get; set; }
}
}
diff --git a/Emby.Server.Implementations/LiveTv/Listings/SchedulesDirectDtos/CrewDto.cs b/Emby.Server.Implementations/LiveTv/Listings/SchedulesDirectDtos/CrewDto.cs
index 82d1001c8..f00c9accd 100644
--- a/Emby.Server.Implementations/LiveTv/Listings/SchedulesDirectDtos/CrewDto.cs
+++ b/Emby.Server.Implementations/LiveTv/Listings/SchedulesDirectDtos/CrewDto.cs
@@ -1,5 +1,3 @@
-#nullable disable
-
using System.Text.Json.Serialization;
namespace Emby.Server.Implementations.LiveTv.Listings.SchedulesDirectDtos
@@ -13,30 +11,30 @@ namespace Emby.Server.Implementations.LiveTv.Listings.SchedulesDirectDtos
/// Gets or sets the billing order.
/// </summary>
[JsonPropertyName("billingOrder")]
- public string BillingOrder { get; set; }
+ public string? BillingOrder { get; set; }
/// <summary>
/// Gets or sets the role.
/// </summary>
[JsonPropertyName("role")]
- public string Role { get; set; }
+ public string? Role { get; set; }
/// <summary>
/// Gets or sets the name id.
/// </summary>
[JsonPropertyName("nameId")]
- public string NameId { get; set; }
+ public string? NameId { get; set; }
/// <summary>
/// Gets or sets the person id.
/// </summary>
[JsonPropertyName("personId")]
- public string PersonId { get; set; }
+ public string? PersonId { get; set; }
/// <summary>
/// Gets or sets the name.
/// </summary>
[JsonPropertyName("name")]
- public string Name { get; set; }
+ public string? Name { get; set; }
}
}
diff --git a/Emby.Server.Implementations/LiveTv/Listings/SchedulesDirectDtos/DayDto.cs b/Emby.Server.Implementations/LiveTv/Listings/SchedulesDirectDtos/DayDto.cs
index 68876b068..1a371965c 100644
--- a/Emby.Server.Implementations/LiveTv/Listings/SchedulesDirectDtos/DayDto.cs
+++ b/Emby.Server.Implementations/LiveTv/Listings/SchedulesDirectDtos/DayDto.cs
@@ -1,5 +1,4 @@
-#nullable disable
-
+using System;
using System.Collections.Generic;
using System.Text.Json.Serialization;
@@ -11,29 +10,21 @@ namespace Emby.Server.Implementations.LiveTv.Listings.SchedulesDirectDtos
public class DayDto
{
/// <summary>
- /// Initializes a new instance of the <see cref="DayDto"/> class.
- /// </summary>
- public DayDto()
- {
- Programs = new List<ProgramDto>();
- }
-
- /// <summary>
/// Gets or sets the station id.
/// </summary>
[JsonPropertyName("stationID")]
- public string StationId { get; set; }
+ public string? StationId { get; set; }
/// <summary>
/// Gets or sets the list of programs.
/// </summary>
[JsonPropertyName("programs")]
- public List<ProgramDto> Programs { get; set; }
+ public IReadOnlyList<ProgramDto> Programs { get; set; } = Array.Empty<ProgramDto>();
/// <summary>
/// Gets or sets the metadata schedule.
/// </summary>
[JsonPropertyName("metadata")]
- public MetadataScheduleDto Metadata { get; set; }
+ public MetadataScheduleDto? Metadata { get; set; }
}
}
diff --git a/Emby.Server.Implementations/LiveTv/Listings/SchedulesDirectDtos/Description1000Dto.cs b/Emby.Server.Implementations/LiveTv/Listings/SchedulesDirectDtos/Description1000Dto.cs
index d3e6ff393..ca6ae7fb1 100644
--- a/Emby.Server.Implementations/LiveTv/Listings/SchedulesDirectDtos/Description1000Dto.cs
+++ b/Emby.Server.Implementations/LiveTv/Listings/SchedulesDirectDtos/Description1000Dto.cs
@@ -1,5 +1,3 @@
-#nullable disable
-
using System.Text.Json.Serialization;
namespace Emby.Server.Implementations.LiveTv.Listings.SchedulesDirectDtos
@@ -13,12 +11,12 @@ namespace Emby.Server.Implementations.LiveTv.Listings.SchedulesDirectDtos
/// Gets or sets the description language.
/// </summary>
[JsonPropertyName("descriptionLanguage")]
- public string DescriptionLanguage { get; set; }
+ public string? DescriptionLanguage { get; set; }
/// <summary>
/// Gets or sets the description.
/// </summary>
[JsonPropertyName("description")]
- public string Description { get; set; }
+ public string? Description { get; set; }
}
}
diff --git a/Emby.Server.Implementations/LiveTv/Listings/SchedulesDirectDtos/Description100Dto.cs b/Emby.Server.Implementations/LiveTv/Listings/SchedulesDirectDtos/Description100Dto.cs
index 04360266c..1577219ed 100644
--- a/Emby.Server.Implementations/LiveTv/Listings/SchedulesDirectDtos/Description100Dto.cs
+++ b/Emby.Server.Implementations/LiveTv/Listings/SchedulesDirectDtos/Description100Dto.cs
@@ -1,5 +1,3 @@
-#nullable disable
-
using System.Text.Json.Serialization;
namespace Emby.Server.Implementations.LiveTv.Listings.SchedulesDirectDtos
@@ -13,12 +11,12 @@ namespace Emby.Server.Implementations.LiveTv.Listings.SchedulesDirectDtos
/// Gets or sets the description language.
/// </summary>
[JsonPropertyName("descriptionLanguage")]
- public string DescriptionLanguage { get; set; }
+ public string? DescriptionLanguage { get; set; }
/// <summary>
/// Gets or sets the description.
/// </summary>
[JsonPropertyName("description")]
- public string Description { get; set; }
+ public string? Description { get; set; }
}
}
diff --git a/Emby.Server.Implementations/LiveTv/Listings/SchedulesDirectDtos/DescriptionsProgramDto.cs b/Emby.Server.Implementations/LiveTv/Listings/SchedulesDirectDtos/DescriptionsProgramDto.cs
index 3af36ae96..eaf4a340b 100644
--- a/Emby.Server.Implementations/LiveTv/Listings/SchedulesDirectDtos/DescriptionsProgramDto.cs
+++ b/Emby.Server.Implementations/LiveTv/Listings/SchedulesDirectDtos/DescriptionsProgramDto.cs
@@ -1,5 +1,4 @@
-#nullable disable
-
+using System;
using System.Collections.Generic;
using System.Text.Json.Serialization;
@@ -14,12 +13,12 @@ namespace Emby.Server.Implementations.LiveTv.Listings.SchedulesDirectDtos
/// Gets or sets the list of description 100.
/// </summary>
[JsonPropertyName("description100")]
- public List<Description100Dto> Description100 { get; set; }
+ public IReadOnlyList<Description100Dto> Description100 { get; set; } = Array.Empty<Description100Dto>();
/// <summary>
/// Gets or sets the list of description1000.
/// </summary>
[JsonPropertyName("description1000")]
- public List<Description1000Dto> Description1000 { get; set; }
+ public IReadOnlyList<Description1000Dto> Description1000 { get; set; } = Array.Empty<Description1000Dto>();
}
}
diff --git a/Emby.Server.Implementations/LiveTv/Listings/SchedulesDirectDtos/EventDetailsDto.cs b/Emby.Server.Implementations/LiveTv/Listings/SchedulesDirectDtos/EventDetailsDto.cs
index c3b2bd9c1..fbdfb1f71 100644
--- a/Emby.Server.Implementations/LiveTv/Listings/SchedulesDirectDtos/EventDetailsDto.cs
+++ b/Emby.Server.Implementations/LiveTv/Listings/SchedulesDirectDtos/EventDetailsDto.cs
@@ -1,5 +1,3 @@
-#nullable disable
-
using System.Text.Json.Serialization;
namespace Emby.Server.Implementations.LiveTv.Listings.SchedulesDirectDtos
@@ -13,6 +11,6 @@ namespace Emby.Server.Implementations.LiveTv.Listings.SchedulesDirectDtos
/// Gets or sets the sub type.
/// </summary>
[JsonPropertyName("subType")]
- public string SubType { get; set; }
+ public string? SubType { get; set; }
}
}
diff --git a/Emby.Server.Implementations/LiveTv/Listings/SchedulesDirectDtos/GracenoteDto.cs b/Emby.Server.Implementations/LiveTv/Listings/SchedulesDirectDtos/GracenoteDto.cs
index 3d8bea362..6852d89d7 100644
--- a/Emby.Server.Implementations/LiveTv/Listings/SchedulesDirectDtos/GracenoteDto.cs
+++ b/Emby.Server.Implementations/LiveTv/Listings/SchedulesDirectDtos/GracenoteDto.cs
@@ -1,5 +1,3 @@
-#nullable disable
-
using System.Text.Json.Serialization;
namespace Emby.Server.Implementations.LiveTv.Listings.SchedulesDirectDtos
diff --git a/Emby.Server.Implementations/LiveTv/Listings/SchedulesDirectDtos/HeadendsDto.cs b/Emby.Server.Implementations/LiveTv/Listings/SchedulesDirectDtos/HeadendsDto.cs
index 1fb3decb2..b9844562f 100644
--- a/Emby.Server.Implementations/LiveTv/Listings/SchedulesDirectDtos/HeadendsDto.cs
+++ b/Emby.Server.Implementations/LiveTv/Listings/SchedulesDirectDtos/HeadendsDto.cs
@@ -1,5 +1,4 @@
-#nullable disable
-
+using System;
using System.Collections.Generic;
using System.Text.Json.Serialization;
@@ -14,24 +13,24 @@ namespace Emby.Server.Implementations.LiveTv.Listings.SchedulesDirectDtos
/// Gets or sets the headend.
/// </summary>
[JsonPropertyName("headend")]
- public string Headend { get; set; }
+ public string? Headend { get; set; }
/// <summary>
/// Gets or sets the transport.
/// </summary>
[JsonPropertyName("transport")]
- public string Transport { get; set; }
+ public string? Transport { get; set; }
/// <summary>
/// Gets or sets the location.
/// </summary>
[JsonPropertyName("location")]
- public string Location { get; set; }
+ public string? Location { get; set; }
/// <summary>
/// Gets or sets the list of lineups.
/// </summary>
[JsonPropertyName("lineups")]
- public List<LineupDto> Lineups { get; set; }
+ public IReadOnlyList<LineupDto> Lineups { get; set; } = Array.Empty<LineupDto>();
}
}
diff --git a/Emby.Server.Implementations/LiveTv/Listings/SchedulesDirectDtos/ImageDataDto.cs b/Emby.Server.Implementations/LiveTv/Listings/SchedulesDirectDtos/ImageDataDto.cs
index 912e680dd..a1ae3ca6d 100644
--- a/Emby.Server.Implementations/LiveTv/Listings/SchedulesDirectDtos/ImageDataDto.cs
+++ b/Emby.Server.Implementations/LiveTv/Listings/SchedulesDirectDtos/ImageDataDto.cs
@@ -1,5 +1,3 @@
-#nullable disable
-
using System.Text.Json.Serialization;
namespace Emby.Server.Implementations.LiveTv.Listings.SchedulesDirectDtos
@@ -13,60 +11,60 @@ namespace Emby.Server.Implementations.LiveTv.Listings.SchedulesDirectDtos
/// Gets or sets the width.
/// </summary>
[JsonPropertyName("width")]
- public string Width { get; set; }
+ public string? Width { get; set; }
/// <summary>
/// Gets or sets the height.
/// </summary>
[JsonPropertyName("height")]
- public string Height { get; set; }
+ public string? Height { get; set; }
/// <summary>
/// Gets or sets the uri.
/// </summary>
[JsonPropertyName("uri")]
- public string Uri { get; set; }
+ public string? Uri { get; set; }
/// <summary>
/// Gets or sets the size.
/// </summary>
[JsonPropertyName("size")]
- public string Size { get; set; }
+ public string? Size { get; set; }
/// <summary>
/// Gets or sets the aspect.
/// </summary>
[JsonPropertyName("aspect")]
- public string aspect { get; set; }
+ public string? Aspect { get; set; }
/// <summary>
/// Gets or sets the category.
/// </summary>
[JsonPropertyName("category")]
- public string Category { get; set; }
+ public string? Category { get; set; }
/// <summary>
/// Gets or sets the text.
/// </summary>
[JsonPropertyName("text")]
- public string Text { get; set; }
+ public string? Text { get; set; }
/// <summary>
/// Gets or sets the primary.
/// </summary>
[JsonPropertyName("primary")]
- public string Primary { get; set; }
+ public string? Primary { get; set; }
/// <summary>
/// Gets or sets the tier.
/// </summary>
[JsonPropertyName("tier")]
- public string Tier { get; set; }
+ public string? Tier { get; set; }
/// <summary>
/// Gets or sets the caption.
/// </summary>
[JsonPropertyName("caption")]
- public CaptionDto Caption { get; set; }
+ public CaptionDto? Caption { get; set; }
}
}
diff --git a/Emby.Server.Implementations/LiveTv/Listings/SchedulesDirectDtos/LineupDto.cs b/Emby.Server.Implementations/LiveTv/Listings/SchedulesDirectDtos/LineupDto.cs
index 52e920aa6..3dc64e5d8 100644
--- a/Emby.Server.Implementations/LiveTv/Listings/SchedulesDirectDtos/LineupDto.cs
+++ b/Emby.Server.Implementations/LiveTv/Listings/SchedulesDirectDtos/LineupDto.cs
@@ -1,5 +1,3 @@
-#nullable disable
-
using System.Text.Json.Serialization;
namespace Emby.Server.Implementations.LiveTv.Listings.SchedulesDirectDtos
@@ -13,30 +11,36 @@ namespace Emby.Server.Implementations.LiveTv.Listings.SchedulesDirectDtos
/// Gets or sets the linup.
/// </summary>
[JsonPropertyName("lineup")]
- public string Lineup { get; set; }
+ public string? Lineup { get; set; }
/// <summary>
/// Gets or sets the lineup name.
/// </summary>
[JsonPropertyName("name")]
- public string Name { get; set; }
+ public string? Name { get; set; }
/// <summary>
/// Gets or sets the transport.
/// </summary>
[JsonPropertyName("transport")]
- public string Transport { get; set; }
+ public string? Transport { get; set; }
/// <summary>
/// Gets or sets the location.
/// </summary>
[JsonPropertyName("location")]
- public string Location { get; set; }
+ public string? Location { get; set; }
/// <summary>
/// Gets or sets the uri.
/// </summary>
[JsonPropertyName("uri")]
- public string Uri { get; set; }
+ public string? Uri { get; set; }
+
+ /// <summary>
+ /// Gets or sets a value indicating whether this lineup was deleted.
+ /// </summary>
+ [JsonPropertyName("isDeleted")]
+ public bool? IsDeleted { get; set; }
}
}
diff --git a/Emby.Server.Implementations/LiveTv/Listings/SchedulesDirectDtos/LineupsDto.cs b/Emby.Server.Implementations/LiveTv/Listings/SchedulesDirectDtos/LineupsDto.cs
index 15139ba3b..f19081781 100644
--- a/Emby.Server.Implementations/LiveTv/Listings/SchedulesDirectDtos/LineupsDto.cs
+++ b/Emby.Server.Implementations/LiveTv/Listings/SchedulesDirectDtos/LineupsDto.cs
@@ -1,5 +1,4 @@
-#nullable disable
-
+using System;
using System.Collections.Generic;
using System.Text.Json.Serialization;
@@ -20,18 +19,18 @@ namespace Emby.Server.Implementations.LiveTv.Listings.SchedulesDirectDtos
/// Gets or sets the server id.
/// </summary>
[JsonPropertyName("serverID")]
- public string ServerId { get; set; }
+ public string? ServerId { get; set; }
/// <summary>
/// Gets or sets the datetime.
/// </summary>
[JsonPropertyName("datetime")]
- public string Datetime { get; set; }
+ public DateTime? LineupTimestamp { get; set; }
/// <summary>
/// Gets or sets the list of lineups.
/// </summary>
[JsonPropertyName("lineups")]
- public List<LineupDto> Lineups { get; set; }
+ public IReadOnlyList<LineupDto> Lineups { get; set; } = Array.Empty<LineupDto>();
}
}
diff --git a/Emby.Server.Implementations/LiveTv/Listings/SchedulesDirectDtos/LogoDto.cs b/Emby.Server.Implementations/LiveTv/Listings/SchedulesDirectDtos/LogoDto.cs
index 7b235ed7f..fecc55e03 100644
--- a/Emby.Server.Implementations/LiveTv/Listings/SchedulesDirectDtos/LogoDto.cs
+++ b/Emby.Server.Implementations/LiveTv/Listings/SchedulesDirectDtos/LogoDto.cs
@@ -1,5 +1,3 @@
-#nullable disable
-
using System.Text.Json.Serialization;
namespace Emby.Server.Implementations.LiveTv.Listings.SchedulesDirectDtos
@@ -13,7 +11,7 @@ namespace Emby.Server.Implementations.LiveTv.Listings.SchedulesDirectDtos
/// Gets or sets the url.
/// </summary>
[JsonPropertyName("URL")]
- public string Url { get; set; }
+ public string? Url { get; set; }
/// <summary>
/// Gets or sets the height.
@@ -31,6 +29,6 @@ namespace Emby.Server.Implementations.LiveTv.Listings.SchedulesDirectDtos
/// Gets or sets the md5.
/// </summary>
[JsonPropertyName("md5")]
- public string Md5 { get; set; }
+ public string? Md5 { get; set; }
}
}
diff --git a/Emby.Server.Implementations/LiveTv/Listings/SchedulesDirectDtos/MapDto.cs b/Emby.Server.Implementations/LiveTv/Listings/SchedulesDirectDtos/MapDto.cs
index 5140277b2..ffd02d474 100644
--- a/Emby.Server.Implementations/LiveTv/Listings/SchedulesDirectDtos/MapDto.cs
+++ b/Emby.Server.Implementations/LiveTv/Listings/SchedulesDirectDtos/MapDto.cs
@@ -1,5 +1,3 @@
-#nullable disable
-
using System.Text.Json.Serialization;
namespace Emby.Server.Implementations.LiveTv.Listings.SchedulesDirectDtos
@@ -13,19 +11,25 @@ namespace Emby.Server.Implementations.LiveTv.Listings.SchedulesDirectDtos
/// Gets or sets the station id.
/// </summary>
[JsonPropertyName("stationID")]
- public string StationId { get; set; }
+ public string? StationId { get; set; }
/// <summary>
/// Gets or sets the channel.
/// </summary>
[JsonPropertyName("channel")]
- public string Channel { get; set; }
+ public string? Channel { get; set; }
+
+ /// <summary>
+ /// Gets or sets the provider callsign.
+ /// </summary>
+ [JsonPropertyName("providerCallsign")]
+ public string? ProvderCallsign { get; set; }
/// <summary>
/// Gets or sets the logical channel number.
/// </summary>
[JsonPropertyName("logicalChannelNumber")]
- public string LogicalChannelNumber { get; set; }
+ public string? LogicalChannelNumber { get; set; }
/// <summary>
/// Gets or sets the uhfvhf.
@@ -44,5 +48,11 @@ namespace Emby.Server.Implementations.LiveTv.Listings.SchedulesDirectDtos
/// </summary>
[JsonPropertyName("atscMinor")]
public int AtscMinor { get; set; }
+
+ /// <summary>
+ /// Gets or sets the match type.
+ /// </summary>
+ [JsonPropertyName("matchType")]
+ public string? MatchType { get; set; }
}
}
diff --git a/Emby.Server.Implementations/LiveTv/Listings/SchedulesDirectDtos/MetadataDto.cs b/Emby.Server.Implementations/LiveTv/Listings/SchedulesDirectDtos/MetadataDto.cs
index 5a3893a35..40faa493c 100644
--- a/Emby.Server.Implementations/LiveTv/Listings/SchedulesDirectDtos/MetadataDto.cs
+++ b/Emby.Server.Implementations/LiveTv/Listings/SchedulesDirectDtos/MetadataDto.cs
@@ -1,5 +1,3 @@
-#nullable disable
-
using System.Text.Json.Serialization;
namespace Emby.Server.Implementations.LiveTv.Listings.SchedulesDirectDtos
@@ -13,18 +11,18 @@ namespace Emby.Server.Implementations.LiveTv.Listings.SchedulesDirectDtos
/// Gets or sets the linup.
/// </summary>
[JsonPropertyName("lineup")]
- public string Lineup { get; set; }
+ public string? Lineup { get; set; }
/// <summary>
/// Gets or sets the modified timestamp.
/// </summary>
[JsonPropertyName("modified")]
- public string Modified { get; set; }
+ public string? Modified { get; set; }
/// <summary>
/// Gets or sets the transport.
/// </summary>
[JsonPropertyName("transport")]
- public string Transport { get; set; }
+ public string? Transport { get; set; }
}
}
diff --git a/Emby.Server.Implementations/LiveTv/Listings/SchedulesDirectDtos/MetadataProgramsDto.cs b/Emby.Server.Implementations/LiveTv/Listings/SchedulesDirectDtos/MetadataProgramsDto.cs
index 4057e9802..43f290156 100644
--- a/Emby.Server.Implementations/LiveTv/Listings/SchedulesDirectDtos/MetadataProgramsDto.cs
+++ b/Emby.Server.Implementations/LiveTv/Listings/SchedulesDirectDtos/MetadataProgramsDto.cs
@@ -1,5 +1,3 @@
-#nullable disable
-
using System.Text.Json.Serialization;
namespace Emby.Server.Implementations.LiveTv.Listings.SchedulesDirectDtos
@@ -12,7 +10,7 @@ namespace Emby.Server.Implementations.LiveTv.Listings.SchedulesDirectDtos
/// <summary>
/// Gets or sets the gracenote object.
/// </summary>
- [JsonPropertyName("gracenote")]
- public GracenoteDto Gracenote { get; set; }
+ [JsonPropertyName("Gracenote")]
+ public GracenoteDto? Gracenote { get; set; }
}
}
diff --git a/Emby.Server.Implementations/LiveTv/Listings/SchedulesDirectDtos/MetadataScheduleDto.cs b/Emby.Server.Implementations/LiveTv/Listings/SchedulesDirectDtos/MetadataScheduleDto.cs
index 4979296da..04560ab55 100644
--- a/Emby.Server.Implementations/LiveTv/Listings/SchedulesDirectDtos/MetadataScheduleDto.cs
+++ b/Emby.Server.Implementations/LiveTv/Listings/SchedulesDirectDtos/MetadataScheduleDto.cs
@@ -1,5 +1,4 @@
-#nullable disable
-
+using System;
using System.Text.Json.Serialization;
namespace Emby.Server.Implementations.LiveTv.Listings.SchedulesDirectDtos
@@ -13,25 +12,25 @@ namespace Emby.Server.Implementations.LiveTv.Listings.SchedulesDirectDtos
/// Gets or sets the modified timestamp.
/// </summary>
[JsonPropertyName("modified")]
- public string Modified { get; set; }
+ public string? Modified { get; set; }
/// <summary>
/// Gets or sets the md5.
/// </summary>
[JsonPropertyName("md5")]
- public string Md5 { get; set; }
+ public string? Md5 { get; set; }
/// <summary>
/// Gets or sets the start date.
/// </summary>
[JsonPropertyName("startDate")]
- public string StartDate { get; set; }
+ public DateTime? StartDate { get; set; }
/// <summary>
/// Gets or sets the end date.
/// </summary>
[JsonPropertyName("endDate")]
- public string EndDate { get; set; }
+ public DateTime? EndDate { get; set; }
/// <summary>
/// Gets or sets the days count.
diff --git a/Emby.Server.Implementations/LiveTv/Listings/SchedulesDirectDtos/MovieDto.cs b/Emby.Server.Implementations/LiveTv/Listings/SchedulesDirectDtos/MovieDto.cs
index 48d731d89..31bef423b 100644
--- a/Emby.Server.Implementations/LiveTv/Listings/SchedulesDirectDtos/MovieDto.cs
+++ b/Emby.Server.Implementations/LiveTv/Listings/SchedulesDirectDtos/MovieDto.cs
@@ -1,5 +1,4 @@
-#nullable disable
-
+using System;
using System.Collections.Generic;
using System.Text.Json.Serialization;
@@ -14,7 +13,7 @@ namespace Emby.Server.Implementations.LiveTv.Listings.SchedulesDirectDtos
/// Gets or sets the year.
/// </summary>
[JsonPropertyName("year")]
- public string Year { get; set; }
+ public string? Year { get; set; }
/// <summary>
/// Gets or sets the duration.
@@ -26,6 +25,6 @@ namespace Emby.Server.Implementations.LiveTv.Listings.SchedulesDirectDtos
/// Gets or sets the list of quality rating.
/// </summary>
[JsonPropertyName("qualityRating")]
- public List<QualityRatingDto> QualityRating { get; set; }
+ public IReadOnlyList<QualityRatingDto> QualityRating { get; set; } = Array.Empty<QualityRatingDto>();
}
}
diff --git a/Emby.Server.Implementations/LiveTv/Listings/SchedulesDirectDtos/MultipartDto.cs b/Emby.Server.Implementations/LiveTv/Listings/SchedulesDirectDtos/MultipartDto.cs
index 42eddfff2..e8b15dc07 100644
--- a/Emby.Server.Implementations/LiveTv/Listings/SchedulesDirectDtos/MultipartDto.cs
+++ b/Emby.Server.Implementations/LiveTv/Listings/SchedulesDirectDtos/MultipartDto.cs
@@ -1,5 +1,3 @@
-#nullable disable
-
using System.Text.Json.Serialization;
namespace Emby.Server.Implementations.LiveTv.Listings.SchedulesDirectDtos
diff --git a/Emby.Server.Implementations/LiveTv/Listings/SchedulesDirectDtos/ProgramDetailsDto.cs b/Emby.Server.Implementations/LiveTv/Listings/SchedulesDirectDtos/ProgramDetailsDto.cs
index a84c47c12..84c48f67f 100644
--- a/Emby.Server.Implementations/LiveTv/Listings/SchedulesDirectDtos/ProgramDetailsDto.cs
+++ b/Emby.Server.Implementations/LiveTv/Listings/SchedulesDirectDtos/ProgramDetailsDto.cs
@@ -1,5 +1,4 @@
-#nullable disable
-
+using System;
using System.Collections.Generic;
using System.Text.Json.Serialization;
@@ -14,85 +13,85 @@ namespace Emby.Server.Implementations.LiveTv.Listings.SchedulesDirectDtos
/// Gets or sets the audience.
/// </summary>
[JsonPropertyName("audience")]
- public string Audience { get; set; }
+ public string? Audience { get; set; }
/// <summary>
/// Gets or sets the program id.
/// </summary>
[JsonPropertyName("programID")]
- public string ProgramId { get; set; }
+ public string? ProgramId { get; set; }
/// <summary>
/// Gets or sets the list of titles.
/// </summary>
[JsonPropertyName("titles")]
- public List<TitleDto> Titles { get; set; }
+ public IReadOnlyList<TitleDto> Titles { get; set; } = Array.Empty<TitleDto>();
/// <summary>
/// Gets or sets the event details object.
/// </summary>
[JsonPropertyName("eventDetails")]
- public EventDetailsDto EventDetails { get; set; }
+ public EventDetailsDto? EventDetails { get; set; }
/// <summary>
/// Gets or sets the descriptions.
/// </summary>
[JsonPropertyName("descriptions")]
- public DescriptionsProgramDto Descriptions { get; set; }
+ public DescriptionsProgramDto? Descriptions { get; set; }
/// <summary>
/// Gets or sets the original air date.
/// </summary>
[JsonPropertyName("originalAirDate")]
- public string OriginalAirDate { get; set; }
+ public DateTime? OriginalAirDate { get; set; }
/// <summary>
/// Gets or sets the list of genres.
/// </summary>
[JsonPropertyName("genres")]
- public List<string> Genres { get; set; }
+ public IReadOnlyList<string> Genres { get; set; } = Array.Empty<string>();
/// <summary>
/// Gets or sets the episode title.
/// </summary>
[JsonPropertyName("episodeTitle150")]
- public string EpisodeTitle150 { get; set; }
+ public string? EpisodeTitle150 { get; set; }
/// <summary>
/// Gets or sets the list of metadata.
/// </summary>
[JsonPropertyName("metadata")]
- public List<MetadataProgramsDto> Metadata { get; set; }
+ public IReadOnlyList<MetadataProgramsDto> Metadata { get; set; } = Array.Empty<MetadataProgramsDto>();
/// <summary>
/// Gets or sets the list of content raitings.
/// </summary>
[JsonPropertyName("contentRating")]
- public List<ContentRatingDto> ContentRating { get; set; }
+ public IReadOnlyList<ContentRatingDto> ContentRating { get; set; } = Array.Empty<ContentRatingDto>();
/// <summary>
/// Gets or sets the list of cast.
/// </summary>
[JsonPropertyName("cast")]
- public List<CastDto> Cast { get; set; }
+ public IReadOnlyList<CastDto> Cast { get; set; } = Array.Empty<CastDto>();
/// <summary>
/// Gets or sets the list of crew.
/// </summary>
[JsonPropertyName("crew")]
- public List<CrewDto> Crew { get; set; }
+ public IReadOnlyList<CrewDto> Crew { get; set; } = Array.Empty<CrewDto>();
/// <summary>
/// Gets or sets the entity type.
/// </summary>
[JsonPropertyName("entityType")]
- public string EntityType { get; set; }
+ public string? EntityType { get; set; }
/// <summary>
/// Gets or sets the show type.
/// </summary>
[JsonPropertyName("showType")]
- public string ShowType { get; set; }
+ public string? ShowType { get; set; }
/// <summary>
/// Gets or sets a value indicating whether there is image artwork.
@@ -104,54 +103,54 @@ namespace Emby.Server.Implementations.LiveTv.Listings.SchedulesDirectDtos
/// Gets or sets the primary image.
/// </summary>
[JsonPropertyName("primaryImage")]
- public string PrimaryImage { get; set; }
+ public string? PrimaryImage { get; set; }
/// <summary>
/// Gets or sets the thumb image.
/// </summary>
[JsonPropertyName("thumbImage")]
- public string ThumbImage { get; set; }
+ public string? ThumbImage { get; set; }
/// <summary>
/// Gets or sets the backdrop image.
/// </summary>
[JsonPropertyName("backdropImage")]
- public string BackdropImage { get; set; }
+ public string? BackdropImage { get; set; }
/// <summary>
/// Gets or sets the banner image.
/// </summary>
[JsonPropertyName("bannerImage")]
- public string BannerImage { get; set; }
+ public string? BannerImage { get; set; }
/// <summary>
/// Gets or sets the image id.
/// </summary>
[JsonPropertyName("imageID")]
- public string ImageId { get; set; }
+ public string? ImageId { get; set; }
/// <summary>
/// Gets or sets the md5.
/// </summary>
[JsonPropertyName("md5")]
- public string Md5 { get; set; }
+ public string? Md5 { get; set; }
/// <summary>
/// Gets or sets the list of content advisory.
/// </summary>
[JsonPropertyName("contentAdvisory")]
- public List<string> ContentAdvisory { get; set; }
+ public IReadOnlyList<string> ContentAdvisory { get; set; } = Array.Empty<string>();
/// <summary>
/// Gets or sets the movie object.
/// </summary>
[JsonPropertyName("movie")]
- public MovieDto Movie { get; set; }
+ public MovieDto? Movie { get; set; }
/// <summary>
/// Gets or sets the list of recommendations.
/// </summary>
[JsonPropertyName("recommendations")]
- public List<RecommendationDto> Recommendations { get; set; }
+ public IReadOnlyList<RecommendationDto> Recommendations { get; set; } = Array.Empty<RecommendationDto>();
}
}
diff --git a/Emby.Server.Implementations/LiveTv/Listings/SchedulesDirectDtos/ProgramDto.cs b/Emby.Server.Implementations/LiveTv/Listings/SchedulesDirectDtos/ProgramDto.cs
index ad5389100..60389b45b 100644
--- a/Emby.Server.Implementations/LiveTv/Listings/SchedulesDirectDtos/ProgramDto.cs
+++ b/Emby.Server.Implementations/LiveTv/Listings/SchedulesDirectDtos/ProgramDto.cs
@@ -1,5 +1,4 @@
-#nullable disable
-
+using System;
using System.Collections.Generic;
using System.Text.Json.Serialization;
@@ -14,13 +13,13 @@ namespace Emby.Server.Implementations.LiveTv.Listings.SchedulesDirectDtos
/// Gets or sets the program id.
/// </summary>
[JsonPropertyName("programID")]
- public string ProgramId { get; set; }
+ public string? ProgramId { get; set; }
/// <summary>
/// Gets or sets the air date time.
/// </summary>
[JsonPropertyName("airDateTime")]
- public string AirDateTime { get; set; }
+ public DateTime? AirDateTime { get; set; }
/// <summary>
/// Gets or sets the duration.
@@ -32,25 +31,25 @@ namespace Emby.Server.Implementations.LiveTv.Listings.SchedulesDirectDtos
/// Gets or sets the md5.
/// </summary>
[JsonPropertyName("md5")]
- public string Md5 { get; set; }
+ public string? Md5 { get; set; }
/// <summary>
/// Gets or sets the list of audio properties.
/// </summary>
[JsonPropertyName("audioProperties")]
- public List<string> AudioProperties { get; set; }
+ public IReadOnlyList<string> AudioProperties { get; set; } = Array.Empty<string>();
/// <summary>
/// Gets or sets the list of video properties.
/// </summary>
[JsonPropertyName("videoProperties")]
- public List<string> VideoProperties { get; set; }
+ public IReadOnlyList<string> VideoProperties { get; set; } = Array.Empty<string>();
/// <summary>
/// Gets or sets the list of ratings.
/// </summary>
[JsonPropertyName("ratings")]
- public List<RatingDto> Ratings { get; set; }
+ public IReadOnlyList<RatingDto> Ratings { get; set; } = Array.Empty<RatingDto>();
/// <summary>
/// Gets or sets a value indicating whether this program is new.
@@ -62,13 +61,13 @@ namespace Emby.Server.Implementations.LiveTv.Listings.SchedulesDirectDtos
/// Gets or sets the multipart object.
/// </summary>
[JsonPropertyName("multipart")]
- public MultipartDto Multipart { get; set; }
+ public MultipartDto? Multipart { get; set; }
/// <summary>
/// Gets or sets the live tape delay.
/// </summary>
[JsonPropertyName("liveTapeDelay")]
- public string LiveTapeDelay { get; set; }
+ public string? LiveTapeDelay { get; set; }
/// <summary>
/// Gets or sets a value indicating whether this is the premiere.
@@ -86,6 +85,6 @@ namespace Emby.Server.Implementations.LiveTv.Listings.SchedulesDirectDtos
/// Gets or sets the premiere or finale.
/// </summary>
[JsonPropertyName("isPremiereOrFinale")]
- public string IsPremiereOrFinale { get; set; }
+ public string? IsPremiereOrFinale { get; set; }
}
}
diff --git a/Emby.Server.Implementations/LiveTv/Listings/SchedulesDirectDtos/QualityRatingDto.cs b/Emby.Server.Implementations/LiveTv/Listings/SchedulesDirectDtos/QualityRatingDto.cs
index 5cd0a7459..c5ddcf7c5 100644
--- a/Emby.Server.Implementations/LiveTv/Listings/SchedulesDirectDtos/QualityRatingDto.cs
+++ b/Emby.Server.Implementations/LiveTv/Listings/SchedulesDirectDtos/QualityRatingDto.cs
@@ -1,5 +1,3 @@
-#nullable disable
-
using System.Text.Json.Serialization;
namespace Emby.Server.Implementations.LiveTv.Listings.SchedulesDirectDtos
@@ -13,30 +11,30 @@ namespace Emby.Server.Implementations.LiveTv.Listings.SchedulesDirectDtos
/// Gets or sets the ratings body.
/// </summary>
[JsonPropertyName("ratingsBody")]
- public string RatingsBody { get; set; }
+ public string? RatingsBody { get; set; }
/// <summary>
/// Gets or sets the rating.
/// </summary>
[JsonPropertyName("rating")]
- public string Rating { get; set; }
+ public string? Rating { get; set; }
/// <summary>
/// Gets or sets the min rating.
/// </summary>
[JsonPropertyName("minRating")]
- public string MinRating { get; set; }
+ public string? MinRating { get; set; }
/// <summary>
/// Gets or sets the max rating.
/// </summary>
[JsonPropertyName("maxRating")]
- public string MaxRating { get; set; }
+ public string? MaxRating { get; set; }
/// <summary>
/// Gets or sets the increment.
/// </summary>
[JsonPropertyName("increment")]
- public string Increment { get; set; }
+ public string? Increment { get; set; }
}
}
diff --git a/Emby.Server.Implementations/LiveTv/Listings/SchedulesDirectDtos/RatingDto.cs b/Emby.Server.Implementations/LiveTv/Listings/SchedulesDirectDtos/RatingDto.cs
index 948b83144..e04b619a4 100644
--- a/Emby.Server.Implementations/LiveTv/Listings/SchedulesDirectDtos/RatingDto.cs
+++ b/Emby.Server.Implementations/LiveTv/Listings/SchedulesDirectDtos/RatingDto.cs
@@ -1,5 +1,3 @@
-#nullable disable
-
using System.Text.Json.Serialization;
namespace Emby.Server.Implementations.LiveTv.Listings.SchedulesDirectDtos
@@ -13,12 +11,12 @@ namespace Emby.Server.Implementations.LiveTv.Listings.SchedulesDirectDtos
/// Gets or sets the body.
/// </summary>
[JsonPropertyName("body")]
- public string Body { get; set; }
+ public string? Body { get; set; }
/// <summary>
/// Gets or sets the code.
/// </summary>
[JsonPropertyName("code")]
- public string Code { get; set; }
+ public string? Code { get; set; }
}
}
diff --git a/Emby.Server.Implementations/LiveTv/Listings/SchedulesDirectDtos/RecommendationDto.cs b/Emby.Server.Implementations/LiveTv/Listings/SchedulesDirectDtos/RecommendationDto.cs
index 1308f45ce..c8f79fd1c 100644
--- a/Emby.Server.Implementations/LiveTv/Listings/SchedulesDirectDtos/RecommendationDto.cs
+++ b/Emby.Server.Implementations/LiveTv/Listings/SchedulesDirectDtos/RecommendationDto.cs
@@ -1,5 +1,3 @@
-#nullable disable
-
using System.Text.Json.Serialization;
namespace Emby.Server.Implementations.LiveTv.Listings.SchedulesDirectDtos
@@ -13,12 +11,12 @@ namespace Emby.Server.Implementations.LiveTv.Listings.SchedulesDirectDtos
/// Gets or sets the program id.
/// </summary>
[JsonPropertyName("programID")]
- public string ProgramId { get; set; }
+ public string? ProgramId { get; set; }
/// <summary>
/// Gets or sets the title.
/// </summary>
[JsonPropertyName("title120")]
- public string Title120 { get; set; }
+ public string? Title120 { get; set; }
}
}
diff --git a/Emby.Server.Implementations/LiveTv/Listings/SchedulesDirectDtos/RequestScheduleForChannelDto.cs b/Emby.Server.Implementations/LiveTv/Listings/SchedulesDirectDtos/RequestScheduleForChannelDto.cs
index fb7a31ac8..0cd05709b 100644
--- a/Emby.Server.Implementations/LiveTv/Listings/SchedulesDirectDtos/RequestScheduleForChannelDto.cs
+++ b/Emby.Server.Implementations/LiveTv/Listings/SchedulesDirectDtos/RequestScheduleForChannelDto.cs
@@ -1,5 +1,4 @@
-#nullable disable
-
+using System;
using System.Collections.Generic;
using System.Text.Json.Serialization;
@@ -14,12 +13,12 @@ namespace Emby.Server.Implementations.LiveTv.Listings.SchedulesDirectDtos
/// Gets or sets the station id.
/// </summary>
[JsonPropertyName("stationID")]
- public string StationId { get; set; }
+ public string? StationId { get; set; }
/// <summary>
/// Gets or sets the list of dates.
/// </summary>
[JsonPropertyName("date")]
- public List<string> Date { get; set; }
+ public IReadOnlyList<string> Date { get; set; } = Array.Empty<string>();
}
}
diff --git a/Emby.Server.Implementations/LiveTv/Listings/SchedulesDirectDtos/ShowImagesDto.cs b/Emby.Server.Implementations/LiveTv/Listings/SchedulesDirectDtos/ShowImagesDto.cs
index 34302370d..84e224b71 100644
--- a/Emby.Server.Implementations/LiveTv/Listings/SchedulesDirectDtos/ShowImagesDto.cs
+++ b/Emby.Server.Implementations/LiveTv/Listings/SchedulesDirectDtos/ShowImagesDto.cs
@@ -1,5 +1,4 @@
-#nullable disable
-
+using System;
using System.Collections.Generic;
using System.Text.Json.Serialization;
@@ -14,12 +13,12 @@ namespace Emby.Server.Implementations.LiveTv.Listings.SchedulesDirectDtos
/// Gets or sets the program id.
/// </summary>
[JsonPropertyName("programID")]
- public string ProgramId { get; set; }
+ public string? ProgramId { get; set; }
/// <summary>
/// Gets or sets the list of data.
/// </summary>
[JsonPropertyName("data")]
- public List<ImageDataDto> Data { get; set; }
+ public IReadOnlyList<ImageDataDto> Data { get; set; } = Array.Empty<ImageDataDto>();
}
}
diff --git a/Emby.Server.Implementations/LiveTv/Listings/SchedulesDirectDtos/StationDto.cs b/Emby.Server.Implementations/LiveTv/Listings/SchedulesDirectDtos/StationDto.cs
index 12f3576c6..d797fd49b 100644
--- a/Emby.Server.Implementations/LiveTv/Listings/SchedulesDirectDtos/StationDto.cs
+++ b/Emby.Server.Implementations/LiveTv/Listings/SchedulesDirectDtos/StationDto.cs
@@ -1,67 +1,66 @@
-#nullable disable
-
+using System;
using System.Collections.Generic;
using System.Text.Json.Serialization;
namespace Emby.Server.Implementations.LiveTv.Listings.SchedulesDirectDtos
{
/// <summary>
- /// Station dto.
- /// </summary>
- public class StationDto
- {
- /// <summary>
- /// Gets or sets the station id.
- /// </summary>
- [JsonPropertyName("stationID")]
- public string StationId { get; set; }
+ /// Station dto.
+ /// </summary>
+ public class StationDto
+ {
+ /// <summary>
+ /// Gets or sets the station id.
+ /// </summary>
+ [JsonPropertyName("stationID")]
+ public string? StationId { get; set; }
- /// <summary>
- /// Gets or sets the name.
- /// </summary>
- [JsonPropertyName("name")]
- public string Name { get; set; }
+ /// <summary>
+ /// Gets or sets the name.
+ /// </summary>
+ [JsonPropertyName("name")]
+ public string? Name { get; set; }
- /// <summary>
- /// Gets or sets the callsign.
- /// </summary>
- [JsonPropertyName("callsign")]
- public string Callsign { get; set; }
+ /// <summary>
+ /// Gets or sets the callsign.
+ /// </summary>
+ [JsonPropertyName("callsign")]
+ public string? Callsign { get; set; }
- /// <summary>
- /// Gets or sets the broadcast language.
- /// </summary>
- [JsonPropertyName("broadcastLanguage")]
- public List<string> BroadcastLanguage { get; set; }
+ /// <summary>
+ /// Gets or sets the broadcast language.
+ /// </summary>
+ [JsonPropertyName("broadcastLanguage")]
+ public IReadOnlyList<string> BroadcastLanguage { get; set; } = Array.Empty<string>();
- /// <summary>
- /// Gets or sets the description language.
- /// </summary>
- [JsonPropertyName("descriptionLanguage")]
- public List<string> DescriptionLanguage { get; set; }
+ /// <summary>
+ /// Gets or sets the description language.
+ /// </summary>
+ [JsonPropertyName("descriptionLanguage")]
+ public IReadOnlyList<string> DescriptionLanguage { get; set; } = Array.Empty<string>();
- /// <summary>
- /// Gets or sets the broadcaster.
- /// </summary>
- [JsonPropertyName("broadcaster")]
- public BroadcasterDto Broadcaster { get; set; }
+ /// <summary>
+ /// Gets or sets the broadcaster.
+ /// </summary>
+ [JsonPropertyName("broadcaster")]
+ public BroadcasterDto? Broadcaster { get; set; }
- /// <summary>
- /// Gets or sets the affiliate.
- /// </summary>
- [JsonPropertyName("affiliate")]
- public string Affiliate { get; set; }
+ /// <summary>
+ /// Gets or sets the affiliate.
+ /// </summary>
+ [JsonPropertyName("affiliate")]
+ public string? Affiliate { get; set; }
- /// <summary>
- /// Gets or sets the logo.
- /// </summary>
- [JsonPropertyName("logo")]
- public LogoDto Logo { get; set; }
+ /// <summary>
+ /// Gets or sets the logo.
+ /// </summary>
+ [JsonPropertyName("logo")]
+ public LogoDto? Logo { get; set; }
- /// <summary>
- /// Gets or set a value indicating whether it is commercial free.
- /// </summary>
- [JsonPropertyName("isCommercialFree")]
- public bool? IsCommercialFree { get; set; }
- }
+ /// <summary>
+ /// Gets or sets a value indicating whether it is commercial free.
+ /// </summary>
+ [JsonPropertyName("isCommercialFree")]
+ public bool? IsCommercialFree { get; set; }
+ }
}
diff --git a/Emby.Server.Implementations/LiveTv/Listings/SchedulesDirectDtos/TitleDto.cs b/Emby.Server.Implementations/LiveTv/Listings/SchedulesDirectDtos/TitleDto.cs
index 06c95524b..61cd4a9b0 100644
--- a/Emby.Server.Implementations/LiveTv/Listings/SchedulesDirectDtos/TitleDto.cs
+++ b/Emby.Server.Implementations/LiveTv/Listings/SchedulesDirectDtos/TitleDto.cs
@@ -1,5 +1,3 @@
-#nullable disable
-
using System.Text.Json.Serialization;
namespace Emby.Server.Implementations.LiveTv.Listings.SchedulesDirectDtos
@@ -13,6 +11,6 @@ namespace Emby.Server.Implementations.LiveTv.Listings.SchedulesDirectDtos
/// Gets or sets the title.
/// </summary>
[JsonPropertyName("title120")]
- public string Title120 { get; set; }
+ public string? Title120 { get; set; }
}
}
diff --git a/Emby.Server.Implementations/LiveTv/Listings/SchedulesDirectDtos/TokenDto.cs b/Emby.Server.Implementations/LiveTv/Listings/SchedulesDirectDtos/TokenDto.cs
index c3ec1c7d6..afb999486 100644
--- a/Emby.Server.Implementations/LiveTv/Listings/SchedulesDirectDtos/TokenDto.cs
+++ b/Emby.Server.Implementations/LiveTv/Listings/SchedulesDirectDtos/TokenDto.cs
@@ -1,5 +1,4 @@
-#nullable disable
-
+using System;
using System.Text.Json.Serialization;
namespace Emby.Server.Implementations.LiveTv.Listings.SchedulesDirectDtos
@@ -19,18 +18,30 @@ namespace Emby.Server.Implementations.LiveTv.Listings.SchedulesDirectDtos
/// Gets or sets the response message.
/// </summary>
[JsonPropertyName("message")]
- public string Message { get; set; }
+ public string? Message { get; set; }
/// <summary>
/// Gets or sets the server id.
/// </summary>
[JsonPropertyName("serverID")]
- public string ServerId { get; set; }
+ public string? ServerId { get; set; }
/// <summary>
/// Gets or sets the token.
/// </summary>
[JsonPropertyName("token")]
- public string Token { get; set; }
+ public string? Token { get; set; }
+
+ /// <summary>
+ /// Gets or sets the current datetime.
+ /// </summary>
+ [JsonPropertyName("datetime")]
+ public DateTime? TokenTimestamp { get; set; }
+
+ /// <summary>
+ /// Gets or sets the response message.
+ /// </summary>
+ [JsonPropertyName("response")]
+ public string? Response { get; set; }
}
}
diff --git a/Emby.Server.Implementations/LiveTv/Listings/XmlTvListingsProvider.cs b/Emby.Server.Implementations/LiveTv/Listings/XmlTvListingsProvider.cs
index 2e51ac807..3da9d02b8 100644
--- a/Emby.Server.Implementations/LiveTv/Listings/XmlTvListingsProvider.cs
+++ b/Emby.Server.Implementations/LiveTv/Listings/XmlTvListingsProvider.cs
@@ -60,34 +60,34 @@ namespace Emby.Server.Implementations.LiveTv.Listings
return _config.Configuration.PreferredMetadataLanguage;
}
- private async Task<string> GetXml(string path, CancellationToken cancellationToken)
+ private async Task<string> GetXml(ListingsProviderInfo info, CancellationToken cancellationToken)
{
- _logger.LogInformation("xmltv path: {Path}", path);
+ _logger.LogInformation("xmltv path: {Path}", info.Path);
- if (!path.StartsWith("http", StringComparison.OrdinalIgnoreCase))
+ if (!info.Path.StartsWith("http", StringComparison.OrdinalIgnoreCase))
{
- return UnzipIfNeeded(path, path);
+ return UnzipIfNeeded(info.Path, info.Path);
}
- string cacheFilename = DateTime.UtcNow.DayOfYear.ToString(CultureInfo.InvariantCulture) + "-" + DateTime.UtcNow.Hour.ToString(CultureInfo.InvariantCulture) + ".xml";
+ string cacheFilename = DateTime.UtcNow.DayOfYear.ToString(CultureInfo.InvariantCulture) + "-" + DateTime.UtcNow.Hour.ToString(CultureInfo.InvariantCulture) + "-" + info.Id + ".xml";
string cacheFile = Path.Combine(_config.ApplicationPaths.CachePath, "xmltv", cacheFilename);
if (File.Exists(cacheFile))
{
- return UnzipIfNeeded(path, cacheFile);
+ return UnzipIfNeeded(info.Path, cacheFile);
}
- _logger.LogInformation("Downloading xmltv listings from {Path}", path);
+ _logger.LogInformation("Downloading xmltv listings from {Path}", info.Path);
Directory.CreateDirectory(Path.GetDirectoryName(cacheFile));
- using var response = await _httpClientFactory.CreateClient(NamedClient.Default).GetAsync(path, cancellationToken).ConfigureAwait(false);
+ using var response = await _httpClientFactory.CreateClient(NamedClient.Default).GetAsync(info.Path, cancellationToken).ConfigureAwait(false);
await using var stream = await response.Content.ReadAsStreamAsync(cancellationToken).ConfigureAwait(false);
await using (var fileStream = new FileStream(cacheFile, FileMode.CreateNew, FileAccess.Write, FileShare.None, IODefaults.CopyToBufferSize, FileOptions.Asynchronous))
{
await stream.CopyToAsync(fileStream, cancellationToken).ConfigureAwait(false);
}
- return UnzipIfNeeded(path, cacheFile);
+ return UnzipIfNeeded(info.Path, cacheFile);
}
private string UnzipIfNeeded(ReadOnlySpan<char> originalUrl, string file)
@@ -163,7 +163,7 @@ namespace Emby.Server.Implementations.LiveTv.Listings
_logger.LogDebug("Getting xmltv programs for channel {Id}", channelId);
- string path = await GetXml(info.Path, cancellationToken).ConfigureAwait(false);
+ string path = await GetXml(info, cancellationToken).ConfigureAwait(false);
_logger.LogDebug("Opening XmlTvReader for {Path}", path);
var reader = new XmlTvReader(path, GetLanguage(info));
@@ -190,10 +190,10 @@ namespace Emby.Server.Implementations.LiveTv.Listings
IsSeries = program.Episode != null,
IsRepeat = program.IsPreviouslyShown && !program.IsNew,
IsPremiere = program.Premiere != null,
- IsKids = program.Categories.Any(c => info.KidsCategories.Contains(c, StringComparer.OrdinalIgnoreCase)),
- IsMovie = program.Categories.Any(c => info.MovieCategories.Contains(c, StringComparer.OrdinalIgnoreCase)),
- IsNews = program.Categories.Any(c => info.NewsCategories.Contains(c, StringComparer.OrdinalIgnoreCase)),
- IsSports = program.Categories.Any(c => info.SportsCategories.Contains(c, StringComparer.OrdinalIgnoreCase)),
+ IsKids = program.Categories.Any(c => info.KidsCategories.Contains(c, StringComparison.OrdinalIgnoreCase)),
+ IsMovie = program.Categories.Any(c => info.MovieCategories.Contains(c, StringComparison.OrdinalIgnoreCase)),
+ IsNews = program.Categories.Any(c => info.NewsCategories.Contains(c, StringComparison.OrdinalIgnoreCase)),
+ IsSports = program.Categories.Any(c => info.SportsCategories.Contains(c, StringComparison.OrdinalIgnoreCase)),
ImageUrl = program.Icon != null && !string.IsNullOrEmpty(program.Icon.Source) ? program.Icon.Source : null,
HasImage = program.Icon != null && !string.IsNullOrEmpty(program.Icon.Source),
OfficialRating = program.Rating != null && !string.IsNullOrEmpty(program.Rating.Value) ? program.Rating.Value : null,
@@ -257,7 +257,7 @@ namespace Emby.Server.Implementations.LiveTv.Listings
public async Task<List<NameIdPair>> GetLineups(ListingsProviderInfo info, string country, string location)
{
// In theory this should never be called because there is always only one lineup
- string path = await GetXml(info.Path, CancellationToken.None).ConfigureAwait(false);
+ string path = await GetXml(info, CancellationToken.None).ConfigureAwait(false);
_logger.LogDebug("Opening XmlTvReader for {Path}", path);
var reader = new XmlTvReader(path, GetLanguage(info));
IEnumerable<XmlTvChannel> results = reader.GetChannels();
@@ -269,7 +269,7 @@ namespace Emby.Server.Implementations.LiveTv.Listings
public async Task<List<ChannelInfo>> GetChannels(ListingsProviderInfo info, CancellationToken cancellationToken)
{
// In theory this should never be called because there is always only one lineup
- string path = await GetXml(info.Path, cancellationToken).ConfigureAwait(false);
+ string path = await GetXml(info, cancellationToken).ConfigureAwait(false);
_logger.LogDebug("Opening XmlTvReader for {Path}", path);
var reader = new XmlTvReader(path, GetLanguage(info));
var results = reader.GetChannels();
diff --git a/Emby.Server.Implementations/LiveTv/LiveTvDtoService.cs b/Emby.Server.Implementations/LiveTv/LiveTvDtoService.cs
index 21e1409ac..323b96021 100644
--- a/Emby.Server.Implementations/LiveTv/LiveTvDtoService.cs
+++ b/Emby.Server.Implementations/LiveTv/LiveTvDtoService.cs
@@ -7,12 +7,12 @@ using System.Globalization;
using System.Linq;
using System.Threading;
using System.Threading.Tasks;
+using Jellyfin.Data.Enums;
using MediaBrowser.Common;
using MediaBrowser.Common.Extensions;
using MediaBrowser.Controller.Drawing;
using MediaBrowser.Controller.Dto;
using MediaBrowser.Controller.Entities;
-using MediaBrowser.Controller.Entities.TV;
using MediaBrowser.Controller.Library;
using MediaBrowser.Controller.LiveTv;
using MediaBrowser.Model.Dto;
@@ -161,7 +161,7 @@ namespace Emby.Server.Implementations.LiveTv
{
var librarySeries = _libraryManager.GetItemList(new InternalItemsQuery
{
- IncludeItemTypes = new string[] { nameof(Series) },
+ IncludeItemTypes = new[] { BaseItemKind.Series },
Name = seriesName,
Limit = 1,
ImageTypes = new ImageType[] { ImageType.Thumb },
@@ -204,7 +204,7 @@ namespace Emby.Server.Implementations.LiveTv
var program = _libraryManager.GetItemList(new InternalItemsQuery
{
- IncludeItemTypes = new string[] { nameof(LiveTvProgram) },
+ IncludeItemTypes = new[] { BaseItemKind.LiveTvProgram },
ExternalSeriesId = programSeriesId,
Limit = 1,
ImageTypes = new ImageType[] { ImageType.Primary },
@@ -255,7 +255,7 @@ namespace Emby.Server.Implementations.LiveTv
{
var librarySeries = _libraryManager.GetItemList(new InternalItemsQuery
{
- IncludeItemTypes = new string[] { nameof(Series) },
+ IncludeItemTypes = new[] { BaseItemKind.Series },
Name = seriesName,
Limit = 1,
ImageTypes = new ImageType[] { ImageType.Thumb },
@@ -298,7 +298,7 @@ namespace Emby.Server.Implementations.LiveTv
var program = _libraryManager.GetItemList(new InternalItemsQuery
{
- IncludeItemTypes = new string[] { nameof(Series) },
+ IncludeItemTypes = new[] { BaseItemKind.Series },
Name = seriesName,
Limit = 1,
ImageTypes = new ImageType[] { ImageType.Primary },
@@ -309,7 +309,7 @@ namespace Emby.Server.Implementations.LiveTv
{
program = _libraryManager.GetItemList(new InternalItemsQuery
{
- IncludeItemTypes = new string[] { nameof(LiveTvProgram) },
+ IncludeItemTypes = new[] { BaseItemKind.LiveTvProgram },
ExternalSeriesId = programSeriesId,
Limit = 1,
ImageTypes = new ImageType[] { ImageType.Primary },
@@ -393,7 +393,7 @@ namespace Emby.Server.Implementations.LiveTv
}
catch (Exception ex)
{
- _logger.LogError(ex, "Error getting image info for {name}", info.Name);
+ _logger.LogError(ex, "Error getting image info for {Name}", info.Name);
}
return null;
diff --git a/Emby.Server.Implementations/LiveTv/LiveTvManager.cs b/Emby.Server.Implementations/LiveTv/LiveTvManager.cs
index ea1a28fe8..aa3598c8b 100644
--- a/Emby.Server.Implementations/LiveTv/LiveTvManager.cs
+++ b/Emby.Server.Implementations/LiveTv/LiveTvManager.cs
@@ -33,8 +33,6 @@ using MediaBrowser.Model.LiveTv;
using MediaBrowser.Model.Querying;
using MediaBrowser.Model.Tasks;
using Microsoft.Extensions.Logging;
-using Episode = MediaBrowser.Controller.Entities.TV.Episode;
-using Movie = MediaBrowser.Controller.Entities.Movies.Movie;
namespace Emby.Server.Implementations.LiveTv
{
@@ -191,7 +189,7 @@ namespace Emby.Server.Implementations.LiveTv
IsKids = query.IsKids,
IsSports = query.IsSports,
IsSeries = query.IsSeries,
- IncludeItemTypes = new[] { nameof(LiveTvChannel) },
+ IncludeItemTypes = new[] { BaseItemKind.LiveTvChannel },
TopParentIds = new[] { topFolder.Id },
IsFavorite = query.IsFavorite,
IsLiked = query.IsLiked,
@@ -209,7 +207,7 @@ namespace Emby.Server.Implementations.LiveTv
orderBy.Insert(0, (ItemSortBy.IsFavoriteOrLiked, SortOrder.Descending));
}
- if (!internalQuery.OrderBy.Any(i => string.Equals(i.Item1, ItemSortBy.SortName, StringComparison.OrdinalIgnoreCase)))
+ if (!internalQuery.OrderBy.Any(i => string.Equals(i.OrderBy, ItemSortBy.SortName, StringComparison.OrdinalIgnoreCase)))
{
orderBy.Add((ItemSortBy.SortName, SortOrder.Ascending));
}
@@ -522,7 +520,7 @@ namespace Emby.Server.Implementations.LiveTv
return item;
}
- private (LiveTvProgram item, bool isNew, bool isUpdated) GetProgram(ProgramInfo info, Dictionary<Guid, LiveTvProgram> allExistingPrograms, LiveTvChannel channel)
+ private (LiveTvProgram Item, bool IsNew, bool IsUpdated) GetProgram(ProgramInfo info, Dictionary<Guid, LiveTvProgram> allExistingPrograms, LiveTvChannel channel)
{
var id = _tvDtoService.GetInternalProgramId(info.Id);
@@ -781,9 +779,9 @@ namespace Emby.Server.Implementations.LiveTv
var dto = _dtoService.GetBaseItemDto(program, new DtoOptions(), user);
- var list = new List<Tuple<BaseItemDto, string, string>>
+ var list = new List<(BaseItemDto ItemDto, string ExternalId, string ExternalSeriesId)>
{
- new Tuple<BaseItemDto, string, string>(dto, program.ExternalId, program.ExternalSeriesId)
+ (dto, program.ExternalId, program.ExternalSeriesId)
};
await AddRecordingInfo(list, cancellationToken).ConfigureAwait(false);
@@ -810,7 +808,7 @@ namespace Emby.Server.Implementations.LiveTv
var internalQuery = new InternalItemsQuery(user)
{
- IncludeItemTypes = new[] { nameof(LiveTvProgram) },
+ IncludeItemTypes = new[] { BaseItemKind.LiveTvProgram },
MinEndDate = query.MinEndDate,
MinStartDate = query.MinStartDate,
MaxEndDate = query.MaxEndDate,
@@ -874,7 +872,7 @@ namespace Emby.Server.Implementations.LiveTv
var internalQuery = new InternalItemsQuery(user)
{
- IncludeItemTypes = new[] { nameof(LiveTvProgram) },
+ IncludeItemTypes = new[] { BaseItemKind.LiveTvProgram },
IsAiring = query.IsAiring,
HasAired = query.HasAired,
IsNews = query.IsNews,
@@ -978,16 +976,16 @@ namespace Emby.Server.Implementations.LiveTv
return score;
}
- private async Task AddRecordingInfo(IEnumerable<Tuple<BaseItemDto, string, string>> programs, CancellationToken cancellationToken)
+ private async Task AddRecordingInfo(IEnumerable<(BaseItemDto ItemDto, string ExternalId, string ExternalSeriesId)> programs, CancellationToken cancellationToken)
{
IReadOnlyList<TimerInfo> timerList = null;
IReadOnlyList<SeriesTimerInfo> seriesTimerList = null;
foreach (var programTuple in programs)
{
- var program = programTuple.Item1;
- var externalProgramId = programTuple.Item2;
- string externalSeriesId = programTuple.Item3;
+ var program = programTuple.ItemDto;
+ var externalProgramId = programTuple.ExternalId;
+ string externalSeriesId = programTuple.ExternalSeriesId;
timerList ??= (await GetTimersInternal(new TimerQuery(), cancellationToken).ConfigureAwait(false)).Items;
@@ -1054,7 +1052,7 @@ namespace Emby.Server.Implementations.LiveTv
{
cancellationToken.ThrowIfCancellationRequested();
- _logger.LogDebug("Refreshing guide from {name}", service.Name);
+ _logger.LogDebug("Refreshing guide from {Name}", service.Name);
try
{
@@ -1085,8 +1083,8 @@ namespace Emby.Server.Implementations.LiveTv
if (cleanDatabase)
{
- CleanDatabaseInternal(newChannelIdList.ToArray(), new[] { nameof(LiveTvChannel) }, progress, cancellationToken);
- CleanDatabaseInternal(newProgramIdList.ToArray(), new[] { nameof(LiveTvProgram) }, progress, cancellationToken);
+ CleanDatabaseInternal(newChannelIdList.ToArray(), new[] { BaseItemKind.LiveTvChannel }, progress, cancellationToken);
+ CleanDatabaseInternal(newProgramIdList.ToArray(), new[] { BaseItemKind.LiveTvProgram }, progress, cancellationToken);
}
var coreService = _services.OfType<EmbyTV.EmbyTV>().FirstOrDefault();
@@ -1135,7 +1133,7 @@ namespace Emby.Server.Implementations.LiveTv
}
catch (Exception ex)
{
- _logger.LogError(ex, "Error getting channel information for {name}", channelInfo.Item2.Name);
+ _logger.LogError(ex, "Error getting channel information for {Name}", channelInfo.Item2.Name);
}
numComplete++;
@@ -1177,7 +1175,7 @@ namespace Emby.Server.Implementations.LiveTv
var existingPrograms = _libraryManager.GetItemList(new InternalItemsQuery
{
- IncludeItemTypes = new string[] { nameof(LiveTvProgram) },
+ IncludeItemTypes = new[] { BaseItemKind.LiveTvProgram },
ChannelIds = new Guid[] { currentChannel.Id },
DtoOptions = new DtoOptions(true)
}).Cast<LiveTvProgram>().ToDictionary(i => i.Id);
@@ -1188,13 +1186,13 @@ namespace Emby.Server.Implementations.LiveTv
foreach (var program in channelPrograms)
{
var programTuple = GetProgram(program, existingPrograms, currentChannel);
- var programItem = programTuple.item;
+ var programItem = programTuple.Item;
- if (programTuple.isNew)
+ if (programTuple.IsNew)
{
newPrograms.Add(programItem);
}
- else if (programTuple.isUpdated)
+ else if (programTuple.IsUpdated)
{
updatedPrograms.Add(programItem);
}
@@ -1248,7 +1246,7 @@ namespace Emby.Server.Implementations.LiveTv
}
catch (Exception ex)
{
- _logger.LogError(ex, "Error getting programs for channel {name}", currentChannel.Name);
+ _logger.LogError(ex, "Error getting programs for channel {Name}", currentChannel.Name);
}
numComplete++;
@@ -1261,7 +1259,7 @@ namespace Emby.Server.Implementations.LiveTv
return new Tuple<List<Guid>, List<Guid>>(channels, programs);
}
- private void CleanDatabaseInternal(Guid[] currentIdList, string[] validTypes, IProgress<double> progress, CancellationToken cancellationToken)
+ private void CleanDatabaseInternal(Guid[] currentIdList, BaseItemKind[] validTypes, IProgress<double> progress, CancellationToken cancellationToken)
{
var list = _itemRepo.GetItemIdsList(new InternalItemsQuery
{
@@ -1328,25 +1326,25 @@ namespace Emby.Server.Implementations.LiveTv
.Select(i => i.Id)
.ToList();
- var excludeItemTypes = new List<string>();
+ var excludeItemTypes = new List<BaseItemKind>();
if (folderIds.Count == 0)
{
return new QueryResult<BaseItem>();
}
- var includeItemTypes = new List<string>();
+ var includeItemTypes = new List<BaseItemKind>();
var genres = new List<string>();
if (query.IsMovie.HasValue)
{
if (query.IsMovie.Value)
{
- includeItemTypes.Add(nameof(Movie));
+ includeItemTypes.Add(BaseItemKind.Movie);
}
else
{
- excludeItemTypes.Add(nameof(Movie));
+ excludeItemTypes.Add(BaseItemKind.Movie);
}
}
@@ -1354,11 +1352,11 @@ namespace Emby.Server.Implementations.LiveTv
{
if (query.IsSeries.Value)
{
- includeItemTypes.Add(nameof(Episode));
+ includeItemTypes.Add(BaseItemKind.Episode);
}
else
{
- excludeItemTypes.Add(nameof(Episode));
+ excludeItemTypes.Add(BaseItemKind.Episode);
}
}
@@ -1425,9 +1423,9 @@ namespace Emby.Server.Implementations.LiveTv
return result;
}
- public Task AddInfoToProgramDto(IReadOnlyCollection<(BaseItem, BaseItemDto)> programs, IReadOnlyList<ItemFields> fields, User user = null)
+ public Task AddInfoToProgramDto(IReadOnlyCollection<(BaseItem Item, BaseItemDto ItemDto)> programs, IReadOnlyList<ItemFields> fields, User user = null)
{
- var programTuples = new List<Tuple<BaseItemDto, string, string>>();
+ var programTuples = new List<(BaseItemDto Dto, string ExternalId, string ExternalSeriesId)>();
var hasChannelImage = fields.Contains(ItemFields.ChannelImage);
var hasChannelInfo = fields.Contains(ItemFields.ChannelInfo);
@@ -1463,7 +1461,7 @@ namespace Emby.Server.Implementations.LiveTv
}
}
- programTuples.Add(new Tuple<BaseItemDto, string, string>(dto, program.ExternalId, program.ExternalSeriesId));
+ programTuples.Add((dto, program.ExternalId, program.ExternalSeriesId));
}
return AddRecordingInfo(programTuples, CancellationToken.None);
@@ -1870,15 +1868,15 @@ namespace Emby.Server.Implementations.LiveTv
return _libraryManager.GetItemById(internalChannelId);
}
- public void AddChannelInfo(IReadOnlyCollection<(BaseItemDto, LiveTvChannel)> items, DtoOptions options, User user)
+ public void AddChannelInfo(IReadOnlyCollection<(BaseItemDto ItemDto, LiveTvChannel Channel)> items, DtoOptions options, User user)
{
var now = DateTime.UtcNow;
- var channelIds = items.Select(i => i.Item2.Id).Distinct().ToArray();
+ var channelIds = items.Select(i => i.Channel.Id).Distinct().ToArray();
var programs = options.AddCurrentProgram ? _libraryManager.GetItemList(new InternalItemsQuery(user)
{
- IncludeItemTypes = new[] { nameof(LiveTvProgram) },
+ IncludeItemTypes = new[] { BaseItemKind.LiveTvProgram },
ChannelIds = channelIds,
MaxStartDate = now,
MinEndDate = now,
@@ -1895,11 +1893,8 @@ namespace Emby.Server.Implementations.LiveTv
var addCurrentProgram = options.AddCurrentProgram;
- foreach (var tuple in items)
+ foreach (var (dto, channel) in items)
{
- var dto = tuple.Item1;
- var channel = tuple.Item2;
-
dto.Number = channel.Number;
dto.ChannelNumber = channel.Number;
dto.ChannelType = channel.ChannelType;
diff --git a/Emby.Server.Implementations/LiveTv/LiveTvMediaSourceProvider.cs b/Emby.Server.Implementations/LiveTv/LiveTvMediaSourceProvider.cs
index ecd28097d..4b7584af3 100644
--- a/Emby.Server.Implementations/LiveTv/LiveTvMediaSourceProvider.cs
+++ b/Emby.Server.Implementations/LiveTv/LiveTvMediaSourceProvider.cs
@@ -104,7 +104,7 @@ namespace Emby.Server.Implementations.LiveTv
// Dummy this up so that direct play checks can still run
if (string.IsNullOrEmpty(source.Path) && source.Protocol == MediaProtocol.Http)
{
- source.Path = _appHost.GetSmartApiUrl(string.Empty);
+ source.Path = _appHost.GetApiUrlForLocalAccess();
}
}
diff --git a/Emby.Server.Implementations/LiveTv/TunerHosts/HdHomerun/HdHomerunChannelCommands.cs b/Emby.Server.Implementations/LiveTv/TunerHosts/HdHomerun/HdHomerunChannelCommands.cs
new file mode 100644
index 000000000..aae33503f
--- /dev/null
+++ b/Emby.Server.Implementations/LiveTv/TunerHosts/HdHomerun/HdHomerunChannelCommands.cs
@@ -0,0 +1,35 @@
+#pragma warning disable CS1591
+
+using System;
+using System.Collections.Generic;
+
+namespace Emby.Server.Implementations.LiveTv.TunerHosts.HdHomerun
+{
+ public class HdHomerunChannelCommands : IHdHomerunChannelCommands
+ {
+ private string? _channel;
+ private string? _profile;
+
+ public HdHomerunChannelCommands(string? channel, string? profile)
+ {
+ _channel = channel;
+ _profile = profile;
+ }
+
+ public IEnumerable<(string CommandName, string CommandValue)> GetCommands()
+ {
+ if (!string.IsNullOrEmpty(_channel))
+ {
+ if (!string.IsNullOrEmpty(_profile)
+ && !string.Equals(_profile, "native", StringComparison.OrdinalIgnoreCase))
+ {
+ yield return ("vchannel", $"{_channel} transcode={_profile}");
+ }
+ else
+ {
+ yield return ("vchannel", _channel);
+ }
+ }
+ }
+ }
+}
diff --git a/Emby.Server.Implementations/LiveTv/TunerHosts/HdHomerun/HdHomerunHost.cs b/Emby.Server.Implementations/LiveTv/TunerHosts/HdHomerun/HdHomerunHost.cs
index 4d538c604..532790019 100644
--- a/Emby.Server.Implementations/LiveTv/TunerHosts/HdHomerun/HdHomerunHost.cs
+++ b/Emby.Server.Implementations/LiveTv/TunerHosts/HdHomerun/HdHomerunHost.cs
@@ -87,11 +87,6 @@ namespace Emby.Server.Implementations.LiveTv.TunerHosts.HdHomerun
return lineup.Where(i => !i.DRM).ToList();
}
- private class HdHomerunChannelInfo : ChannelInfo
- {
- public bool IsLegacyTuner { get; set; }
- }
-
protected override async Task<List<ChannelInfo>> GetChannelsInternal(TunerHostInfo tuner, CancellationToken cancellationToken)
{
var lineup = await GetLineup(tuner, cancellationToken).ConfigureAwait(false);
@@ -635,7 +630,7 @@ namespace Emby.Server.Implementations.LiveTv.TunerHosts.HdHomerun
}
catch (HttpRequestException ex)
{
- if (ex.StatusCode.HasValue && ex.StatusCode.Value == System.Net.HttpStatusCode.NotFound)
+ if (ex.StatusCode.HasValue && ex.StatusCode.Value == HttpStatusCode.NotFound)
{
// HDHR4 doesn't have this api
return;
@@ -715,5 +710,10 @@ namespace Emby.Server.Implementations.LiveTv.TunerHosts.HdHomerun
return hostInfo;
}
+
+ private class HdHomerunChannelInfo : ChannelInfo
+ {
+ public bool IsLegacyTuner { get; set; }
+ }
}
}
diff --git a/Emby.Server.Implementations/LiveTv/TunerHosts/HdHomerun/HdHomerunManager.cs b/Emby.Server.Implementations/LiveTv/TunerHosts/HdHomerun/HdHomerunManager.cs
index b2e555c7d..f1a6ef344 100644
--- a/Emby.Server.Implementations/LiveTv/TunerHosts/HdHomerun/HdHomerunManager.cs
+++ b/Emby.Server.Implementations/LiveTv/TunerHosts/HdHomerun/HdHomerunManager.cs
@@ -5,12 +5,10 @@
using System;
using System.Buffers;
using System.Buffers.Binary;
-using System.Collections.Generic;
using System.Globalization;
using System.Net;
using System.Net.Sockets;
using System.Text;
-using System.Text.RegularExpressions;
using System.Threading;
using System.Threading.Tasks;
using MediaBrowser.Common;
@@ -18,70 +16,6 @@ using MediaBrowser.Controller.LiveTv;
namespace Emby.Server.Implementations.LiveTv.TunerHosts.HdHomerun
{
- public interface IHdHomerunChannelCommands
- {
- IEnumerable<(string, string)> GetCommands();
- }
-
- public class LegacyHdHomerunChannelCommands : IHdHomerunChannelCommands
- {
- private string _channel;
- private string _program;
-
- public LegacyHdHomerunChannelCommands(string url)
- {
- // parse url for channel and program
- var regExp = new Regex(@"\/ch([0-9]+)-?([0-9]*)");
- var match = regExp.Match(url);
- if (match.Success)
- {
- _channel = match.Groups[1].Value;
- _program = match.Groups[2].Value;
- }
- }
-
- public IEnumerable<(string, string)> GetCommands()
- {
- if (!string.IsNullOrEmpty(_channel))
- {
- yield return ("channel", _channel);
- }
-
- if (!string.IsNullOrEmpty(_program))
- {
- yield return ("program", _program);
- }
- }
- }
-
- public class HdHomerunChannelCommands : IHdHomerunChannelCommands
- {
- private string _channel;
- private string _profile;
-
- public HdHomerunChannelCommands(string channel, string profile)
- {
- _channel = channel;
- _profile = profile;
- }
-
- public IEnumerable<(string, string)> GetCommands()
- {
- if (!string.IsNullOrEmpty(_channel))
- {
- if (!string.IsNullOrEmpty(_profile)
- && !string.Equals(_profile, "native", StringComparison.OrdinalIgnoreCase))
- {
- yield return ("vchannel", $"{_channel} transcode={_profile}");
- }
- else
- {
- yield return ("vchannel", _channel);
- }
- }
- }
- }
-
public sealed class HdHomerunManager : IDisposable
{
public const int HdHomeRunPort = 65001;
@@ -117,7 +51,7 @@ namespace Emby.Server.Implementations.LiveTv.TunerHosts.HdHomerun
public async Task<bool> CheckTunerAvailability(IPAddress remoteIp, int tuner, CancellationToken cancellationToken)
{
using var client = new TcpClient();
- client.Connect(remoteIp, HdHomeRunPort);
+ await client.ConnectAsync(remoteIp, HdHomeRunPort).ConfigureAwait(false);
using var stream = client.GetStream();
return await CheckTunerAvailability(stream, tuner, cancellationToken).ConfigureAwait(false);
@@ -150,8 +84,7 @@ namespace Emby.Server.Implementations.LiveTv.TunerHosts.HdHomerun
if (!_lockkey.HasValue)
{
- var rand = new Random();
- _lockkey = (uint)rand.Next();
+ _lockkey = (uint)Random.Shared.Next();
}
var lockKeyValue = _lockkey.Value;
@@ -181,7 +114,7 @@ namespace Emby.Server.Implementations.LiveTv.TunerHosts.HdHomerun
foreach (var command in commands.GetCommands())
{
- var channelMsgLen = WriteSetMessage(buffer, i, command.Item1, command.Item2, lockKeyValue);
+ var channelMsgLen = WriteSetMessage(buffer, i, command.CommandName, command.CommandValue, lockKeyValue);
await stream.WriteAsync(buffer.AsMemory(0, channelMsgLen), cancellationToken).ConfigureAwait(false);
receivedBytes = await stream.ReadAsync(buffer, cancellationToken).ConfigureAwait(false);
@@ -189,7 +122,6 @@ namespace Emby.Server.Implementations.LiveTv.TunerHosts.HdHomerun
if (!TryGetReturnValueOfGetSet(buffer.AsSpan(0, receivedBytes), out _))
{
await ReleaseLockkey(_tcpClient, lockKeyValue).ConfigureAwait(false);
- continue;
}
}
@@ -235,7 +167,7 @@ namespace Emby.Server.Implementations.LiveTv.TunerHosts.HdHomerun
{
foreach (var command in commandList)
{
- var channelMsgLen = WriteSetMessage(buffer, _activeTuner, command.Item1, command.Item2, _lockkey);
+ var channelMsgLen = WriteSetMessage(buffer, _activeTuner, command.CommandName, command.CommandValue, _lockkey);
await stream.WriteAsync(buffer.AsMemory(0, channelMsgLen), cancellationToken).ConfigureAwait(false);
int receivedBytes = await stream.ReadAsync(buffer, cancellationToken).ConfigureAwait(false);
diff --git a/Emby.Server.Implementations/LiveTv/TunerHosts/HdHomerun/HdHomerunUdpStream.cs b/Emby.Server.Implementations/LiveTv/TunerHosts/HdHomerun/HdHomerunUdpStream.cs
index 31445e1ec..9ed0d8d73 100644
--- a/Emby.Server.Implementations/LiveTv/TunerHosts/HdHomerun/HdHomerunUdpStream.cs
+++ b/Emby.Server.Implementations/LiveTv/TunerHosts/HdHomerun/HdHomerunUdpStream.cs
@@ -3,7 +3,6 @@
#pragma warning disable CS1591
using System;
-using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Net;
@@ -82,10 +81,10 @@ namespace Emby.Server.Implementations.LiveTv.TunerHosts.HdHomerun
Directory.CreateDirectory(Path.GetDirectoryName(TempFilePath));
- Logger.LogInformation("Opening HDHR UDP Live stream from {host}", uri.Host);
+ Logger.LogInformation("Opening HDHR UDP Live stream from {Host}", uri.Host);
var remoteAddress = IPAddress.Parse(uri.Host);
- IPAddress localAddress = null;
+ IPAddress localAddress;
using (var tcpClient = new TcpClient())
{
try
@@ -147,7 +146,7 @@ namespace Emby.Server.Implementations.LiveTv.TunerHosts.HdHomerun
// OpenedMediaSource.Path = tempFile;
// OpenedMediaSource.ReadAtNativeFramerate = true;
- MediaSource.Path = _appHost.GetLoopbackHttpApiUrl() + "/LiveTv/LiveStreamFiles/" + UniqueId + "/stream.ts";
+ MediaSource.Path = _appHost.GetApiUrlForLocalAccess() + "/LiveTv/LiveStreamFiles/" + UniqueId + "/stream.ts";
MediaSource.Protocol = MediaProtocol.Http;
// OpenedMediaSource.SupportsDirectPlay = false;
// OpenedMediaSource.SupportsDirectStream = true;
@@ -213,7 +212,7 @@ namespace Emby.Server.Implementations.LiveTv.TunerHosts.HdHomerun
if (read > 0)
{
- fileStream.Write(buffer, RtpHeaderBytes, read);
+ await fileStream.WriteAsync(buffer.AsMemory(RtpHeaderBytes, read), linkedSource.Token).ConfigureAwait(false);
}
if (!resolved)
diff --git a/Emby.Server.Implementations/LiveTv/TunerHosts/HdHomerun/IHdHomerunChannelCommands.cs b/Emby.Server.Implementations/LiveTv/TunerHosts/HdHomerun/IHdHomerunChannelCommands.cs
new file mode 100644
index 000000000..11bd40ab1
--- /dev/null
+++ b/Emby.Server.Implementations/LiveTv/TunerHosts/HdHomerun/IHdHomerunChannelCommands.cs
@@ -0,0 +1,11 @@
+#pragma warning disable CS1591
+
+using System.Collections.Generic;
+
+namespace Emby.Server.Implementations.LiveTv.TunerHosts.HdHomerun
+{
+ public interface IHdHomerunChannelCommands
+ {
+ IEnumerable<(string CommandName, string CommandValue)> GetCommands();
+ }
+}
diff --git a/Emby.Server.Implementations/LiveTv/TunerHosts/HdHomerun/LegacyHdHomerunChannelCommands.cs b/Emby.Server.Implementations/LiveTv/TunerHosts/HdHomerun/LegacyHdHomerunChannelCommands.cs
new file mode 100644
index 000000000..80d9d0724
--- /dev/null
+++ b/Emby.Server.Implementations/LiveTv/TunerHosts/HdHomerun/LegacyHdHomerunChannelCommands.cs
@@ -0,0 +1,38 @@
+#pragma warning disable CS1591
+
+using System.Collections.Generic;
+using System.Text.RegularExpressions;
+
+namespace Emby.Server.Implementations.LiveTv.TunerHosts.HdHomerun
+{
+ public class LegacyHdHomerunChannelCommands : IHdHomerunChannelCommands
+ {
+ private string? _channel;
+ private string? _program;
+
+ public LegacyHdHomerunChannelCommands(string url)
+ {
+ // parse url for channel and program
+ var regExp = new Regex(@"\/ch([0-9]+)-?([0-9]*)");
+ var match = regExp.Match(url);
+ if (match.Success)
+ {
+ _channel = match.Groups[1].Value;
+ _program = match.Groups[2].Value;
+ }
+ }
+
+ public IEnumerable<(string CommandName, string CommandValue)> GetCommands()
+ {
+ if (!string.IsNullOrEmpty(_channel))
+ {
+ yield return ("channel", _channel);
+ }
+
+ if (!string.IsNullOrEmpty(_program))
+ {
+ yield return ("program", _program);
+ }
+ }
+ }
+}
diff --git a/Emby.Server.Implementations/LiveTv/TunerHosts/M3UTunerHost.cs b/Emby.Server.Implementations/LiveTv/TunerHosts/M3UTunerHost.cs
index 08b9260b9..dd83f9a53 100644
--- a/Emby.Server.Implementations/LiveTv/TunerHosts/M3UTunerHost.cs
+++ b/Emby.Server.Implementations/LiveTv/TunerHosts/M3UTunerHost.cs
@@ -10,6 +10,7 @@ using System.Linq;
using System.Net.Http;
using System.Threading;
using System.Threading.Tasks;
+using Jellyfin.Extensions;
using MediaBrowser.Common.Extensions;
using MediaBrowser.Common.Net;
using MediaBrowser.Controller;
@@ -119,7 +120,7 @@ namespace Emby.Server.Implementations.LiveTv.TunerHosts
{
var extension = Path.GetExtension(mediaSource.Path) ?? string.Empty;
- if (!_disallowedSharedStreamExtensions.Contains(extension, StringComparer.OrdinalIgnoreCase))
+ if (!_disallowedSharedStreamExtensions.Contains(extension, StringComparison.OrdinalIgnoreCase))
{
return new SharedHttpStream(mediaSource, tunerHost, streamId, FileSystem, _httpClientFactory, Logger, Config, _appHost, _streamHelper);
}
@@ -130,7 +131,7 @@ namespace Emby.Server.Implementations.LiveTv.TunerHosts
public async Task Validate(TunerHostInfo info)
{
- using (var stream = await new M3uParser(Logger, _httpClientFactory).GetListingsStream(info, CancellationToken.None).ConfigureAwait(false))
+ using (await new M3uParser(Logger, _httpClientFactory).GetListingsStream(info, CancellationToken.None).ConfigureAwait(false))
{
}
}
diff --git a/Emby.Server.Implementations/LiveTv/TunerHosts/M3uParser.cs b/Emby.Server.Implementations/LiveTv/TunerHosts/M3uParser.cs
index 506ef5548..708ff52d7 100644
--- a/Emby.Server.Implementations/LiveTv/TunerHosts/M3uParser.cs
+++ b/Emby.Server.Implementations/LiveTv/TunerHosts/M3uParser.cs
@@ -283,7 +283,7 @@ namespace Emby.Server.Implementations.LiveTv.TunerHosts
// #EXTINF:0,84.0 - VOX Schweiz
if (!string.IsNullOrWhiteSpace(nameInExtInf))
{
- var numberIndex = nameInExtInf.IndexOf(' ');
+ var numberIndex = nameInExtInf.IndexOf(' ', StringComparison.Ordinal);
if (numberIndex > 0)
{
var numberPart = nameInExtInf.Substring(0, numberIndex).Trim(new[] { ' ', '.' });
diff --git a/Emby.Server.Implementations/LiveTv/TunerHosts/SharedHttpStream.cs b/Emby.Server.Implementations/LiveTv/TunerHosts/SharedHttpStream.cs
index 3b69e55b0..b1ce7b2b3 100644
--- a/Emby.Server.Implementations/LiveTv/TunerHosts/SharedHttpStream.cs
+++ b/Emby.Server.Implementations/LiveTv/TunerHosts/SharedHttpStream.cs
@@ -83,7 +83,7 @@ namespace Emby.Server.Implementations.LiveTv.TunerHosts
// OpenedMediaSource.Path = tempFile;
// OpenedMediaSource.ReadAtNativeFramerate = true;
- MediaSource.Path = _appHost.GetLoopbackHttpApiUrl() + "/LiveTv/LiveStreamFiles/" + UniqueId + "/stream.ts";
+ MediaSource.Path = _appHost.GetApiUrlForLocalAccess() + "/LiveTv/LiveStreamFiles/" + UniqueId + "/stream.ts";
MediaSource.Protocol = MediaProtocol.Http;
// OpenedMediaSource.Path = TempFilePath;