aboutsummaryrefslogtreecommitdiff
path: root/MediaBrowser.Providers
diff options
context:
space:
mode:
Diffstat (limited to 'MediaBrowser.Providers')
-rw-r--r--MediaBrowser.Providers/Lyric/LrcLyricParser.cs45
-rw-r--r--MediaBrowser.Providers/Lyric/LyricManager.cs3
-rw-r--r--MediaBrowser.Providers/Lyric/LyricScheduledTask.cs3
-rw-r--r--MediaBrowser.Providers/Manager/MetadataService.cs1
-rw-r--r--MediaBrowser.Providers/MediaInfo/AudioFileProber.cs4
-rw-r--r--MediaBrowser.Providers/Plugins/Tmdb/TmdbExternalUrlProvider.cs19
-rw-r--r--MediaBrowser.Providers/TV/SeriesMetadataService.cs2
7 files changed, 59 insertions, 18 deletions
diff --git a/MediaBrowser.Providers/Lyric/LrcLyricParser.cs b/MediaBrowser.Providers/Lyric/LrcLyricParser.cs
index fffdf4887..27d17b535 100644
--- a/MediaBrowser.Providers/Lyric/LrcLyricParser.cs
+++ b/MediaBrowser.Providers/Lyric/LrcLyricParser.cs
@@ -2,6 +2,7 @@ using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
+using System.Text.RegularExpressions;
using Jellyfin.Extensions;
using LrcParser.Model;
using LrcParser.Parser;
@@ -14,7 +15,7 @@ namespace MediaBrowser.Providers.Lyric;
/// <summary>
/// LRC Lyric Parser.
/// </summary>
-public class LrcLyricParser : ILyricParser
+public partial class LrcLyricParser : ILyricParser
{
private readonly LyricParser _lrcLyricParser;
@@ -65,13 +66,47 @@ public class LrcLyricParser : ILyricParser
}
List<LyricLine> lyricList = [];
-
- for (int i = 0; i < sortedLyricData.Count; i++)
+ for (var l = 0; l < sortedLyricData.Count; l++)
{
- long ticks = TimeSpan.FromMilliseconds(sortedLyricData[i].StartTime).Ticks;
- lyricList.Add(new LyricLine(sortedLyricData[i].Text.Trim(), ticks));
+ var cues = new List<LyricLineCue>();
+ var lyric = sortedLyricData[l];
+
+ if (lyric.TimeTags.Count != 0)
+ {
+ var keys = lyric.TimeTags.Keys.ToList();
+ int current = 0, next = 1;
+ while (next < keys.Count)
+ {
+ var currentKey = keys[current];
+ var currentMs = lyric.TimeTags[currentKey] ?? 0;
+ var nextMs = lyric.TimeTags[keys[next]] ?? 0;
+
+ cues.Add(new LyricLineCue(
+ position: Math.Max(currentKey.Index, 0),
+ start: TimeSpan.FromMilliseconds(currentMs).Ticks,
+ end: TimeSpan.FromMilliseconds(nextMs).Ticks));
+
+ current++;
+ next++;
+ }
+
+ var lastKey = keys[current];
+ var lastMs = lyric.TimeTags[lastKey] ?? 0;
+
+ cues.Add(new LyricLineCue(
+ position: Math.Max(lastKey.Index, 0),
+ start: TimeSpan.FromMilliseconds(lastMs).Ticks,
+ end: l + 1 < sortedLyricData.Count ? TimeSpan.FromMilliseconds(sortedLyricData[l + 1].StartTime).Ticks : null));
+ }
+
+ long lyricStartTicks = TimeSpan.FromMilliseconds(lyric.StartTime).Ticks;
+ lyricList.Add(new LyricLine(WhitespaceRegex().Replace(lyric.Text.Trim(), " "), lyricStartTicks, cues));
}
return new LyricDto { Lyrics = lyricList };
}
+
+ // Replacement is required until https://github.com/karaoke-dev/LrcParser/issues/83 is resolved.
+ [GeneratedRegex(@"\s+")]
+ private static partial Regex WhitespaceRegex();
}
diff --git a/MediaBrowser.Providers/Lyric/LyricManager.cs b/MediaBrowser.Providers/Lyric/LyricManager.cs
index f4b18a8c1..913a104a0 100644
--- a/MediaBrowser.Providers/Lyric/LyricManager.cs
+++ b/MediaBrowser.Providers/Lyric/LyricManager.cs
@@ -78,7 +78,8 @@ public class LyricManager : ILyricManager
MediaPath = audio.Path,
SongName = audio.Name,
AlbumName = audio.Album,
- ArtistNames = audio.GetAllArtists().ToList(),
+ AlbumArtistsNames = audio.AlbumArtists,
+ ArtistNames = audio.Artists,
Duration = audio.RunTimeTicks,
IsAutomated = isAutomated
};
diff --git a/MediaBrowser.Providers/Lyric/LyricScheduledTask.cs b/MediaBrowser.Providers/Lyric/LyricScheduledTask.cs
index 73912b579..b8861ee5e 100644
--- a/MediaBrowser.Providers/Lyric/LyricScheduledTask.cs
+++ b/MediaBrowser.Providers/Lyric/LyricScheduledTask.cs
@@ -117,7 +117,8 @@ public class LyricScheduledTask : IScheduledTask
MediaPath = audioItem.Path,
SongName = audioItem.Name,
AlbumName = audioItem.Album,
- ArtistNames = audioItem.GetAllArtists().ToList(),
+ AlbumArtistsNames = audioItem.AlbumArtists,
+ ArtistNames = audioItem.Artists,
Duration = audioItem.RunTimeTicks,
IsAutomated = true,
DisabledLyricFetchers = libraryOptions.DisabledLyricFetchers,
diff --git a/MediaBrowser.Providers/Manager/MetadataService.cs b/MediaBrowser.Providers/Manager/MetadataService.cs
index e8994693d..45f66f85f 100644
--- a/MediaBrowser.Providers/Manager/MetadataService.cs
+++ b/MediaBrowser.Providers/Manager/MetadataService.cs
@@ -193,6 +193,7 @@ namespace MediaBrowser.Providers.Manager
if (hasRefreshedMetadata && hasRefreshedImages)
{
item.DateLastRefreshed = DateTime.UtcNow;
+ updateType |= item.OnMetadataChanged();
}
updateType = await SaveInternal(item, refreshOptions, updateType, isFirstRefresh, requiresRefresh, metadataResult, cancellationToken).ConfigureAwait(false);
diff --git a/MediaBrowser.Providers/MediaInfo/AudioFileProber.cs b/MediaBrowser.Providers/MediaInfo/AudioFileProber.cs
index 916e2625b..0bb21b287 100644
--- a/MediaBrowser.Providers/MediaInfo/AudioFileProber.cs
+++ b/MediaBrowser.Providers/MediaInfo/AudioFileProber.cs
@@ -180,8 +180,8 @@ namespace MediaBrowser.Providers.MediaInfo
// That setter is meant for its own tag parser and external editor usage and will have unwanted side effects
// For example, setting the Year property will also set the Date property, which is not what we want here.
// To properly handle fallback values, we make a clone of those fields when valid.
- var trackTitle = (string.IsNullOrEmpty(track.Title) ? mediaInfo.Name : track.Title).Trim();
- var trackAlbum = (string.IsNullOrEmpty(track.Album) ? mediaInfo.Album : track.Album).Trim();
+ var trackTitle = (string.IsNullOrEmpty(track.Title) ? mediaInfo.Name : track.Title)?.Trim();
+ var trackAlbum = (string.IsNullOrEmpty(track.Album) ? mediaInfo.Album : track.Album)?.Trim();
var trackYear = track.Year is null or 0 ? mediaInfo.ProductionYear : track.Year;
var trackTrackNumber = track.TrackNumber is null or 0 ? mediaInfo.IndexNumber : track.TrackNumber;
var trackDiscNumber = track.DiscNumber is null or 0 ? mediaInfo.ParentIndexNumber : track.DiscNumber;
diff --git a/MediaBrowser.Providers/Plugins/Tmdb/TmdbExternalUrlProvider.cs b/MediaBrowser.Providers/Plugins/Tmdb/TmdbExternalUrlProvider.cs
index bec800c03..27e3f93a3 100644
--- a/MediaBrowser.Providers/Plugins/Tmdb/TmdbExternalUrlProvider.cs
+++ b/MediaBrowser.Providers/Plugins/Tmdb/TmdbExternalUrlProvider.cs
@@ -33,17 +33,18 @@ public class TmdbExternalUrlProvider : IExternalUrlProvider
if (season.Series.TryGetProviderId(MetadataProvider.Tmdb, out var seriesExternalId))
{
var orderString = season.Series.DisplayOrder;
- if (string.IsNullOrEmpty(orderString))
+ var seasonNumber = season.IndexNumber;
+ if (string.IsNullOrEmpty(orderString) && seasonNumber is not null)
{
// Default order is airdate
- yield return TmdbUtils.BaseTmdbUrl + $"tv/{seriesExternalId}/season/{season.IndexNumber}";
+ yield return TmdbUtils.BaseTmdbUrl + $"tv/{seriesExternalId}/season/{seasonNumber}";
}
if (Enum.TryParse<TvGroupType>(season.Series.DisplayOrder, out var order))
{
- if (order.Equals(TvGroupType.OriginalAirDate))
+ if (order.Equals(TvGroupType.OriginalAirDate) && seasonNumber is not null)
{
- yield return TmdbUtils.BaseTmdbUrl + $"tv/{seriesExternalId}/season/{season.IndexNumber}";
+ yield return TmdbUtils.BaseTmdbUrl + $"tv/{seriesExternalId}/season/{seasonNumber}";
}
}
}
@@ -53,17 +54,19 @@ public class TmdbExternalUrlProvider : IExternalUrlProvider
if (episode.Series.TryGetProviderId(MetadataProvider.Imdb, out seriesExternalId))
{
var orderString = episode.Series.DisplayOrder;
- if (string.IsNullOrEmpty(orderString))
+ var seasonNumber = episode.Season?.IndexNumber;
+ var episodeNumber = episode.IndexNumber;
+ if (string.IsNullOrEmpty(orderString) && seasonNumber is not null && episodeNumber is not null)
{
// Default order is airdate
- yield return TmdbUtils.BaseTmdbUrl + $"tv/{seriesExternalId}/season/{episode.Season.IndexNumber}/episode/{episode.IndexNumber}";
+ yield return TmdbUtils.BaseTmdbUrl + $"tv/{seriesExternalId}/season/{seasonNumber}/episode/{episodeNumber}";
}
if (Enum.TryParse<TvGroupType>(orderString, out var order))
{
- if (order.Equals(TvGroupType.OriginalAirDate))
+ if (order.Equals(TvGroupType.OriginalAirDate) && seasonNumber is not null && episodeNumber is not null)
{
- yield return TmdbUtils.BaseTmdbUrl + $"tv/{seriesExternalId}/season/{episode.Season.IndexNumber}/episode/{episode.IndexNumber}";
+ yield return TmdbUtils.BaseTmdbUrl + $"tv/{seriesExternalId}/season/{seasonNumber}/episode/{episodeNumber}";
}
}
}
diff --git a/MediaBrowser.Providers/TV/SeriesMetadataService.cs b/MediaBrowser.Providers/TV/SeriesMetadataService.cs
index 284415dce..42d59d348 100644
--- a/MediaBrowser.Providers/TV/SeriesMetadataService.cs
+++ b/MediaBrowser.Providers/TV/SeriesMetadataService.cs
@@ -55,7 +55,7 @@ namespace MediaBrowser.Providers.TV
foreach (var season in seasons)
{
- var hasUpdate = refreshOptions != null && season.BeforeMetadataRefresh(refreshOptions.ReplaceAllMetadata);
+ var hasUpdate = refreshOptions is not null && season.BeforeMetadataRefresh(refreshOptions.ReplaceAllMetadata);
if (hasUpdate)
{
await season.UpdateToRepositoryAsync(ItemUpdateType.MetadataEdit, cancellationToken).ConfigureAwait(false);