aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/Jellyfin.LiveTv/Channels/ChannelManager.cs4
-rw-r--r--src/Jellyfin.LiveTv/Guide/GuideManager.cs19
-rw-r--r--src/Jellyfin.LiveTv/IO/EncodedRecorder.cs1
-rw-r--r--src/Jellyfin.LiveTv/Listings/SchedulesDirect.cs4
-rw-r--r--src/Jellyfin.LiveTv/Listings/XmlTvListingsProvider.cs5
-rw-r--r--src/Jellyfin.LiveTv/LiveTvChannelImageHelper.cs33
-rw-r--r--src/Jellyfin.MediaEncoding.Keyframes/FfProbe/FfProbeKeyframeExtractor.cs2
7 files changed, 47 insertions, 21 deletions
diff --git a/src/Jellyfin.LiveTv/Channels/ChannelManager.cs b/src/Jellyfin.LiveTv/Channels/ChannelManager.cs
index ed02fe6a1d..e421601092 100644
--- a/src/Jellyfin.LiveTv/Channels/ChannelManager.cs
+++ b/src/Jellyfin.LiveTv/Channels/ChannelManager.cs
@@ -14,6 +14,7 @@ using Jellyfin.Database.Implementations.Entities;
using Jellyfin.Database.Implementations.Enums;
using Jellyfin.Extensions;
using Jellyfin.Extensions.Json;
+using Jellyfin.LiveTv;
using MediaBrowser.Common.Extensions;
using MediaBrowser.Controller.Channels;
using MediaBrowser.Controller.Configuration;
@@ -1109,9 +1110,8 @@ namespace Jellyfin.LiveTv.Channels
item.Path = mediaSource?.Path;
}
- if (!string.IsNullOrEmpty(info.ImageUrl) && !item.HasImage(ImageType.Primary))
+ if (LiveTvChannelImageHelper.UpdateChannelImageIfNeeded(item, null, info.ImageUrl))
{
- item.SetImagePath(ImageType.Primary, info.ImageUrl);
_logger.LogDebug("Forcing update due to ImageUrl {0}", item.Name);
forceUpdate = true;
}
diff --git a/src/Jellyfin.LiveTv/Guide/GuideManager.cs b/src/Jellyfin.LiveTv/Guide/GuideManager.cs
index c3cc70381e..b8545cbb64 100644
--- a/src/Jellyfin.LiveTv/Guide/GuideManager.cs
+++ b/src/Jellyfin.LiveTv/Guide/GuideManager.cs
@@ -5,6 +5,7 @@ using System.Threading;
using System.Threading.Tasks;
using Jellyfin.Data.Enums;
using Jellyfin.Extensions;
+using Jellyfin.LiveTv;
using Jellyfin.LiveTv.Configuration;
using MediaBrowser.Common.Configuration;
using MediaBrowser.Controller.Dto;
@@ -448,23 +449,9 @@ public class GuideManager : IGuideManager
item.Name = channelInfo.Name;
- var currentPrimary = item.GetImageInfo(ImageType.Primary, 0);
- var imageUrlIsNull = string.IsNullOrWhiteSpace(channelInfo.ImageUrl);
-
- // Update channel image if image URL has changed
- if (currentPrimary is null
- || (!imageUrlIsNull && !string.Equals(currentPrimary.Path, channelInfo.ImageUrl, StringComparison.Ordinal)))
+ if (LiveTvChannelImageHelper.UpdateChannelImageIfNeeded(item, channelInfo.ImagePath, channelInfo.ImageUrl))
{
- if (!string.IsNullOrWhiteSpace(channelInfo.ImagePath))
- {
- item.SetImagePath(ImageType.Primary, channelInfo.ImagePath);
- forceUpdate = true;
- }
- else if (!imageUrlIsNull)
- {
- item.SetImagePath(ImageType.Primary, channelInfo.ImageUrl);
- forceUpdate = true;
- }
+ forceUpdate = true;
}
if (isNew)
diff --git a/src/Jellyfin.LiveTv/IO/EncodedRecorder.cs b/src/Jellyfin.LiveTv/IO/EncodedRecorder.cs
index d877a0d124..19c4514766 100644
--- a/src/Jellyfin.LiveTv/IO/EncodedRecorder.cs
+++ b/src/Jellyfin.LiveTv/IO/EncodedRecorder.cs
@@ -83,6 +83,7 @@ namespace Jellyfin.LiveTv.IO
CreateNoWindow = true,
UseShellExecute = false,
+ StandardErrorEncoding = Encoding.UTF8,
RedirectStandardError = true,
RedirectStandardInput = true,
diff --git a/src/Jellyfin.LiveTv/Listings/SchedulesDirect.cs b/src/Jellyfin.LiveTv/Listings/SchedulesDirect.cs
index c1ccb24bf4..d456bea469 100644
--- a/src/Jellyfin.LiveTv/Listings/SchedulesDirect.cs
+++ b/src/Jellyfin.LiveTv/Listings/SchedulesDirect.cs
@@ -748,9 +748,7 @@ namespace Jellyfin.LiveTv.Listings
#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();
+ string hashedPassword = Convert.ToHexStringLower(hashedPasswordBytes);
options.Content = new StringContent("{\"username\":\"" + username + "\",\"password\":\"" + hashedPassword + "\"}", Encoding.UTF8, MediaTypeNames.Application.Json);
var root = await Request<TokenDto>(options, false, null, cancellationToken).ConfigureAwait(false);
diff --git a/src/Jellyfin.LiveTv/Listings/XmlTvListingsProvider.cs b/src/Jellyfin.LiveTv/Listings/XmlTvListingsProvider.cs
index ec2e6cfcc9..7088d1f0bf 100644
--- a/src/Jellyfin.LiveTv/Listings/XmlTvListingsProvider.cs
+++ b/src/Jellyfin.LiveTv/Listings/XmlTvListingsProvider.cs
@@ -12,6 +12,7 @@ using System.Threading.Tasks;
using Jellyfin.Extensions;
using Jellyfin.XmlTv;
using Jellyfin.XmlTv.Entities;
+using Jellyfin.XmlTv.Enums;
using MediaBrowser.Common.Extensions;
using MediaBrowser.Common.Net;
using MediaBrowser.Controller.Configuration;
@@ -180,6 +181,8 @@ namespace Jellyfin.LiveTv.Listings
string? episodeTitle = program.Episode?.Title;
var programCategories = program.Categories.Where(c => !string.IsNullOrWhiteSpace(c)).ToList();
var imageUrl = program.Icons.FirstOrDefault()?.Source;
+ var episodeImageUrl = program.Images?.FirstOrDefault(m => m.Type == ImageType.Still)?.Path;
+ var backgroundImageUrl = program.Images?.FirstOrDefault(m => m.Type == ImageType.Backdrop)?.Path;
var rating = program.Ratings.FirstOrDefault()?.Value;
var starRating = program.StarRatings?.FirstOrDefault()?.StarRating;
@@ -205,6 +208,8 @@ namespace Jellyfin.LiveTv.Listings
IsSports = programCategories.Any(c => info.SportsCategories.Contains(c, StringComparison.OrdinalIgnoreCase)),
ImageUrl = string.IsNullOrEmpty(imageUrl) ? null : imageUrl,
HasImage = !string.IsNullOrEmpty(imageUrl),
+ BackdropImageUrl = string.IsNullOrEmpty(backgroundImageUrl) ? null : backgroundImageUrl,
+ ThumbImageUrl = string.IsNullOrEmpty(episodeImageUrl) ? null : episodeImageUrl,
OfficialRating = string.IsNullOrEmpty(rating) ? null : rating,
CommunityRating = starRating is null ? null : (float)starRating.Value,
SeriesId = program.Episode?.Episode is null ? null : program.Title?.GetMD5().ToString("N", CultureInfo.InvariantCulture)
diff --git a/src/Jellyfin.LiveTv/LiveTvChannelImageHelper.cs b/src/Jellyfin.LiveTv/LiveTvChannelImageHelper.cs
new file mode 100644
index 0000000000..a590193b5f
--- /dev/null
+++ b/src/Jellyfin.LiveTv/LiveTvChannelImageHelper.cs
@@ -0,0 +1,33 @@
+using MediaBrowser.Controller.Entities;
+using MediaBrowser.Model.Entities;
+
+namespace Jellyfin.LiveTv;
+
+/// <summary>
+/// Helpers for keeping Live TV channel icons in sync with guide data.
+/// </summary>
+internal static class LiveTvChannelImageHelper
+{
+ /// <summary>
+ /// Applies the channel icon from guide or tuner metadata.
+ /// Called on each guide refresh so remote icons are re-downloaded even when the URL is unchanged.
+ /// </summary>
+ /// <param name="item">The channel item.</param>
+ /// <param name="imagePath">The local image path from the tuner, if any.</param>
+ /// <param name="imageUrl">The remote image URL from the guide provider, if any.</param>
+ /// <returns><c>true</c> when the item image metadata was updated.</returns>
+ internal static bool UpdateChannelImageIfNeeded(BaseItem item, string? imagePath, string? imageUrl)
+ {
+ var newImageSource = !string.IsNullOrWhiteSpace(imagePath)
+ ? imagePath
+ : imageUrl;
+
+ if (string.IsNullOrWhiteSpace(newImageSource))
+ {
+ return false;
+ }
+
+ item.SetImagePath(ImageType.Primary, newImageSource);
+ return true;
+ }
+}
diff --git a/src/Jellyfin.MediaEncoding.Keyframes/FfProbe/FfProbeKeyframeExtractor.cs b/src/Jellyfin.MediaEncoding.Keyframes/FfProbe/FfProbeKeyframeExtractor.cs
index cbe97a8210..af868e4bd6 100644
--- a/src/Jellyfin.MediaEncoding.Keyframes/FfProbe/FfProbeKeyframeExtractor.cs
+++ b/src/Jellyfin.MediaEncoding.Keyframes/FfProbe/FfProbeKeyframeExtractor.cs
@@ -3,6 +3,7 @@ using System.Collections.Generic;
using System.Diagnostics;
using System.Globalization;
using System.IO;
+using System.Text;
namespace Jellyfin.MediaEncoding.Keyframes.FfProbe;
@@ -31,6 +32,7 @@ public static class FfProbeKeyframeExtractor
CreateNoWindow = true,
UseShellExecute = false,
+ StandardOutputEncoding = Encoding.UTF8,
RedirectStandardOutput = true,
WindowStyle = ProcessWindowStyle.Hidden,